Blob Blame History Raw
From d7da2966f5931bac3b17f42e251adbbb7e793619 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Thu, 8 Dec 2022 15:14:05 +0100
Subject: [PATCH] ldap: update shadow last change in sysdb as well
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Otherwise pam can use the changed information whe id chaching is
enabled, so next authentication that fits into the id timeout
(5 seconds by default) will still sees the password as expired.

Resolves: https://github.com/SSSD/sssd/issues/6477

Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Tomáš Halman <thalman@redhat.com>
(cherry picked from commit 7e8b97c14b8ef218d6ea23214be28d25dba13886)
---
 src/db/sysdb.h                 |  4 ++++
 src/db/sysdb_ops.c             | 32 ++++++++++++++++++++++++++++++++
 src/providers/ldap/ldap_auth.c | 21 ++++++++++++++++-----
 3 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 7c666f5c4..06b44f5ba 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -1061,6 +1061,10 @@ int sysdb_set_user_attr(struct sss_domain_info *domain,
                         struct sysdb_attrs *attrs,
                         int mod_op);
 
+errno_t sysdb_update_user_shadow_last_change(struct sss_domain_info *domain,
+                                             const char *name,
+                                             const char *attrname);
+
 /* Replace group attrs */
 int sysdb_set_group_attr(struct sss_domain_info *domain,
                          const char *name,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 0d6f2d5cd..ed0df9872 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -1485,6 +1485,38 @@ done:
     return ret;
 }
 
+errno_t sysdb_update_user_shadow_last_change(struct sss_domain_info *domain,
+                                             const char *name,
+                                             const char *attrname)
+{
+    struct sysdb_attrs *attrs;
+    char *value;
+    errno_t ret;
+
+    attrs = sysdb_new_attrs(NULL);
+    if (attrs == NULL) {
+        return ENOMEM;
+    }
+
+    /* The attribute contains number of days since the epoch */
+    value = talloc_asprintf(attrs, "%ld", (long)time(NULL)/86400);
+    if (value == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    ret = sysdb_attrs_add_string(attrs, attrname, value);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    ret = sysdb_set_user_attr(domain, name, attrs, SYSDB_MOD_REP);
+
+done:
+    talloc_free(attrs);
+    return ret;
+}
+
 /* =Replace-Attributes-On-Group=========================================== */
 
 int sysdb_set_group_attr(struct sss_domain_info *domain,
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 6404a9d3a..96b9d6df4 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -1240,6 +1240,7 @@ struct sdap_pam_chpass_handler_state {
     struct pam_data *pd;
     struct sdap_handle *sh;
     char *dn;
+    enum pwexpire pw_expire_type;
 };
 
 static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq);
@@ -1339,7 +1340,6 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
 {
     struct sdap_pam_chpass_handler_state *state;
     struct tevent_req *req;
-    enum pwexpire pw_expire_type;
     void *pw_expire_data;
     size_t msg_len;
     uint8_t *msg;
@@ -1349,7 +1349,7 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
     state = tevent_req_data(req, struct sdap_pam_chpass_handler_state);
 
     ret = auth_recv(subreq, state, &state->sh, &state->dn,
-                    &pw_expire_type, &pw_expire_data);
+                    &state->pw_expire_type, &pw_expire_data);
     talloc_free(subreq);
 
     if ((ret == EOK || ret == ERR_PASSWORD_EXPIRED) &&
@@ -1361,7 +1361,7 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
     }
 
     if (ret == EOK) {
-        switch (pw_expire_type) {
+        switch (state->pw_expire_type) {
         case PWEXPIRE_SHADOW:
             ret = check_pwexpire_shadow(pw_expire_data, time(NULL), NULL);
             break;
@@ -1381,7 +1381,8 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
             break;
         default:
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "Unknown password expiration type %d.\n", pw_expire_type);
+                  "Unknown password expiration type %d.\n",
+                  state->pw_expire_type);
             state->pd->pam_status = PAM_SYSTEM_ERR;
             goto done;
         }
@@ -1392,7 +1393,8 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
         case ERR_PASSWORD_EXPIRED:
             DEBUG(SSSDBG_TRACE_LIBS,
                   "user [%s] successfully authenticated.\n", state->dn);
-            ret = sdap_pam_chpass_handler_change_step(state, req, pw_expire_type);
+            ret = sdap_pam_chpass_handler_change_step(state, req,
+                                                      state->pw_expire_type);
             if (ret != EOK) {
                 DEBUG(SSSDBG_OP_FAILURE,
                       "sdap_pam_chpass_handler_change_step() failed.\n");
@@ -1506,6 +1508,15 @@ static void sdap_pam_chpass_handler_chpass_done(struct tevent_req *subreq)
 
     switch (ret) {
     case EOK:
+        if (state->pw_expire_type == PWEXPIRE_SHADOW) {
+            ret = sysdb_update_user_shadow_last_change(state->be_ctx->domain,
+                    state->pd->user, SYSDB_SHADOWPW_LASTCHANGE);
+            if (ret != EOK) {
+                state->pd->pam_status = PAM_SYSTEM_ERR;
+                goto done;
+            }
+        }
+
         state->pd->pam_status = PAM_SUCCESS;
         break;
     case ERR_CHPASS_DENIED:
-- 
2.37.3