From 10f9b55084a1b7d251752d5d9fe85f9d01fe93d7 Mon Sep 17 00:00:00 2001 From: Arthur de Jong 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