Commit e2c5c93d authored by Brian Kroth's avatar Brian Kroth

allow using both an ipmi kg encryption key and user/password

also support alterntive ipmi privilege levels
parent 8243b154
......@@ -55,6 +55,7 @@ use POSIX ":sys_wait_h";
my $debug = 0;
# Always parallelize for now cause we are vulnerable to timeouts with
# unreachable nodes or weird iLO crap.
# NOTE: ipmi doesn't appear to be handled if $parallelize isn't set.
my $parallelize = 1;
# Turn off line buffering on output
......@@ -99,7 +100,9 @@ sub iloctrl($$@) {
}
my ($IP) = $res->fetchrow();
$res = DBQueryFatal("select key_role,key_uid,mykey" .
# FIXED: Handle multiple rows here like power_ipmi.pm does.
# This is so we can grab a kgkey separately from the user password.
$res = DBQueryFatal("select key_role,key_uid,mykey,key_privlvl" .
" from outlets_remoteauth" .
" where node_id='$n' and key_type='$type'");
if (!defined($res) || !$res || $res->num_rows() == 0) {
......@@ -107,20 +110,53 @@ sub iloctrl($$@) {
++$exitval;
next;
}
my ($krole,$kuid,$kkey) = $res->fetchrow();
my ($krole,$kuid,$kkey,$kgkey,$kprivlvl);
while (my $row = $res->fetchrow_hashref()) {
$krole = $row->{'key_role'};
if ($krole eq "ipmi-passwd") {
$kuid = $row->{'key_uid'};
$kkey = $row->{'mykey'};
if ($row->{'key_privlvl'}) {
$kprivlvl = $row->{'key_privlvl'};
}
}
elsif ($krole eq "ipmi-kgkey") {
$kgkey = $row->{'mykey'} =~ s/^0x//;
# NOTE: key_privlvl is currently ignored in case this is the
# only authentication mechanism being used.
}
}
if ($kgkey && $kkey) {
$krole = 'ipmi-kgkey-passwd';
}
elsif ($kkey) {
$krole = 'ipmi-passwd';
}
elsif ($kgkey) {
$krole = 'ipmi-kgkey';
# restore previous behavior
$kkey = $kgkey;
$kgkey = undef;
$kprivlvl = undef;
}
else {
# all of the keys were empty which is weird and the last key_role
# returned from the db wins
}
$ilo_nodeinfo{$n} = [ $n,$IP,$krole,$kuid,$kkey ];
$ilo_nodeinfo{$n} = [ $n,$IP,$krole,$kuid,$kkey,$kgkey,$kprivlvl ];
}
my $timeout = 30;
if ($parallelize) {
my $coderef = sub {
my ($n,$IP,$krole,$kuid,$kkey) = @{ $_[0] };
my ($n,$IP,$krole,$kuid,$kkey,$kgkey,$kprivlvl) = @{ $_[0] };
my $tret;
eval {
if ($type =~ /^ipmi/) {
$tret = ipmiexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout);
$tret = ipmiexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$kgkey,$kprivlvl,$timeout);
} else {
$tret = iloexec($n,$type,$cmd,$IP,$krole,$kuid,$kkey,$timeout);
}
......@@ -368,10 +404,10 @@ sub iloexec($$$$$$$;$) {
}
#
# Arguments: $node_id,$type,$cmd,$IP,$key_role,$key_uid,$key[,$timeout]
# Arguments: $node_id,$type,$cmd,$IP,$key_role,$key_uid,$key[,$kgkey,$privlvl,$timeout]
#
sub ipmiexec($$$$$$$;$) {
my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$timeout) = @_;
sub ipmiexec($$$$$$$;$$$) {
my ($node_id,$type,$cmd,$IP,$key_role,$key_uid,$key,$kgkey,$privlvl,$timeout) = @_;
if ($debug) {
print "ipmiexec called with (" . join(',',@_) . ")\n";
......@@ -407,12 +443,15 @@ sub ipmiexec($$$$$$$;$) {
if ($key_role eq 'ipmi-passwd') {
$usekey = 0;
} elsif ($key_role eq 'ipmi-kgkey-passwd') {
$usekey = 1;
} elsif ($key_role eq 'ipmi-kgkey') {
if ($type eq 'ipmi15') {
warn "Cannot use key_role 'kgkey' for IPMI 1.5!";
return -21;
}
$usekey = 1;
$kgkey = $key;
} else {
warn "Unsupported IPMI key_role $key_role!";
return -14;
......@@ -421,13 +460,14 @@ sub ipmiexec($$$$$$$;$) {
# XXX IPMI takes about 40 seconds to timeout and doesn't
# have an option to control?!
my $ipmicmd = "ipmitool -I $iface -H $IP -U $key_uid -E -K power $cmd";
my $privlvl_args = ($key_privlvl) ? " -L $key_privlvl" : '';
my $ipmicmd = "ipmitool -I $iface -H $IP -U $key_uid $privlvl_args -E -K power $cmd";
print "*** Executing '$ipmicmd', output:\n"
if ($debug > 1);
# Set the password and key environment variables
$ENV{'IPMI_PASSWORD'} = substr($key, 0, $pwdmax);
$ENV{'IPMI_KGKEY'} = $key
$ENV{'IPMI_KGKEY'} = $kgkey
if ($usekey);
my $output = `$ipmicmd 2>&1`;
......@@ -447,3 +487,7 @@ sub ipmiexec($$$$$$$;$) {
}
1;
# vim: set ft=perl et sw=4 ts=8:
# Not sure what the (no)et sw=? ts=? rules should be in this file - they're kind of mixed.
# Seems like a leading tab in some places and then 4 expanded spaces. Maybe et sw=4 ts=8.
......@@ -81,7 +81,7 @@ sub new($$$;$) {
$self->{KGKEY} = "";
# Fetch authentication credentials from the DB.
my $res = DBQueryFatal("select key_role,key_uid,mykey" .
my $res = DBQueryFatal("select key_role,key_uid,mykey,key_privlvl" .
" from outlets_remoteauth" .
" where node_id='$devicename'".
" and key_type='$KTYPE'");
......@@ -93,6 +93,9 @@ sub new($$$;$) {
if ($role eq "ipmi-passwd") {
$self->{USERNAME} = $row->{'key_uid'};
$self->{PASSWORD} = $row->{'mykey'};
if ($row->{'key_privlvl'}) {
$self->{PRIVLVL} = $row->{'key_privlvl'};
}
}
elsif ($role eq "ipmi-kgkey") {
$self->{KGKEY} = $row->{'mykey'} =~ s/^0x//;
......@@ -106,6 +109,9 @@ sub new($$$;$) {
} elsif ($self->{DEVICETYPE} eq "ipmi-ms") {
$self->{IPMICMD} .= " -I lanplus";
}
if ($self->{PRIVLVL}) {
$self->{IPMICMD} .= " -L $self->{PRIVLVL}";
}
# Do a quick query, to see if it works
system("$self->{IPMICMD} power status >/dev/null 2>\&1");
......@@ -274,3 +280,7 @@ sub _get_msaddr($$) {
# End with true
1;
# vim: set ft=perl et sw=4 ts=8:
# Not sure what the (no)et sw=? ts=? rules should be in this file - they're kind of mixed.
# Seems like a leading tab in some places and then 4 expanded spaces. Maybe et sw=4 ts=8.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment