From 188cab5ec03330e4ff45bb0a4b20cadf2a23551d Mon Sep 17 00:00:00 2001 From: Digimer Date: Tue, 24 Apr 2018 13:32:19 -0400 Subject: [PATCH] * Fixed a few bugs with how rsync is handled, specifically in the rsync wrapper script. * Fixed a bug with handling ssh fingerprints (and removed comments going to the known_hosts file). * Added more nested debug parameter passing when methods call other methods (though more work is needed to catch up) Signed-off-by: Digimer --- Anvil/Tools.pm | 3 ++- Anvil/Tools/Get.pm | 2 +- Anvil/Tools/Remote.pm | 28 +++++++++++++++------- Anvil/Tools/Storage.pm | 45 +++++++++++++++++++++-------------- share/words.xml | 3 ++- tools/anvil-configure-network | 13 ++++++++++ 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index da1f521d..94596413 100755 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -785,6 +785,7 @@ sub _set_paths expect => "/usr/bin/expect", 'firewall-cmd' => "/usr/bin/firewall-cmd", gethostip => "/usr/bin/gethostip", + 'grep' => "/usr/bin/grep", head => "/usr/bin/head", hostname => "/usr/bin/hostname", hostnamectl => "/usr/bin/hostnamectl", @@ -807,7 +808,7 @@ sub _set_paths rsync => "/usr/bin/rsync", sed => "/usr/bin/sed", 'shutdown' => "/usr/sbin/shutdown", - 'ssh-keyscan' => "/usr/bin/ssh-keygen", + 'ssh-keyscan' => "/usr/bin/ssh-keyscan", strings => "/usr/bin/strings", stty => "/usr/bin/stty", su => "/usr/bin/su", diff --git a/Anvil/Tools/Get.pm b/Anvil/Tools/Get.pm index ddd18143..88382ce1 100755 --- a/Anvil/Tools/Get.pm +++ b/Anvil/Tools/Get.pm @@ -715,7 +715,7 @@ sub users_home my $home_directory = 0; - my $user = $parameter->{user} ? $parameter->{user} : ""; + my $user = defined $parameter->{user} ? $parameter->{user} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { user => $user }}); # Make sure the user is only one digit. Sometimes $< (and others) will return multiple IDs. diff --git a/Anvil/Tools/Remote.pm b/Anvil/Tools/Remote.pm index e3b8714f..edd00b9e 100755 --- a/Anvil/Tools/Remote.pm +++ b/Anvil/Tools/Remote.pm @@ -124,7 +124,7 @@ sub add_target_to_known_hosts }}); # Get the local user's home - my $users_home = $anvil->Get->users_home({user => $user}); + my $users_home = $anvil->Get->users_home({debug => $debug, user => $user}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { users_home => $users_home }}); if (not $users_home) { @@ -156,6 +156,7 @@ sub add_target_to_known_hosts { # We don't know about this machine yet, so scan it. my $added = $anvil->Remote->_call_ssh_keyscan({ + debug => $debug, target => $target, port => $port, user => $user, @@ -472,7 +473,7 @@ sub call { # Can we log in without a password? my $user = getpwuid($<); - my $home_directory = $anvil->Get->users_home({user => $user}); + my $home_directory = $anvil->Get->users_home({debug => $debug, user => $user}); my $public_key = $home_directory."/.ssh/id_rsa.pub"; my $private_key = $home_directory."/.ssh/id_rsa"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $log_level, list => { @@ -695,12 +696,13 @@ sub _call_ssh_keyscan user => $user, }}); - my $shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." ".$target." >> ".$known_hosts; + # Redirect STDERR to STDOUT and grep off the comments. + my $shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." ".$target." 2>&1 | ".$anvil->data->{path}{exe}{'grep'}." -v ^# >> ".$known_hosts; if (($port) && ($port ne "22")) { - $shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." -p ".$port." ".$target." >> ".$known_hosts; + $shell_call = $anvil->data->{path}{exe}{'ssh-keyscan'}." -p ".$port." ".$target." 2>&1 | ".$anvil->data->{path}{exe}{'grep'}." -v ^# >> ".$known_hosts; } - my $output = $anvil->System->call({shell_call => $shell_call}); + my $output = $anvil->System->call({debug => $debug, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); foreach my $line (split/\n/, $output) { @@ -769,6 +771,7 @@ sub _check_known_hosts_for_target my $port = defined $parameter->{port} ? $parameter->{port} : ""; my $target = defined $parameter->{target} ? $parameter->{target} : ""; my $user = defined $parameter->{user} ? $parameter->{user} : $<; + my $known_machine = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { delete_if_found => $delete_if_found, known_hosts => $known_hosts, @@ -777,12 +780,19 @@ sub _check_known_hosts_for_target user => $user, }}); + # Is there a known_hosts file at all? + if (not $known_hosts) + { + # Nope. + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0163", variables => { file => $$known_hosts }}); + return($known_machine) + } + # read it in and search. - my $known_machine = 0; - my $body = $anvil->Storage->read_file({file => $known_hosts}); + my $body = $anvil->Storage->read_file({debug => $debug, file => $known_hosts}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { body => $body }}); foreach my $line (split/\n/, $body) { - my $line = $_; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { line => $line }}); if (($line =~ /$target ssh-rsa /) or ($line =~ /\[$target\]:$port ssh-rsa /)) @@ -805,7 +815,7 @@ sub _check_known_hosts_for_target $shell_call = $anvil->data->{path}{exe}{su}." - ".$user." -c '".$anvil->data->{path}{exe}{'ssh-keygen'}." -R ".$target."'"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { shell_call => $shell_call }}); - my $output = $anvil->System->call({shell_call => $shell_call}); + my $output = $anvil->System->call({debug => $debug, shell_call => $shell_call}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); foreach my $line (split/\n/, $output) { diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm index 0de90d76..48e2415a 100755 --- a/Anvil/Tools/Storage.pm +++ b/Anvil/Tools/Storage.pm @@ -881,9 +881,9 @@ sub read_file my $secure = defined $parameter->{secure} ? $parameter->{secure} : 0; my $target = defined $parameter->{target} ? $parameter->{target} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - cache => $cache, - file => $file, - force_read => $force_read, + cache => $cache, + file => $file, + force_read => $force_read, port => $port, password => $anvil->Log->secure ? $password : "--", remote_user => $remote_user, @@ -917,6 +917,7 @@ sub read_file # Setup the temp file name. my $temp_file = $file; $temp_file =~ s/\//_/g; + $temp_file =~ s/^_//g; $temp_file = "/tmp/".$temp_file.".".$target; $temp_file =~ s/\s+/_/g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }}); @@ -937,12 +938,14 @@ sub read_file else { # Read from the target by rsync'ing the file here. - $anvil->Storage->rsync({ + my $failed = $anvil->Storage->rsync({ + debug => $debug, destination => $temp_file, password => $password, port => $port, - source => $remote_user."\@".$target.$file, + source => $remote_user."\@".$target.":".$file, }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { failed => $failed }}); if (-e $temp_file) { @@ -1251,8 +1254,9 @@ sub rsync } # Make sure we know the fingerprint of the remote machine - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0158", variables => { target => $target }}); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, key => "log_0158", variables => { target => $target, user => $< }}); $anvil->Remote->add_target_to_known_hosts({ + debug => $debug, target => $target, user => $<, }); @@ -1269,13 +1273,15 @@ sub rsync } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { shell_call => $shell_call }}); - # Now make the call + # Now make the call (this exposes the password so 'secure' is set). my $conflict = ""; - my $output = $anvil->System->call({shell_call => $shell_call}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { output => $output }}); + my $output = $anvil->System->call({secure => 1, shell_call => $shell_call}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 1, list => { output => $output }}); foreach my $line (split/\n/, $output) { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + # This exposes the password on the 'password: ' line. + my $secure = $line =~ /password/i ? 1 : 0; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => $secure, list => { line => $line }}); if ($line =~ /Offending key in (\/.*\/).ssh\/known_hosts:(\d+)$/) { @@ -1643,6 +1649,7 @@ fi"; # OK, now write the file locally, then we'll rsync it over. my $temp_file = $file; $temp_file =~ s/\//_/g; + $temp_file =~ s/^_//g; $temp_file = "/tmp/".$temp_file; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { temp_file => $temp_file }}); $anvil->Storage->write_file({ @@ -1659,12 +1666,14 @@ fi"; # Now rsync it. if (-e $temp_file) { - $anvil->Storage->rsync({ - destination => $remote_user."\@".$target.$file, + my $failed = $anvil->Storage->rsync({ + debug => $debug, + destination => $remote_user."\@".$target.":".$file, password => $password, port => $port, source => $temp_file, }); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { failed => $failed }}); # Unlink unlink $temp_file; @@ -1786,14 +1795,14 @@ sub _create_rsync_wrapper return(""); } + ### NOTE: The first line needs to be the '#!...' line, hence the odd formatting below. my $timeout = 3600; my $wrapper_script = "/tmp/rsync.$target"; - my $wrapper_body = " -".$anvil->data->{path}{exe}{echo}." #!".$anvil->data->{path}{exe}{expect}." -".$anvil->data->{path}{exe}{echo}." set timeout ".$timeout." -".$anvil->data->{path}{exe}{echo}." eval spawn rsync \$argv -".$anvil->data->{path}{exe}{echo}." expect \"password:\" \{ send \"".$password."\\n\" \} -".$anvil->data->{path}{exe}{echo}." expect eof + my $wrapper_body = "#!".$anvil->data->{path}{exe}{expect}." +set timeout ".$timeout." +eval spawn rsync \$argv +expect \"password:\" \{ send \"".$password."\\n\" \} +expect eof "; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, secure => 0, list => { wrapper_script => $wrapper_script, diff --git a/share/words.xml b/share/words.xml index 9ecf22f4..abfcabc2 100644 --- a/share/words.xml +++ b/share/words.xml @@ -236,11 +236,12 @@ The database connection error was: Removing the old network configuration file: [#!variable!file!#] as part of the network reconfiguration. write_file() was asked to write the file: [#!variable!file!#] but it appears to be missing the file name. Aborting.]]> - Ensuring we've recorded: [#!variable!target!#]'s RSA fingerprint. + Ensuring we've recorded: [#!variable!target!#]'s RSA fingerprint for the user: [#!variable!user!#]. Adding the target: [#!variable!target!#]:[#!variable!port!#]'s RSA fingerprint to: [#!variable!user!#]'s list of known hosts. read_file() was asked to read the remote file: [#!variable!file!#] but it is not a full path. Aborting.]]> read_file() was asked to read the remote file: [#!variable!file!#] but it appears to be missing the file name. Aborting.]]> read_file() tried to rsync the remote file: [#!variable!remote_file!#] to the local temporary file: [#!variable!local_file!#], but it did not arrive. There might be more information above.]]> + The file: [#!variable!file!#] does not exist. Test diff --git a/tools/anvil-configure-network b/tools/anvil-configure-network index 1e57ecbd..71edb00b 100755 --- a/tools/anvil-configure-network +++ b/tools/anvil-configure-network @@ -59,6 +59,19 @@ if (not $connections) $anvil->nice_exit({exit_code => 2}); } +$anvil->Storage->write_file({ + debug => 2, + body => "This is only a test.\n", + file => "/home/admin/test.file", + group => "admin", + mode => "0644", + overwrite => 0, + port => 22, + password => "Initial1", + target => "192.168.122.202", + user => "admin", + remote_user => "admin", +}); die "Testing...\n";