diff --git a/docs/source/guides/admin-guides/references/man5/passwd.5.rst b/docs/source/guides/admin-guides/references/man5/passwd.5.rst index 70d8dd672..3438aa4b6 100644 --- a/docs/source/guides/admin-guides/references/man5/passwd.5.rst +++ b/docs/source/guides/admin-guides/references/man5/passwd.5.rst @@ -56,7 +56,7 @@ passwd Attributes: \ **cryptmethod**\ - Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod is not supported however the code attempts to auto-discover MD5 encrypted passwords. + Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default. diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index 296ee634a..d7c58b808 100755 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -824,7 +824,7 @@ passed as argument rather than by table value', key => 'The type of component this user/pw is for. Valid values: blade (management module), ipmi (BMC), system (nodes), omapi (DHCP), hmc, ivm, cec, frame, switch.', username => 'The default userid for this type of component', password => 'The default password for this type of component', - cryptmethod => 'Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod is not supported however the code attempts to auto-discover MD5 encrypted passwords.', + cryptmethod => 'Indicates the method that was used to encrypt the password attribute. On AIX systems, if a value is provided for this attribute it indicates that the password attribute is encrypted. If the cryptmethod value is not set it indicates the password is a simple string value. On Linux systems, the cryptmethod can be set to md5, sha256 or sha512. If not set, sha256 will be used as default.', authdomain => 'The domain in which this entry has meaning, e.g. specifying different domain administrators per active directory domain', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", diff --git a/xCAT-server/lib/perl/xCAT/PasswordUtils.pm b/xCAT-server/lib/perl/xCAT/PasswordUtils.pm index 72ab1343e..d9647deec 100644 --- a/xCAT-server/lib/perl/xCAT/PasswordUtils.pm +++ b/xCAT-server/lib/perl/xCAT/PasswordUtils.pm @@ -1,9 +1,14 @@ package xCAT::PasswordUtils; use xCAT::Table; +use xCAT::MsgUtils; +use xCAT::Utils; + my $ipmiuser = "USERID"; # default username to apply if nothing specified my $ipmipass = "PASSW0RD"; # default password to apply if nothing specified my $bladeuser = "USERID"; # default username to apply if nothing specified my $bladepass = "PASSW0RD"; # default password to apply if nothing specified +my %CRYPT_METHOD = ('md5' => '$1$', 'sha256' => '$5$', 'sha512' => '$6$'); + # Picks the IPMI authentication to use with or deploy to a BMC # mandatory arguments: @@ -112,3 +117,48 @@ sub getIPMIAuth { return \%authmap; } +# Encrypt system password based on the values in passwd table +# The values for system root user will be used if query key-pair is not defined +sub crypt_system_password { + # Just leave these arguments here for the compability reasons in Template.pm + # which get these values by parsing the template files. + my ($table, $kp, $fields) = @_; + if (!defined($table)) { + $table = 'passwd'; + } + if (!defined($kp)) { + $kp->{'key'} = 'system'; + $kp->{username} = 'root'; + $fields->[0] = 'password'; + $fields->[1] = 'cryptmethod'; + } + my $tabh = xCAT::Table->new($table); + unless ($tabh) { + return undef; + } + $data = $tabh->getAttribs($kp, @{$fields}); + if (!defined($data)) { + xCAT::MsgUtils->message("S", + "ERROR: Unable to get data from database table $table, key=$key"); + return undef; + } + $tabh->close(); + $password = $data->{'password'}; + if (!defined($password)) { + xCAT::MsgUtils->message("S", + "ERROR: Unable to get password from database table $table, key=$key"); + return undef; + } + $cryptmethod = $data->{'cryptmethod'}; + if (!$cryptmethod) { + # Use sha256 crypt method by default + $result = crypt($password, $CRYPT_METHOD{'sha256'} . xCAT::Utils::genpassword(8)); + } elsif( defined($CRYPT_METHOD{$cryptmethod})) { + $result = crypt($password, + $CRYPT_METHOD{$cryptmethod} . xCAT::Utils::genpassword(8)); + } else { + xCAT::MsgUtils->message("S", "Unsupported crypt method $cryptmethod"); + return undef; + } + return $result; +} diff --git a/xCAT-server/lib/perl/xCAT/Template.pm b/xCAT-server/lib/perl/xCAT/Template.pm index e4d99e749..2b72c6e39 100644 --- a/xCAT-server/lib/perl/xCAT/Template.pm +++ b/xCAT-server/lib/perl/xCAT/Template.pm @@ -15,6 +15,7 @@ use xCAT::ADUtils; #to allow setting of one-time machine passwords use xCAT::Utils; use xCAT::TableUtils; use xCAT::NetworkUtils; +use xCAT::PasswordUtils; use XML::Simple; BEGIN @@ -1573,28 +1574,27 @@ sub envvar return ($ENV{$envvar}); } -sub genpassword { - - #Generate a pseudo-random password of specified length - my $length = shift; - my $password = ''; - my $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890'; - srand; #have to reseed, rand is not rand otherwise - while (length($password) < $length) { - $password .= substr($characters, int(rand 63), 1); - } - return $password; -} - sub crydb { - my $result = tabdb(@_); + my ($table, $key, $field) = @_; + my @fields = [$field, 'cryptmethod']; + my $kp; - # 1 - MD5, 5 - SHA256, 6 - SHA512 - unless (($result =~ /^\$1\$/) || ($result =~ /^\$5\$/) || ($result =~ /^\$6\$/)) { - $result = crypt($result, '$1$' . genpassword(8)); - } - return $result; + my $get_query_map = sub { + my $key = shift; + my %kp; + foreach (split /,/, $key) { + my ($k, $v); + ($k, $v) = split /=/, $_; + $kp{$k} = $v if defined($k); + } + return \%kp if %kp; + sendmsg([ 1, "Unable to parse password parameters $key" ]); + return undef; + }; + $kp = $get_query_map->($key); + return undef if (!defined($kp)); + return xCAT::PasswordUtils::crypt_system_password($table, $kp, \@fields); } sub tabdb diff --git a/xCAT-server/lib/xcat/plugins/packimage.pm b/xCAT-server/lib/xcat/plugins/packimage.pm index 82ec70285..60b419ec3 100755 --- a/xCAT-server/lib/xcat/plugins/packimage.pm +++ b/xCAT-server/lib/xcat/plugins/packimage.pm @@ -37,6 +37,7 @@ use File::Path; use xCAT::Utils; use xCAT::TableUtils; use xCAT::SvrUtils; +use xCAT::PasswordUtils; use Digest::MD5 qw(md5_hex); Getopt::Long::Configure("bundling"); @@ -390,34 +391,27 @@ sub process_request { # before packaging the image system("umount $rootimg_dir/proc"); copybootscript($installroot, $rootimg_dir, $osver, $arch, $profile, $callback); - my $passtab = xCAT::Table->new('passwd'); - if ($passtab) { - my $pass = 'cluster'; - (my $pent) = $passtab->getAttribs({ key => 'system', username => 'root' }, 'password'); - if ($pent and defined($pent->{password})) { - $pass = $pent->{password}; - } - my $oldmask = umask(0077); - my $shadow; - open($shadow, "<", "$rootimg_dir/etc/shadow"); - my @shadents = <$shadow>; - close($shadow); - open($shadow, ">", "$rootimg_dir/etc/shadow"); - # 1 - MD5, 5 - SHA256, 6 - SHA512 - unless (($pass =~ /^\$1\$/) || ($pass =~ /^\$5\$/) || ($pass =~ /^\$6\$/)) { - $pass = crypt($pass, '$1$' . xCAT::Utils::genpassword(8)); - } - print $shadow "root:$pass:13880:0:99999:7:::\n"; - foreach (@shadents) { - unless (/^root:/) { - print $shadow "$_"; - } - } - close($shadow); - umask($oldmask); + my $pass = xCAT::PasswordUtils::crypt_system_password(); + if (!defined($pass)) { + $pass = 'cluster'; } + my $oldmask = umask(0077); + my $shadow; + open($shadow, "<", "$rootimg_dir/etc/shadow"); + my @shadents = <$shadow>; + close($shadow); + open($shadow, ">", "$rootimg_dir/etc/shadow"); + print $shadow "root:$pass:13880:0:99999:7:::\n"; + foreach (@shadents) { + unless (/^root:/) { + print $shadow "$_"; + } + } + close($shadow); + umask($oldmask); + # sync fils configured in the synclist to the rootimage $syncfile = xCAT::SvrUtils->getsynclistfile(undef, $osver, $arch, $profile, "netboot", $imagename); if (defined($syncfile) && -f $syncfile diff --git a/xCAT-server/lib/xcat/plugins/statelite.pm b/xCAT-server/lib/xcat/plugins/statelite.pm index 9435e390d..4b5667648 100644 --- a/xCAT-server/lib/xcat/plugins/statelite.pm +++ b/xCAT-server/lib/xcat/plugins/statelite.pm @@ -16,6 +16,7 @@ use File::Temp; use xCAT::Utils qw(genpassword); use xCAT::TableUtils qw(get_site_attribute); use xCAT::SvrUtils; +use xCAT::PasswordUtils; use Data::Dumper; Getopt::Long::Configure("bundling"); Getopt::Long::Configure("pass_through"); @@ -182,34 +183,26 @@ sub process_request { #get the root password for the node - my $passtab = xCAT::Table->new('passwd'); - if ($passtab) { - my $pass = 'cluster'; - (my $pent) = $passtab->getAttribs({ key => 'system', username => 'root' }, 'password'); - if ($pent and defined($pent->{password})) { - $pass = $pent->{password}; - } - my $oldmask = umask(0077); - my $shadow; - open($shadow, "<", "$rootimg_dir/etc/shadow"); - my @shadents = <$shadow>; - close($shadow); - open($shadow, ">", "$rootimg_dir/etc/shadow"); - - # 1 - MD5, 5 - SHA256, 6 - SHA512 - unless (($pass =~ /^\$1\$/) || ($pass =~ /^\$5\$/) || ($pass =~ /^\$6\$/)) { - $pass = crypt($pass, '$1$' . genpassword(8)); - } - print $shadow "root:$pass:13880:0:99999:7:::\n"; - foreach (@shadents) { - unless (/^root:/) { - print $shadow "$_"; - } - } - close($shadow); - umask($oldmask); + my $pass = xCAT::PasswordUtils::crypt_system_password(); + if (!defined($pass)) { + $pass = 'cluster'; } + my $oldmask = umask(0077); + my $shadow; + open($shadow, "<", "$rootimg_dir/etc/shadow"); + my @shadents = <$shadow>; + close($shadow); + open($shadow, ">", "$rootimg_dir/etc/shadow"); + print $shadow "root:$pass:13880:0:99999:7:::\n"; + foreach (@shadents) { + unless (/^root:/) { + print $shadow "$_"; + } + } + close($shadow); + umask($oldmask); + my $distname = $osver; unless (-r "$::XCATROOT/share/xcat/netboot/$distname/" or not $distname) { chop($distname);