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

[patch] pam_unix_passwd PAM_AUTHTOK stacking bug



I am writing a module that is stacked below pam_unix in order to have 
access to PAM_OLDAUTHTOK and PAM_AUTHTOK after a password change.  
Normally, this works great: a non-null PAM_AUTHTOK is passed down the 
stack only upon a successful password change. However, in certain 
situations, a non-null PAM_AUTHTOK is passed down the stack after a 
failed password change.  For example, using a module which simply prints 
out PAM_OLDAUTHTOK and PAM_AUTHTOK and is stacked below pam_unix, we can 
see the following exchange:

[user@redhat72 user]$ passwd
Changing password for user
(current) UNIX password: [password]
stacked module: old authtok obtained for user user: password
stacked module: new authtok obtained for user user: (null)
Enter new UNIX password: [a]
Retype new UNIX password: [a]
You must choose a longer password
Enter new UNIX password: [a]
Retype new UNIX password: [a]
You must choose a longer password
Enter new UNIX password: [a]
Retype new UNIX password: [a]
You must choose a longer password
stacked module: old authtok obtained for user user: arrowhead
stacked module: new authtok obtained for user user: a
passwd: Authentication token manipulation error

So, here the stacked module thinks that the password has been 
successfully changed to "a", when it, in fact, has not.

I went into the code and discovered that the problem was 
pam_sm_chauthtok() calls _unix_read_password(), which sets PAM_AUTHTOK to 
the new password, but pam_sm_chauthtok() does not set it back to NULL if 
a subsequent error occurs (e.g. _pam_unix_approve_pass() fails).  I have 
attached a patch which fixes this problem by setting PAM_AUTHTOK to NULL 
before returning such an error.


Matt

(note: patch is based on revision 1.12 of pam_unix_passwd.c)
--- pam_unix_passwd.c.orig      Fri Aug  2 21:27:48 2002
+++ pam_unix_passwd.c   Fri Aug  2 21:37:24 2002
@@ -931,6 +931,9 @@
                         _log_err(LOG_NOTICE, pamh,
                                  "new password not acceptable");
                         pass_new = pass_old = NULL;     /* tidy up */
+                       if (off(UNIX_NOT_SET_PASS, ctrl)) {
+                               pam_set_item(pamh, PAM_AUTHTOK, NULL);
+                       }
  #ifdef USE_LCKPWDF
                         ulckpwdf();
  #endif
@@ -974,6 +977,9 @@
                                         _log_err(LOG_CRIT, pamh,
                                                  "out of memory for password");
                                         pass_new = pass_old = NULL;     /* tidy up */
+                                       if (off(UNIX_NOT_SET_PASS, ctrl)) {
+                                               pam_set_item(pamh, PAM_AUTHTOK, NULL);
+                                       }
  #ifdef USE_LCKPWDF
                                         ulckpwdf();
  #endif
@@ -1008,9 +1014,17 @@

         D(("retval was %d", retval));

+       if (retval != PAM_SUCCESS) {
+               pass_new = pass_old = NULL;     /* tidy up */
+               if (off(UNIX_NOT_SET_PASS, ctrl)) {
+                       pam_set_item(pamh, PAM_AUTHTOK, NULL);
+               }
+       }
+
  #ifdef USE_LCKPWDF
         ulckpwdf();
  #endif
+
         return retval;
  }


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