Blob Blame History Raw
From 10f9b55084a1b7d251752d5d9fe85f9d01fe93d7 Mon Sep 17 00:00:00 2001
From: Arthur de Jong <arthur@arthurdejong.org>
Date: Fri, 14 Aug 2015 23:09:50 +0200
Subject: [PATCH 20/23] Simplify password policy message handling

This simplifies the check for overwriging pending password expiry and
grace logins warnigns and updates handling of the
LDAP_CONTROL_PWEXPIRING control to be consistent with that of the expire
value of LDAP_CONTROL_PASSWORDPOLICYRESPONSE.

This also corrects the function name, also logs empty password policy
responses in debug mode and documents the meaning of the various
password policy values.

(cherry picked from commit 263a44340badb1e553c997f2dfb4986fb2f4c28b)
---
 nslcd/myldap.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/nslcd/myldap.c b/nslcd/myldap.c
index 9a24a27..86a339e 100644
--- a/nslcd/myldap.c
+++ b/nslcd/myldap.c
@@ -405,7 +405,7 @@ static int do_sasl_interact(LDAP UNUSED(*ld),unsigned UNUSED(flags),void *defaul
 #endif /* HAVE_SASL_INTERACT_T */
 
 #if defined(HAVE_LDAP_SASL_BIND) && defined(LDAP_SASL_SIMPLE)
-static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPControl **ctrls)
+static void handle_ppolicy_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPControl **ctrls)
 {
   int i;
   int rc;
@@ -433,10 +433,9 @@ static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPContr
       sec = atol(seconds);
       log_log(LOG_DEBUG, "got LDAP_CONTROL_PWEXPIRING (password will expire in %ld seconds)",
               sec);
-      /* return this warning to PAM */
-      if (session->policy_response == NSLCD_PAM_SUCCESS)
+      /* return this warning so PAM can present it to the user */
+      if (strlen(session->policy_message) == 0)
       {
-        session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
         mysnprintf(session->policy_message, sizeof(session->policy_message),
                    "password will expire in %ld seconds",  sec);
       }
@@ -452,9 +451,8 @@ static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPContr
       else
       {
         /* log returned control information */
-        if (error != PP_noError)
-          log_log(LOG_DEBUG, "got LDAP_CONTROL_PASSWORDPOLICYRESPONSE (%s)",
-                  ldap_passwordpolicy_err2txt(error));
+        log_log(LOG_DEBUG, "got LDAP_CONTROL_PASSWORDPOLICYRESPONSE (%s)",
+                ldap_passwordpolicy_err2txt(error));
         if (expire >= 0)
           log_log(LOG_DEBUG, "got LDAP_CONTROL_PASSWORDPOLICYRESPONSE (password will expire in %d seconds)",
                   expire);
@@ -466,6 +464,7 @@ static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPContr
             ((session->policy_response == NSLCD_PAM_SUCCESS) ||
              (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
         {
+          /* this means that the password has expired and must be reset */
           session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
           mysnprintf(session->policy_message, sizeof(session->policy_message),
                      "%s", ldap_passwordpolicy_err2txt(error));
@@ -474,6 +473,8 @@ static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPContr
                  ((session->policy_response == NSLCD_PAM_SUCCESS) ||
                   (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
         {
+          /* this means that the account is locked and the user cannot log
+             in (the bind probably failed already) */
           session->policy_response = NSLCD_PAM_ACCT_EXPIRED;
           mysnprintf(session->policy_message, sizeof(session->policy_message),
                      "%s", ldap_passwordpolicy_err2txt(error));
@@ -481,6 +482,8 @@ static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPContr
         else if ((error == PP_changeAfterReset) &&
                  (session->policy_response == NSLCD_PAM_SUCCESS))
         {
+          /* this indicates that the password must be changed before the
+             user is allowed to perform any other operation */
           session->policy_response = NSLCD_PAM_NEW_AUTHTOK_REQD;
           mysnprintf(session->policy_message, sizeof(session->policy_message),
                      "%s", ldap_passwordpolicy_err2txt(error));
@@ -489,20 +492,23 @@ static void handle_ppasswd_controls(MYLDAP_SESSION *session, LDAP *ld, LDAPContr
                  ((session->policy_response == NSLCD_PAM_SUCCESS) ||
                   (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
         {
+          /* any other error is assumed to mean that the operation failed */
           session->policy_response = NSLCD_PAM_PERM_DENIED;
           mysnprintf(session->policy_message, sizeof(session->policy_message),
                      "%s", ldap_passwordpolicy_err2txt(error));
         }
-        else if ((expire >= 0) &&
-                 ((session->policy_response == NSLCD_PAM_SUCCESS) ||
-                  (session->policy_response == NSLCD_PAM_NEW_AUTHTOK_REQD)))
+        /* both expire and grace should just be warnings to the user */
+        if ((expire >= 0) && (strlen(session->policy_message) == 0))
         {
+          /* if no other error has happened, this indicates that the password
+             will soon expire (number of seconds) */
           mysnprintf(session->policy_message, sizeof(session->policy_message),
                      "Password will expire in %d seconds", expire);
         }
-        else if ((grace >= 0) &&
-                 (session->policy_response == NSLCD_PAM_SUCCESS))
+        else if ((grace >= 0) && (strlen(session->policy_message) == 0))
         {
+          /* this indicates the number of grace logins that are left before
+             no further login attempts will be allowed */
           mysnprintf(session->policy_message, sizeof(session->policy_message),
                      "Password expired, %d grace logins left", grace);
         }
@@ -576,7 +582,7 @@ static int do_ppolicy_bind(MYLDAP_SESSION *session, LDAP *ld, const char *uri)
   /* handle any returned controls */
   if (responsectrls != NULL)
   {
-    handle_ppasswd_controls(session, ld, responsectrls);
+    handle_ppolicy_controls(session, ld, responsectrls);
     ldap_controls_free(responsectrls);
   }
   /* return the result of the BIND operation */
-- 
2.20.1