Blob Blame History Raw
From bfafa12ae83bcdec53bb306f68eff9e6acfbb4a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Fri, 20 Jul 2018 12:15:18 +0200
Subject: [PATCH] sdap: respect passwordGracelimit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Since recent changes in 389-ds two response controls are end when
passwordGracelimit is set and about to expire:
- [1.3.6.1.4.1.42.2.27.8.5.1] for the GraceLimit itself
- [2.16.840.1.113730.3.4.4] for the PasswordExpired

Whenever the former is returned and the GraceLimit is still valid, we
shouldn't report the latter to the users.

Resolves:
https://pagure.io/SSSD/sssd/issue/3597

Signed-off-by: Fabiano FidĂȘncio <fidencio@redhat.com>

Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
(cherry picked from commit 954bf82b60b7cfd93b865a6618f155d042b15729)

DOWNSTREAM:
Resolves: rhbz#1522928 - sssd doesn't allow user with expired password
to login when PasswordgraceLimit set
---
 src/providers/ldap/sdap_async_connection.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index a8d4262b52c4b2d2810450d68794f00558ea5c2d..8aacd6705a1f82be8c14f97996786ac9b47396d5 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -734,6 +734,7 @@ static void simple_bind_done(struct sdap_op *op,
     ber_int_t pp_expire;
     LDAPPasswordPolicyError pp_error;
     int result = LDAP_OTHER;
+    bool on_grace_login_limit = false;
 
     if (error) {
         tevent_req_error(req, error);
@@ -772,6 +773,7 @@ static void simple_bind_done(struct sdap_op *op,
             DEBUG(SSSDBG_TRACE_INTERNAL,
                   "Server returned control [%s].\n",
                    response_controls[c]->ldctl_oid);
+
             if (strcmp(response_controls[c]->ldctl_oid,
                        LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) {
                 lret = ldap_parse_passwordpolicy_control(state->sh->ldap,
@@ -799,13 +801,26 @@ static void simple_bind_done(struct sdap_op *op,
                 state->ppolicy->grace = pp_grace;
                 state->ppolicy->expire = pp_expire;
                 if (result == LDAP_SUCCESS) {
-
+                    /* We have to set the on_grace_login_limit as when going
+                     * through the response controls 389-ds may return both
+                     * an warning and an error (and the order is not ensured)
+                     * for the GraceLimit:
+                     * - [1.3.6.1.4.1.42.2.27.8.5.1] for the GraceLimit itself
+                     * - [2.16.840.1.113730.3.4.4] for the PasswordExpired
+                     *
+                     * So, in order to avoid bulldozing the GraceLimit, let's
+                     * set it to true when pp_grace >= 0 and, in the end of
+                     * this function, just return EOK when LDAP returns the
+                     * PasswordExpired error but the GraceLimit is still valid.
+                     */
+                    on_grace_login_limit = false;
                     if (pp_error == PP_changeAfterReset) {
                         DEBUG(SSSDBG_TRACE_LIBS,
                               "Password was reset. "
                                "User must set a new password.\n");
                         ret = ERR_PASSWORD_EXPIRED;
                     } else if (pp_grace >= 0) {
+                        on_grace_login_limit = true;
                         DEBUG(SSSDBG_TRACE_LIBS,
                               "Password expired. "
                                "[%d] grace logins remaining.\n",
@@ -875,6 +890,10 @@ static void simple_bind_done(struct sdap_op *op,
         ret = ERR_AUTH_FAILED;
     }
 
+    if (ret == ERR_PASSWORD_EXPIRED && on_grace_login_limit) {
+        ret = EOK;
+    }
+
 done:
     ldap_controls_free(response_controls);
     ldap_memfree(errmsg);
-- 
2.14.4