[system-tools-backends-clone] Support password (un)locking



commit 3c749d747438afce2a420000c474e7bc3164a7be
Author: Milan Bouchet-Valat <nalimilan club fr>
Date:   Sun Mar 7 15:36:24 2010 +0100

    Support password (un)locking
    
    Detect whether an account's password is locked in /etc/shadow by running 'passwd -S'. Support locking and unlocking of an account. Use 'passwd -d' when setting an empty password, as chpasswd doesn't support it.

 Users/Users.pm |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 54 insertions(+), 5 deletions(-)
---
diff --git a/Users/Users.pm b/Users/Users.pm
index 04a9637..11b9c90 100644
--- a/Users/Users.pm
+++ b/Users/Users.pm
@@ -347,7 +347,7 @@ sub get_logindefs
 
 sub get
 {
-  my ($ifh, @users, %users_hash);
+  my ($ifh, @users, %users_hash, $fd, @passwd_status);
   my (@line, @users);
 
   # Find the passwd file.
@@ -381,11 +381,30 @@ sub get
 
     $users_hash{$login} = [ line];
 
+    # Detect lock status of password
+    # We run 'passwd' instead of reading /etc/shadow directly
+    # to avoid leaving sensitive data in memory (hard to clear in perl)
+    $fd = &Utils::File::run_pipe_read ("passwd -S $login");
+    @passwd_status = split ' ', <$fd>;
+    &Utils::File::close_file ($fd);
+
+    if ($passwd_status[1] eq "P")
+    {
+      $users_hash{$login}[$PASSWD_STATUS] = 0;
+    }
+    elsif ($passwd_status[1] eq "NP")
+    {
+      $users_hash{$login}[$PASSWD_STATUS] = 1;
+    }
+    else # "L", means locked password
+    {
+      $users_hash{$login}[$PASSWD_STATUS] = 1 << 1;
+    }
+
     # max value for an unsigned 32 bits integer means no main group
     $users_hash{$login}[$GID] = 0xFFFFFFFF if (!$users_hash{$login}[$GID]);
 
     # TODO: read actual values
-    $users_hash{$login}[$PASSWD_STATUS] = 0;
     $users_hash{$login}[$ENC_HOME] = 0;
     $users_hash{$login}[$HOME_FLAGS] = 0;
     $users_hash{$login}[$LOCALE] = "";
@@ -475,9 +494,16 @@ sub change_user_chfn
 
 sub set_passwd
 {
-  my ($login, $password) = @_;
+  my ($login, $password, $passwd_status) = @_;
   my ($pwdpipe);
 
+  # handle empty password via passwd, as all tools don't support it
+  if ($passwd_status & 1)
+  {
+    &Utils::File::run ("passwd", "-d", $login);
+    return;
+  }
+
   if ($Utils::Backend::tool{"system"} eq "FreeBSD")
   {
     my ($command);
@@ -502,6 +528,22 @@ sub set_passwd
   }
 }
 
+# Enable/disable password, only call if value has changed
+sub set_lock
+{
+  my ($login, $passwd_status) = @_;
+  my ($pwdpipe);
+
+  if ($passwd_status & (1 << 1))
+  {
+    &Utils::File::run ("passwd", "-l", $login);
+  }
+  else
+  {
+    &Utils::File::run ("passwd", "-u", $login);
+  }
+}
+
 # This function allows empty values to be passed, in which cas
 # the platform's tools will choose the default.
 sub add_user
@@ -616,7 +658,8 @@ sub add_user
   }
 
   &change_user_chfn ($$user[$LOGIN], undef, $$user[$COMMENT]);
-  &set_passwd ($$user[$LOGIN], $$user[$PASSWD]);
+  &set_passwd ($$user[$LOGIN], $$user[$PASSWD], $$user[$PASSWD_STATUS]);
+  &set_lock ($$user[$LOGIN], $$user[$PASSWD_STATUS]);
 
   # Return the new user with default values filled.
   # Returns NULL if user doesn't exist, which means failure.
@@ -651,7 +694,13 @@ sub change_user
   }
 
   &change_user_chfn ($$new_user[$LOGIN], $$old_user[$COMMENT], $$new_user[$COMMENT]);
-  &set_passwd ($$new_user[$LOGIN], $$new_user[$PASSWD]);
+  &set_passwd ($$new_user[$LOGIN], $$new_user[$PASSWD], $$user[$PASSWD_STATUS]);
+
+  # Only change lock status if status has changed
+  if (($$new_user[$PASSWD_STATUS] & (1 << 1)) != ($$user[$PASSWD_STATUS] & (1 << 1)))
+  {
+    &set_lock ($$user[$LOGIN], $$new_user[$PASSWD_STATUS]);
+  }
 
   # Erase password string to avoid it from staying in memory
   $$new_user[$PASSWD] = '0' x length ($$new_user[$PASSWD]);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]