From 69fff6a31ead857c12558ad2bd9207c5463ddf6c Mon Sep 17 00:00:00 2001 From: chenglch Date: Fri, 18 Nov 2016 13:20:39 +0800 Subject: [PATCH] Load the cryptmethod in the passwd table to generate the password sha256 and sha512 crypt methods are supported from glibc 2.7 version. This patch enable the crypt feature on linux system and encrypt the password with sha256 by default. implement: #1890 --- .../admin-guides/references/man5/passwd.5.rst | 2 +- perl-xCAT/xCAT/Schema.pm | 2 +- xCAT-server/lib/perl/xCAT/PasswordUtils.pm | 50 +++++++++++++++++++ xCAT-server/lib/perl/xCAT/Template.pm | 38 +++++++------- xCAT-server/lib/xcat/plugins/packimage.pm | 44 +++++++--------- xCAT-server/lib/xcat/plugins/statelite.pm | 45 +++++++---------- 6 files changed, 109 insertions(+), 72 deletions(-) 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 929f2d578..688a800fc 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);