diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 9f528c26d..8f6ed715b 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1568,7 +1568,18 @@ hwinv => { disable => "Set to 'yes' or '1' to comment out this row.", }, }, - +token => { + cols => [qw(tokenid username expire comments disable)], + keys => [qw(tokenid)], + table_desc => 'The token of users for authentication.', + descriptions => { + tokenid => 'It is a UUID as an unified identify for the user.', + username => 'The user name.', + expire => 'The expire time for this token.', + comments => 'Any user-provided notes.', + disable => "Set to 'yes' or '1' to comment out this row.", + }, +}, ); # end of tabspec definition diff --git a/xCAT-server/lib/perl/xCAT/xcatd.pm b/xCAT-server/lib/perl/xCAT/xcatd.pm index ed76310dc..6dae1b684 100644 --- a/xCAT-server/lib/perl/xCAT/xcatd.pm +++ b/xCAT-server/lib/perl/xCAT/xcatd.pm @@ -10,6 +10,7 @@ use xCAT::Table; use xCAT::MsgUtils; use Data::Dumper; use xCAT::NodeRange; +use xCAT::Utils; #-------------------------------------------------------------------------------- =head1 xCAT::XCATD @@ -270,4 +271,67 @@ sub validate { xCAT::MsgUtils->message("S","Request matched no policy rule: peername=$peername, peerhost=$peerhost ".$request->{command}->[0]); return 0; } + +my $tokentimeout = 86400; # one day +# this subroutine search the token table +# 1. find the existed token entry for the user and reset the expire time +# 1.1. if not find existed token, create a new one and add it to token table +# 2. clean up the expired token +# +# this subroutine is called after the account has been authorized +sub gettoken { + my $class=shift; + my $req = shift; + + my $user = $req->{gettoken}->[0]->{username}->[0]; + my $tokentb = xCAT::Table->new('token'); + unless ($tokentb) { + return undef; + } + my $tokens = $tokentb->getAllEntries; + my $expiretime = time() + $tokentimeout; + foreach my $token (@{$tokens}) { + if ($token->{username} eq $user) { + #delete old token + $tokentb->delEntries({'tokenid'=>$token->{tokenid}}); + } else { + #clean the expired token + if ($token->{expire} > $expiretime) { + $tokentb->delEntries({'tokenid'=>$token->{tokenid}}); + } + } + } + + # create a new token for this request + my $uuid = xCAT::Utils->genUUID(); + $tokentb->setAttribs({tokenid=>$uuid, username => $user}, {expire => $expiretime}); + $tokentb->close(); + + return ($uuid, $expiretime); +} + +# verify the token has correct entry in token table and expire time is not exceeded. +sub verifytoken { + my $class=shift; + my $req = shift; + + my $tokenid = $req->{tokens}->[0]->{tokenid}->[0]; + my $tokentb = xCAT::Table->new('token'); + unless ($tokentb) { + return undef; + } + my $token = $tokentb->getAttribs({'tokenid' => $tokenid}, ('username', 'expire')); + if (defined ($token) && defined ($token->{'username'}) && defined ($token->{'expire'})) { + my $expiretime = time() + $tokentimeout; + if ($token->{'expire'} < time()) { + $tokentb->delEntries({'tokenid'=>$token->{tokenid}}); + return undef; + } else { + return $token->{'username'}; + } + } else { + return undef; + } +} + 1; diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index 770ae13ab..3c881770f 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -2096,6 +2096,40 @@ sub service_connection { delete($req->{becomeuser}); #Remove it to keep it from view } + # If the request is to aquire a token for a specific account + if (defined $req->{gettoken}) { + # authencitate the username:password + $peername=becomeuser($req->{gettoken}->[0]->{username}->[0], + $req->{gettoken}->[0]->{password}->[0]); + my $resp; + if ($peername) { + # for a valid account, get a token + my ($tokenid, $exptime) = xCAT::xcatd->gettoken($req); + my ($sec,$min,$hour,$mday,$mon,$year) = localtime($exptime); + $year += 1900; + my $htime = "$year-$mon-$mday $hour:$min:$sec"; + $resp = {data=>[{token => [{id => $tokenid, expire => $htime}]}]}; + } else { + $resp={error=>["Authentication failure"],errorcode=>[1]}; + } + $resp->{serverdone}=[ undef ] ; + send_response($resp,$sock); + return; + } + + # If user trying to use 'token' to authenticate + if (defined $req->{tokens}) { + # get the valid user name by the token id + $peername = xCAT::xcatd->verifytoken($req); + unless (defined $peername) { + my $resp={error=>["Authentication failure"],errorcode=>[1]}; + $resp->{serverdone}=[ undef ] ; + send_response($resp,$sock); + return; + } + delete($req->{tokenid}); + } + #we have a full request.. #printf $request."\n"; $request="";