You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
234 lines
8.0 KiB
234 lines
8.0 KiB
5 years ago
|
#!/usr/bin/perl
|
||
|
#
|
||
|
# This program is setuid 'admin' and calls a (new) peer to read its hostname and system UUID. It takes the
|
||
|
# target's password in via a file.
|
||
|
#
|
||
|
# Exit codes;
|
||
|
# 0 = Normal exit.
|
||
|
# 1 = Password file given, but not found
|
||
|
# 2 = Password file given, but not readable
|
||
|
# 3 = Peer not accessible
|
||
|
# 4 = Unable to find the peer's host UUID
|
||
|
#
|
||
|
|
||
|
use strict;
|
||
|
use warnings;
|
||
|
use Anvil::Tools;
|
||
|
|
||
|
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
|
||
|
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0];
|
||
|
if (($running_directory =~ /^\./) && ($ENV{PWD}))
|
||
|
{
|
||
|
$running_directory =~ s/^\./$ENV{PWD}/;
|
||
|
}
|
||
|
|
||
|
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete.
|
||
|
$| = 1;
|
||
|
|
||
|
my $anvil = Anvil::Tools->new();
|
||
|
$anvil->Log->level({set => 2});
|
||
|
$anvil->Log->secure({set => 1});
|
||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }});
|
||
|
|
||
|
# Read switches (target ([user@]host[:port]) and the file with the target's password.
|
||
|
$anvil->data->{switches}{target} = "";
|
||
|
$anvil->data->{switches}{password} = "";
|
||
|
$anvil->Get->switches;
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => {
|
||
|
'switches::target' => $anvil->data->{switches}{target},
|
||
|
'switches::password' => $anvil->data->{switches}{password},
|
||
|
}});
|
||
|
|
||
|
$anvil->data->{target}{user} = "admin";
|
||
|
$anvil->data->{target}{host} = $anvil->data->{switches}{target};
|
||
|
$anvil->data->{target}{port} = 22;
|
||
|
$anvil->data->{target}{password} = get_password($anvil);
|
||
|
if ($anvil->data->{target}{host} =~ /^(.*?)@/)
|
||
|
{
|
||
|
$anvil->data->{target}{user} = $1;
|
||
|
$anvil->data->{target}{host} =~ s/^(.*?)@//;
|
||
|
}
|
||
|
if ($anvil->data->{target}{host} =~ /:(\d+)$/)
|
||
|
{
|
||
|
$anvil->data->{target}{port} = $1;
|
||
|
$anvil->data->{target}{host} =~ s/:(\d+)$//;
|
||
|
}
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||
|
'target::user' => $anvil->data->{target}{user},
|
||
|
'target::target' => $anvil->data->{target}{host},
|
||
|
'target::port' => $anvil->data->{target}{port},
|
||
|
'target::password' => $anvil->Log->is_secure($anvil->data->{target}{password}),
|
||
|
}});
|
||
|
|
||
|
my $host_uuid = get_host_uuid($anvil);
|
||
|
my $host_name = get_host_name($anvil);
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||
|
host_uuid => $host_uuid,
|
||
|
host_name => $host_name,
|
||
|
}});
|
||
|
print "host_name=".$host_name."\n";
|
||
|
print "host_uuid=".$host_uuid."\n";
|
||
|
|
||
|
$anvil->nice_exit({code => 0});
|
||
|
|
||
|
|
||
|
#############################################################################################################
|
||
|
# Functions #
|
||
|
#############################################################################################################
|
||
|
|
||
|
# This tries to read the target's UUID either via host.uuid or via dmidecode.
|
||
|
sub get_host_name
|
||
|
{
|
||
|
my ($anvil) = @_;
|
||
|
|
||
|
my ($host_name, $error, $return_code) = $anvil->Remote->call({
|
||
|
debug => 2,
|
||
|
shell_call => $anvil->data->{path}{exe}{hostnamectl}." --static",
|
||
|
user => $anvil->data->{target}{user},
|
||
|
target => $anvil->data->{target}{host},
|
||
|
port => $anvil->data->{target}{port},
|
||
|
password => $anvil->data->{target}{password},
|
||
|
});
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||
|
host_name => $host_name,
|
||
|
error => $error,
|
||
|
return_code => $return_code,
|
||
|
}});
|
||
|
|
||
|
return($host_name);
|
||
|
}
|
||
|
|
||
|
# This tries to read the target's UUID either via host.uuid or via dmidecode.
|
||
|
sub get_host_uuid
|
||
|
{
|
||
|
my ($anvil) = @_;
|
||
|
|
||
|
# This is the first thing called, so start by verifying we can talk to the target at all.
|
||
|
my $access = $anvil->Remote->test_access({
|
||
|
user => $anvil->data->{target}{user},
|
||
|
target => $anvil->data->{target}{host},
|
||
|
port => $anvil->data->{target}{port},
|
||
|
password => $anvil->data->{target}{password},
|
||
|
});
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { access => $access }});
|
||
|
if (not $access)
|
||
|
{
|
||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0069", variables => {
|
||
|
host => $anvil->data->{target}{user}.'@'.$anvil->data->{target}{host}.':'.$anvil->data->{target}{port},
|
||
|
}});
|
||
|
$anvil->nice_exit({exit_code => 3});
|
||
|
}
|
||
|
|
||
|
# Try to read the host.uuid file on the target, if possible.
|
||
|
my $host_uuid = "";
|
||
|
my $file_body = $anvil->Storage->read_file({
|
||
|
debug => 3,
|
||
|
file => $anvil->data->{path}{data}{host_uuid},
|
||
|
user => $anvil->data->{target}{user},
|
||
|
target => $anvil->data->{target}{host},
|
||
|
port => $anvil->data->{target}{port},
|
||
|
password => $anvil->data->{target}{password},
|
||
|
});
|
||
|
$file_body =~ s/\n$//g;
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { file_body => $file_body }});
|
||
|
if (($file_body eq "!!error!!") or (not $anvil->Validate->is_uuid({uuid => $file_body})))
|
||
|
{
|
||
|
# No good, Try dmidecode.
|
||
|
my ($output, $error, $return_code) = $anvil->Remote->call({
|
||
|
debug => 2,
|
||
|
shell_call => $anvil->data->{path}{exe}{dmidecode}." --string system-uuid",
|
||
|
user => $anvil->data->{target}{user},
|
||
|
target => $anvil->data->{target}{host},
|
||
|
port => $anvil->data->{target}{port},
|
||
|
password => $anvil->data->{target}{password},
|
||
|
});
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => {
|
||
|
output => $output,
|
||
|
error => $error,
|
||
|
return_code => $return_code,
|
||
|
}});
|
||
|
if ($anvil->Validate->is_uuid({uuid => $output}))
|
||
|
{
|
||
|
# Got it.
|
||
|
$host_uuid = $output;
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }});
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$host_uuid = $file_body;
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_uuid => $host_uuid }});
|
||
|
}
|
||
|
|
||
|
# Exit out if I failed to get the host's UUID.
|
||
|
if (not $host_uuid)
|
||
|
{
|
||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0070", variables => {
|
||
|
host => $anvil->data->{target}{user}.'@'.$anvil->data->{target}{host}.':'.$anvil->data->{target}{port},
|
||
|
}});
|
||
|
$anvil->nice_exit({exit_code => 4});
|
||
|
}
|
||
|
|
||
|
return($host_uuid);
|
||
|
}
|
||
|
|
||
|
# This reads in the password from the password file, if possible.
|
||
|
sub get_password
|
||
|
{
|
||
|
my ($anvil) = @_;
|
||
|
|
||
|
my $password = "";
|
||
|
if ($anvil->data->{switches}{password})
|
||
|
{
|
||
|
my $found = 0;
|
||
|
my $file = $anvil->data->{switches}{password};
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }});
|
||
|
if (-e $file)
|
||
|
{
|
||
|
$found = 1;
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { found => $found }});
|
||
|
}
|
||
|
elsif ($anvil->data->{switches}{password} !~ /^\//)
|
||
|
{
|
||
|
$file = "/tmp/".$anvil->data->{switches}{password};
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { file => $file }});
|
||
|
if (-e $file)
|
||
|
{
|
||
|
$found = 1;
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { found => $found }});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (not $found)
|
||
|
{
|
||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0067", variables => { file => $file }});
|
||
|
$anvil->nice_exit({exit_code => 1});
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
# Read the file in.
|
||
|
my $body = $anvil->Storage->read_file({
|
||
|
debug => 3,
|
||
|
file => $file,
|
||
|
secure => 1,
|
||
|
});
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, secure => 1, list => { body => $body }});
|
||
|
|
||
|
if ($body eq "!!error!!")
|
||
|
{
|
||
|
# Something went wrong.
|
||
|
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, priority => "err", key => "error_0068", variables => { file => $file }});
|
||
|
$anvil->nice_exit({exit_code => 2});
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$password = $body;
|
||
|
$password =~ s/\n$//;
|
||
|
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, secure => 1, list => { password => $password }});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return($password);
|
||
|
}
|