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