File Coverage

lib/Rex/Interface/Exec/Sudo.pm
Criterion Covered Total %
statement 32 104 30.7
branch 0 34 0.0
condition 0 3 0.0
subroutine 11 14 78.5
pod 0 2 0.0
total 43 157 27.3


line stmt bran cond sub pod time code
1             #
2             # (c) Jan Gehring
3             #
4              
5             package Rex::Interface::Exec::Sudo;
6              
7 1     1   15 use v5.12.5;
  1         4  
8 1     1   5 use warnings;
  1         3  
  1         40  
9              
10             our $VERSION = '1.14.2.3'; # TRIAL VERSION
11              
12 1     1   9 use Rex::Config;
  1         4  
  1         7  
13 1     1   12 use Rex::Interface::Exec::Local;
  1         2  
  1         10  
14 1     1   37 use Rex::Interface::Exec::SSH;
  1         3  
  1         9  
15 1     1   29 use Rex::Helper::Encode;
  1         2  
  1         49  
16 1     1   6 use Rex::Interface::File::Local;
  1         3  
  1         9  
17 1     1   27 use Rex::Interface::File::SSH;
  1         3  
  1         9  
18              
19 1     1   29 use Rex::Commands;
  1         3  
  1         11  
20 1     1   11 use Rex::Helper::Path;
  1         3  
  1         95  
21              
22 1     1   27 use base 'Rex::Interface::Exec::Base';
  1         5  
  1         937  
23              
24             sub new {
25 0     0 0   my $that = shift;
26 0   0       my $proto = ref($that) || $that;
27 0           my $self = {@_};
28              
29 0           bless( $self, $proto );
30              
31 0           return $self;
32             }
33              
34             sub exec {
35 0     0 0   my ( $self, $cmd, $path, $option ) = @_;
36              
37 0 0         if ( exists $option->{cwd} ) {
38 0           $cmd = "cd " . $option->{cwd} . " && $cmd";
39             }
40              
41 0 0         if ( exists $option->{path} ) {
42 0           $path = $option->{path};
43             }
44              
45 0           my ( $exec, $file, $shell );
46 0 0         if ( my $ssh = Rex::is_ssh() ) {
47 0 0         if ( ref $ssh eq "Net::OpenSSH" ) {
48 0           $exec = Rex::Interface::Exec->create("OpenSSH");
49 0           $file = Rex::Interface::File->create("OpenSSH");
50             }
51             else {
52 0           $exec = Rex::Interface::Exec->create("SSH");
53 0           $file = Rex::Interface::File->create("SSH");
54             }
55             }
56             else {
57 0           $exec = Rex::Interface::Exec->create("Local");
58 0           $file = Rex::Interface::File->create("Local");
59             }
60 0           $shell = Rex::Interface::Shell->create("Sh"); # we're using sh for sudo
61              
62             ######## envs setzen. aber erst nachdem wir wissen ob wir sh forcen duerfen
63             # if(exists $option->{env}) {
64             # $shell->set_environment($option->{env});
65             # }
66              
67 0 0         my $sudo_password = (
68             defined task() ? task->get_sudo_password : Rex::Config->get_sudo_password );
69 0           my $enc_pw;
70 0           my $random_file = "";
71              
72 0           Rex::Logger::debug("Sudo: Executing: $cmd");
73              
74 0 0         if ($sudo_password) {
75 0           my $random_string = get_random( length($sudo_password), 'a' .. 'z' );
76 0           my $crypt = $sudo_password ^ $random_string;
77              
78 0           $random_file = get_tmp_file;
79              
80 0           $file->open( '>', $random_file );
81 0           $file->write(<
82             #!/usr/bin/perl
83             unlink \$0;
84              
85             for (0..255) {
86             \$escapes{chr(\$_)} = sprintf("%%%02X", \$_);
87             }
88              
89             my \$txt = \$ARGV[0];
90              
91             \$txt=~ s/%([0-9A-Fa-f]{2})/chr(hex(\$1))/eg;
92              
93             my \$rnd = '$random_string';
94             print \$txt ^ \$rnd;
95             print "\\n"
96              
97             EOF
98              
99 0           $file->close;
100              
101 0           $enc_pw = Rex::Helper::Encode::url_encode($crypt);
102             }
103             else {
104 0           $enc_pw = "";
105             }
106              
107             #my $sudo_options = Rex::get_current_connection()->{sudo_options};
108 0           my $sudo_options =
109             Rex::get_current_connection_object()->get_current_sudo_options;
110 0           my $sudo_options_str = "";
111 0 0         if ( exists $sudo_options->{user} ) {
112 0           $sudo_options_str .= " -u " . $sudo_options->{user};
113             }
114              
115 0 0         if ( Rex::Config->get_sudo_without_locales() ) {
116 0           Rex::Logger::debug(
117             "Using sudo without locales. If the locale is NOT C or en_US it will break many things!"
118             );
119 0           $option->{no_locales} = 1;
120             }
121              
122 0           my $sudo_command = "sudo $sudo_options_str -p '' -S";
123              
124 0 0         if ( Rex::Config->get_sudo_without_sh() ) {
125 0           Rex::Logger::debug(
126             "Using sudo without sh will break things like file editing.");
127              
128             # $option->{no_sh} = 1;
129 0           $shell->set_inner_shell(0);
130 0           $shell->set_sudo_env(1);
131              
132 0 0         if ( exists $option->{env} ) {
133 0           $shell->set_environment( $option->{env} );
134             }
135              
136 0 0         if ($enc_pw) {
137              
138             # $option->{format_cmd} =
139             # "perl $random_file '$enc_pw' | sudo $sudo_options_str -p '' -S {{CMD}}";
140 0           $sudo_command = "perl $random_file '$enc_pw' 2>/dev/null | $sudo_command";
141             }
142              
143             # else {
144             # $option->{format_cmd} = "sudo $sudo_options_str -p '' -S {{CMD}}";
145             # }
146             }
147             else {
148              
149 0           $shell->set_locale("C");
150 0           $shell->path($path);
151              
152 0 0         if ( Rex::Config->get_source_global_profile ) {
153 0           $shell->source_global_profile(1);
154             }
155              
156 0 0         if ( Rex::Config->get_source_profile ) {
157 0           $shell->source_profile(1);
158             }
159              
160 0 0         if ( exists $option->{env} ) {
161 0           $shell->set_environment( $option->{env} );
162             }
163              
164             # escape some special shell things
165             # $option->{preprocess_command} = sub {
166             # my ($_cmd) = @_;
167             # $_cmd =~ s/\\/\\\\/gms;
168             # $_cmd =~ s/"/\\"/gms;
169             # $_cmd =~ s/\$/\\\$/gms;
170             # };
171              
172 0           $shell->set_inner_shell(1);
173              
174             # $cmd =~ s/\\/\\\\/gms;
175             # $cmd =~ s/"/\\"/gms;
176             # $cmd =~ s/\$/\\\$/gms;
177              
178             # Calling sudo with sh(1) in this case we don't need to respect current user shell, pass _force_sh flag to ssh layer
179             # $option->{_force_sh} = 1;
180              
181 0 0         if ($enc_pw) {
182 0           $sudo_command = "perl $random_file '$enc_pw' 2>/dev/null | $sudo_command";
183              
184             # $option->{format_cmd} =
185             # "perl $random_file '$enc_pw' | sudo $sudo_options_str -p '' -S sh -c \"{{CMD}}\"";
186             }
187              
188             # else {
189             # $option->{format_cmd} =
190             # "sudo $sudo_options_str -p '' -S sh -c \"{{CMD}}\"";
191             # }
192             }
193              
194 0           $option->{prepend_command} = $sudo_command;
195              
196 0           my $real_exec = $shell->exec( $cmd, $option );
197 0           Rex::Logger::debug("sudo: exec: $real_exec");
198              
199 0           return $exec->direct_exec( $real_exec, $option );
200             }
201              
202             sub _exec {
203 0     0     my ( $self, $cmd, $path, $option ) = @_;
204              
205 0           my ( $exec, $file, $shell );
206 0 0         if ( my $ssh = Rex::is_ssh() ) {
207 0 0         if ( ref $ssh eq "Net::OpenSSH" ) {
208 0           $exec = Rex::Interface::Exec->create("OpenSSH");
209             }
210             else {
211 0           $exec = Rex::Interface::Exec->create("SSH");
212             }
213             }
214             else {
215 0           $exec = Rex::Interface::Exec->create("Local");
216             }
217              
218 0           return $exec->_exec( $cmd, $option );
219             }
220              
221             1;