Rework IPMI.pm IPMI 2 session negotiation a bit, now we take care to make sure the most recent open rmcp+ request is the one used

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/branches/2.7@13817 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
jbjohnso 2012-09-16 03:56:42 +00:00
parent 94511e23c0
commit 1dd54b108d

View File

@ -320,7 +320,9 @@ sub open_rmcpplus_request {
my $self = shift;
$self->{'authtype'}=6;
$self->{sidm} = [0x15,0x58,0x25,0x7a];
my @payload = (0x1f,#message tag, TODO: could be random
unless ($self->{rmcptag}) { $self->{rmcptag} = 1; }
$self->{rmcptag}+=1;
my @payload = ($self->{rmcptag},#message tag,
0, #requested privilege role, 0 is highest allowed
0,0, #reserved
0x15,0x58,0x25,0x7a, #we only have to sweat one session, so no need to generate
@ -433,7 +435,15 @@ sub timedout {
$self->{ipmicallback}->($rsp,$self->{ipmicallback_args});
return;
}
$self->sendpayload(%{$self->{pendingargs}},nowait=>1); #do not induce the xmit to wait for packets, just spit it out. timedout is in a wait-for-packets loop already, so it's fine
if ($self->{sessionestablishmentcontext} == STATE_OPENSESSION) { #in this particular case, we want to craft a new rmcp session request with a new client side session id, to aid in distinguishing retry from new
$self->open_rmcpplus_request();
} elsif ($self->{sessionestablishmentcontext} == STATE_EXPECTINGRAKP2) { #in this particular case, we want to craft a new rmcp session request with a new client side session id, to aid in distinguishing retry from new
$self->send_rakp1();
} elsif ($self->{sessionestablishmentcontext} == STATE_EXPECTINGRAKP4) { #in this particular case, we want to craft a new rmcp session request with a new client side session id, to aid in distinguishing retry from new
$self->relog();
} else {
$self->sendpayload(%{$self->{pendingargs}},nowait=>1); #do not induce the xmit to wait for packets, just spit it out. timedout is in a wait-for-packets loop already, so it's fine
}
}
sub route_ipmiresponse {
my $sockaddr=shift;
@ -582,7 +592,7 @@ sub got_rmcp_response {
#we would ignore an RMCP+ open session response if we are not in an IPMI2 negotiation, so we have to have *some* state that isn't established for this to be kosher
return 9; #now's not the time for this response, ignore it
}
unless ($byte == 0x1f) {
unless ($byte == $self->{rmcptag}) { #make sure this rmcp response is specifically the last one we sent.... we don't want to happily proceed with the risk a retry request blew up our temp session id without letting us know
return 9;
}
$byte = shift @data;
@ -597,7 +607,6 @@ sub got_rmcp_response {
}
splice @data,0,5;
$self->{pendingsessionid} = [splice @data,0,4];
$self->{sessionestablishmentcontext} = STATE_EXPECTINGRAKP2;
#TODO: if we retried, and the first answer comes back but the second answer is dropped, log in will fail as we do not know our correct session id
#basically, we would have to retry open session requested until RAKP2 *confirmed* good
$self->send_rakp1();
@ -607,7 +616,8 @@ sub got_rmcp_response {
sub send_rakp3 {
#TODO: this is the point where OPEN RMCP SESSION REQUEST should have retry stopped, not send_rakp1
my $self = shift;
my @payload = (0x1f,0,0,0,@{$self->{pendingsessionid}});
$self->{rmcptag}+=1;
my @payload = ($self->{rmcptag},0,0,0,@{$self->{pendingsessionid}});
my @user = unpack("C*",$self->{userid});
push @payload,unpack("C*",hmac_sha1(pack("C*",@{$self->{remoterandomnumber}},@{$self->{sidm}},4,scalar @user,@user),$self->{password}));
$self->sendpayload(payload=>\@payload,type=>$payload_types{'rakp3'});
@ -615,7 +625,8 @@ sub send_rakp3 {
sub send_rakp1 {
my $self = shift;
my @payload = (0x1f,0,0,0,@{$self->{pendingsessionid}});
$self->{rmcptag}+=1;
my @payload = ($self->{rmcptag},0,0,0,@{$self->{pendingsessionid}});
$self->{randomnumber}=[];
foreach (1..16) {
my $randomnumber = int(rand(255));
@ -626,6 +637,7 @@ sub send_rakp1 {
my @user = unpack("C*",$self->{userid});
push @payload,scalar @user;
push @payload,@user;
$self->{sessionestablishmentcontext} = STATE_EXPECTINGRAKP2;
$self->sendpayload(payload=>\@payload,type=>$payload_types{'rakp1'});
}
sub init {
@ -653,7 +665,7 @@ sub got_rakp4 {
unless ($self->{sessionestablishmentcontext} == STATE_EXPECTINGRAKP4) { #ignore rakp4 unless we are explicitly expecting RAKP4
return 9; #now's not the time for this response, ignore it
}
unless ($byte == 0x1f) {
unless ($byte == $self->{rmcptag}) { #make sure this rmcp response is specifically the last one we sent.... we don't want to happily proceed with the risk a retry request blew up our temp session id without letting us know
return 9;
}
$byte = shift @data;
@ -675,7 +687,8 @@ sub got_rakp4 {
my @expectauthcode = unpack("C*",hmac_sha1(pack("C*",@{$self->{randomnumber}},@{$self->{pendingsessionid}},@{$self->{remoteguid}}),$self->{sik}));
foreach (@expectauthcode[0..11]) {
unless ($_ == (shift @data)) {
$self->{onlogon}->("ERROR: failure in final rakp exchange message",$self->{onlogon_args});
#we'll just ignore this transgression...... *this time*
#$self->{onlogon}->("ERROR: failure in final rakp exchange message",$self->{onlogon_args});
return 9;
}
}
@ -701,7 +714,7 @@ sub got_rakp2 {
#the reason being that if an old rakp1 retry actually made it and we were just too aggressive, then a previous rakp2 is invalidated and invalid session id or the integrity check value is bad
return 9; #now's not the time for this response, ignore it
}
unless ($byte == 0x1f) {
unless ($byte == $self->{rmcptag}) { #make sure this rmcp response is specifically the last one we sent.... we don't want to happily proceed with the risk a retry request blew up our temp session id without letting us know
return 9;
}
$byte = shift @data;