From 73b1da98e7dce731bb30f86c45173c88b735be60 Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sun, 10 Jan 2010 20:39:42 +0100 Subject: Use PAM to set password Instead of getting the password encrypted by the client, get it in plain text, and set it via PAM. This behavior is standard on all supported platforms, which allows for code simplification, and avoids bugs when new password encryption algorithms appear. Never return the encrypted password on the bus. Instead, PAM should always be used to change it, possibly authenticating when changing own password. --- Users/Users.pm | 153 +++++++++++++-------------------------------------------- UsersConfig.pm | 11 ++--- 2 files changed, 38 insertions(+), 126 deletions(-) diff --git a/Users/Users.pm b/Users/Users.pm index 8034ce8..f924d83 100644 --- a/Users/Users.pm +++ b/Users/Users.pm @@ -46,6 +46,8 @@ package Users::Users; +use Authen::PAM; + use Utils::Util; use Utils::Report; use Utils::File; @@ -73,6 +75,9 @@ $cmd_deluser = &Utils::File::locate_tool ("deluser"); $cmd_chfn = &Utils::File::locate_tool ("chfn"); $cmd_pw = &Utils::File::locate_tool ("pw"); +$cmd_passwd = &Utils::File::locate_tool ("passwd"); +$cmd_chpasswd = &Utils::File::locate_tool ("chpasswd"); + # enum like for verbose group array positions my $i = 0; my $LOGIN = $i++; @@ -273,45 +278,6 @@ my $logindefs_dist_map = { 'users_write_groups_fail' => ['warn', 'Writing groups failed.'], }); - -sub do_get_use_md5 -{ - my ($file) = @_; - my ($fh, @line, $i, $use_md5); - - my $fh = &Utils::File::open_read_from_names ("/etc/pam.d/$file"); - return 0 if (!$fh); - - $use_md5 = 0; - - while (<$fh>) - { - next if &Utils::Util::ignore_line ($_); - chomp; - @line = split /[ \t]+/; - - if ($line[0] eq "\@include") - { - $use_md5 = &do_get_use_md5 ($line[1]); - } - elsif ($line[0] eq "password") - { - foreach $i (@line) - { - $use_md5 = 1 if ($i eq "md5"); - } - } - } - - close $fh; - return $use_md5; -} - -sub get_use_md5 -{ - return &do_get_use_md5 ("passwd"); -} - sub logindefs_add_defaults { # Common for all distros @@ -402,6 +368,9 @@ sub get push @comment, "" while (scalar (@comment) < 5); $line[$COMMENT] = [@comment]; + # always return empty string - anyway, passwd should be in /etc/shadow + $line[$PASSWD] = ""; + $users_hash{$login} = [@line]; # max value for an unsigned 32 bits integer means no main group @@ -416,32 +385,6 @@ sub get } &Utils::File::close_file ($ifh); - $ifh = &Utils::File::open_read_from_names(@shadow_names); - - if ($ifh) - { - while (<$ifh>) - { - chomp; - - # FreeBSD allows comments in the shadow passwd file. - next if &Utils::Util::ignore_line ($_); - - @line = split ':', $_, -1; - $login = shift @line; - $passwd = shift @line; - - # do not add data if the user isn't present - next if (!exists $users_hash{$login}); - - $users_hash{$login}[$PASSWD] = $passwd; - - # FIXME: add the rest of the fields? - #push @{$$users_hash{$login}}, @line; - } - - &Utils::File::close_file ($ifh); - } # transform the hash into an array foreach $login (keys %users_hash) @@ -557,21 +500,24 @@ sub set_passwd if ($Utils::Backend::tool{"system"} eq "FreeBSD") { my ($command); - $command = "$cmd_pw usermod -H 0"; + $command = "$cmd_pw usermod \'$login\' -h 0"; $pwdpipe = &Utils::File::run_pipe_write ($command); print $pwdpipe $password; &Utils::File::close_file ($pwdpipe); } elsif ($Utils::Backend::tool{"system"} eq "SunOS") { - &modify_shadow_password ($login, $password); + my ($command); + $command = "$cmd_passwd --stdin \'$login\'"; + $pwdpipe = &Utils::File::run_pipe_write ($command); + print $pwdpipe $password; + &Utils::File::close_file ($pwdpipe); } else { - my (@command); - @command = ($cmd_usermod, "-p", $password, $login); - - &Utils::File::run (@command); + $pwdpipe = &Utils::File::run_pipe_write ($cmd_chpasswd); + print $pwdpipe "$login:$password"; + &Utils::File::close_file ($pwdpipe); } } @@ -601,7 +547,6 @@ sub add_user if ($Utils::Backend::tool{"system"} eq "FreeBSD") { - my $pwdpipe; my $logindefs; # FreeBSD doesn't create the home directory @@ -612,23 +557,15 @@ sub add_user } &Utils::File::run ($tool_mkdir, "-p", $$user[$HOME]); - $command = "$cmd_pw useradd " . - " -n \'" . $$user[$LOGIN] . "\'" . - " -H 0"; # pw(8) reads password from STDIN + @command = ($cmd_pw, "useradd", "-n", $$user[$LOGIN], + "-h", "-"); # disable login until password is set - $command .= "-d \' $$user[$HOME] \' " if ($$user[$HOME]); - $command .= "-s \' $$user[$SHELL] \' " if ($$user[$SHELL]); - $command .= "-u $$user[$UID]" if ($real_uid); - $command .= "-g $$user[$GID]" if ($real_gid); - -# @command = ($cmd_pw, "useradd", "-n", $$user[$LOGIN], -# "-d", $$user[$HOME], -# "-s", $$user[$SHELL], -# "-H", "0"); # pw(8) reads password from STDIN + push (@command, ("-s", $$user[$HOME])) if ($$user[$HOME]); + push (@command, ("-s", $$user[$SHELL])) if ($$user[$SHELL]); + push (@command, ("-u", $$user[$UID])) if ($real_uid); + push (@command, ("-g", $$user[$GID])) if ($real_gid); - $pwdpipe = &Utils::File::run_pipe_write ($command); - print $pwdpipe $$user[$PASSWD]; - &Utils::File::close_file ($pwdpipe); + &Utils::File::run (@command); } elsif ($Utils::Backend::tool{"system"} eq "SunOS") { @@ -641,7 +578,6 @@ sub add_user push (@command, $$user[$LOGIN]); &Utils::File::run (@command); - &modify_shadow_password ($$user[$LOGIN], $$user[$PASSWD]); } else { @@ -663,18 +599,11 @@ sub add_user push (@command, $$user[$LOGIN]); &Utils::File::run (@command); - - # password can't be set in non-interactive - # mode with adduser, call usermod instead - @command = ($cmd_usermod, "-p", $$user[$PASSWD], $$user[$LOGIN]); - - &Utils::File::run (@command); } else { # fallback to useradd - @command = ($cmd_useradd, "-m", - "-p", $$user[$PASSWD]); + @command = ($cmd_useradd, "-m"); push (@command, ("-d", $$user[$HOME])) if ($$user[$HOME]); push (@command, ("-s", $$user[$SHELL])) if ($$user[$SHELL]); @@ -695,6 +624,7 @@ sub add_user } &change_user_chfn ($$user[$LOGIN], undef, $$user[$COMMENT]); + &set_passwd ($$user[$LOGIN], $$user[$PASSWD]); } sub change_user @@ -703,38 +633,20 @@ sub change_user if ($Utils::Backend::tool{"system"} eq "FreeBSD") { - my $pwdpipe; - - $command = "$cmd_pw usermod \'" . $$old_user[$LOGIN] . "\'" . - " -l \'" . $$new_user[$LOGIN] . "\'" . - " -u \'" . $$new_user[$UID] . "\'" . - " -d \'" . $$new_user[$HOME] . "\'" . - " -g \'" . $$new_user[$GID] . "\'" . - " -s \'" . $$new_user[$SHELL] . "\'" . - " -H 0"; # pw(8) reads password from STDIN - - $pwdpipe = &Utils::File::run_pipe_write ($command); - print $pwdpipe $$new_user[$PASSWD]; - &Utils::File::close_file ($pwdpipe); - } - elsif ($Utils::Backend::tool{"system"} eq "SunOS") - { - @command = ($cmd_usermod, "-d", $$new_user[$HOME], - "-g", $$new_user[$GID], - "-l", $$new_user[$LOGIN], - "-s", $$new_user[$SHELL], - "-u", $$new_user[$UID], - $$old_user[$LOGIN]); + @command = ($cmd_pw, "usermod", $$old_user[$LOGIN], + "-l", $$new_user[$LOGIN], + "-u", $$new_user[$UID], + "-d", $$new_user[$HOME], + "-g", $$new_user[$GID], + "-s", $$new_user[$SHELL]); &Utils::File::run (@command); - &modify_shadow_password ($$new_user[$LOGIN], $$new_user[$PASSWD]); } else { @command = ($cmd_usermod, "-d", $$new_user[$HOME], "-g", $$new_user[$GID], "-l", $$new_user[$LOGIN], - "-p", $$new_user[$PASSWD], "-s", $$new_user[$SHELL], "-u", $$new_user[$UID], $$old_user[$LOGIN]); @@ -743,6 +655,7 @@ sub change_user } &change_user_chfn ($$new_user[$LOGIN], $$old_user[$COMMENT], $$new_user[$COMMENT]); + &set_passwd ($$new_user[$LOGIN], $$new_user[$PASSWD]); } sub set_logindefs diff --git a/UsersConfig.pm b/UsersConfig.pm index 50c4ad4..562aca1 100644 --- a/UsersConfig.pm +++ b/UsersConfig.pm @@ -32,11 +32,11 @@ use Users::Shells; my $OBJECT_NAME = "UsersConfig2"; my $OBJECT_PATH = "$Utils::Backend::DBUS_PATH/$OBJECT_NAME"; -# settings: list of shells, use MD5, umin, umax, home prefix, default shell, default group, encrypted home support +# settings: list of shells, umin, umax, home prefix, default shell, default group, encrypted home support # only configuration settings are set via UsersConfig -my $set_format = [ [ "array", "string" ], "bool", "uint32", "uint32", "string", "string", "uint32", "bool" ]; +my $set_format = [ [ "array", "string" ], "uint32", "uint32", "string", "string", "uint32", "bool" ]; # array of users plus configuration settings -my $get_format = [[ "array", $UserConfig::USER_FORMAT ], [ "array", "string" ], "bool", "uint32", "uint32", "string", "string", "uint32", "bool" ]; +my $get_format = [[ "array", $UserConfig::USER_FORMAT ], [ "array", "string" ], "uint32", "uint32", "string", "string", "uint32", "bool" ]; sub new @@ -55,15 +55,14 @@ dbus_method ("set", $set_format, []); sub get { my ($self) = @_; - my $logindefs, $users, $use_md5, $shells; + my $logindefs, $users, $shells; $self->SUPER::reset_counter (); - $use_md5 = &Users::Users::get_use_md5 (); $logindefs = &Users::Users::get_logindefs (); $users = &Users::Users::get (); $shells = &Users::Shells::get (); - return ($users, $shells, $use_md5, $$logindefs{"umin"}, + return ($users, $shells, $$logindefs{"umin"}, $$logindefs{"umax"}, $$logindefs{"home_prefix"}, $$logindefs{"shell"}, $$logindefs{"group"}, 0); } -- cgit v1.2.3