Blame SOURCES/0001-ldap-update-shadow-last-change-in-sysdb-as-well.patch

8ea3d3
From d7da2966f5931bac3b17f42e251adbbb7e793619 Mon Sep 17 00:00:00 2001
8ea3d3
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
8ea3d3
Date: Thu, 8 Dec 2022 15:14:05 +0100
8ea3d3
Subject: [PATCH] ldap: update shadow last change in sysdb as well
8ea3d3
MIME-Version: 1.0
8ea3d3
Content-Type: text/plain; charset=UTF-8
8ea3d3
Content-Transfer-Encoding: 8bit
8ea3d3
8ea3d3
Otherwise pam can use the changed information whe id chaching is
8ea3d3
enabled, so next authentication that fits into the id timeout
8ea3d3
(5 seconds by default) will still sees the password as expired.
8ea3d3
8ea3d3
Resolves: https://github.com/SSSD/sssd/issues/6477
8ea3d3
8ea3d3
Reviewed-by: Sumit Bose <sbose@redhat.com>
8ea3d3
Reviewed-by: Tomáš Halman <thalman@redhat.com>
8ea3d3
(cherry picked from commit 7e8b97c14b8ef218d6ea23214be28d25dba13886)
8ea3d3
---
8ea3d3
 src/db/sysdb.h                 |  4 ++++
8ea3d3
 src/db/sysdb_ops.c             | 32 ++++++++++++++++++++++++++++++++
8ea3d3
 src/providers/ldap/ldap_auth.c | 21 ++++++++++++++++-----
8ea3d3
 3 files changed, 52 insertions(+), 5 deletions(-)
8ea3d3
8ea3d3
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
8ea3d3
index 7c666f5c4..06b44f5ba 100644
8ea3d3
--- a/src/db/sysdb.h
8ea3d3
+++ b/src/db/sysdb.h
8ea3d3
@@ -1061,6 +1061,10 @@ int sysdb_set_user_attr(struct sss_domain_info *domain,
8ea3d3
                         struct sysdb_attrs *attrs,
8ea3d3
                         int mod_op);
8ea3d3
 
8ea3d3
+errno_t sysdb_update_user_shadow_last_change(struct sss_domain_info *domain,
8ea3d3
+                                             const char *name,
8ea3d3
+                                             const char *attrname);
8ea3d3
+
8ea3d3
 /* Replace group attrs */
8ea3d3
 int sysdb_set_group_attr(struct sss_domain_info *domain,
8ea3d3
                          const char *name,
8ea3d3
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
8ea3d3
index 0d6f2d5cd..ed0df9872 100644
8ea3d3
--- a/src/db/sysdb_ops.c
8ea3d3
+++ b/src/db/sysdb_ops.c
8ea3d3
@@ -1485,6 +1485,38 @@ done:
8ea3d3
     return ret;
8ea3d3
 }
8ea3d3
 
8ea3d3
+errno_t sysdb_update_user_shadow_last_change(struct sss_domain_info *domain,
8ea3d3
+                                             const char *name,
8ea3d3
+                                             const char *attrname)
8ea3d3
+{
8ea3d3
+    struct sysdb_attrs *attrs;
8ea3d3
+    char *value;
8ea3d3
+    errno_t ret;
8ea3d3
+
8ea3d3
+    attrs = sysdb_new_attrs(NULL);
8ea3d3
+    if (attrs == NULL) {
8ea3d3
+        return ENOMEM;
8ea3d3
+    }
8ea3d3
+
8ea3d3
+    /* The attribute contains number of days since the epoch */
8ea3d3
+    value = talloc_asprintf(attrs, "%ld", (long)time(NULL)/86400);
8ea3d3
+    if (value == NULL) {
8ea3d3
+        ret = ENOMEM;
8ea3d3
+        goto done;
8ea3d3
+    }
8ea3d3
+
8ea3d3
+    ret = sysdb_attrs_add_string(attrs, attrname, value);
8ea3d3
+    if (ret != EOK) {
8ea3d3
+        goto done;
8ea3d3
+    }
8ea3d3
+
8ea3d3
+    ret = sysdb_set_user_attr(domain, name, attrs, SYSDB_MOD_REP);
8ea3d3
+
8ea3d3
+done:
8ea3d3
+    talloc_free(attrs);
8ea3d3
+    return ret;
8ea3d3
+}
8ea3d3
+
8ea3d3
 /* =Replace-Attributes-On-Group=========================================== */
8ea3d3
 
8ea3d3
 int sysdb_set_group_attr(struct sss_domain_info *domain,
8ea3d3
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
8ea3d3
index 6404a9d3a..96b9d6df4 100644
8ea3d3
--- a/src/providers/ldap/ldap_auth.c
8ea3d3
+++ b/src/providers/ldap/ldap_auth.c
8ea3d3
@@ -1240,6 +1240,7 @@ struct sdap_pam_chpass_handler_state {
8ea3d3
     struct pam_data *pd;
8ea3d3
     struct sdap_handle *sh;
8ea3d3
     char *dn;
8ea3d3
+    enum pwexpire pw_expire_type;
8ea3d3
 };
8ea3d3
 
8ea3d3
 static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq);
8ea3d3
@@ -1339,7 +1340,6 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
8ea3d3
 {
8ea3d3
     struct sdap_pam_chpass_handler_state *state;
8ea3d3
     struct tevent_req *req;
8ea3d3
-    enum pwexpire pw_expire_type;
8ea3d3
     void *pw_expire_data;
8ea3d3
     size_t msg_len;
8ea3d3
     uint8_t *msg;
8ea3d3
@@ -1349,7 +1349,7 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
8ea3d3
     state = tevent_req_data(req, struct sdap_pam_chpass_handler_state);
8ea3d3
 
8ea3d3
     ret = auth_recv(subreq, state, &state->sh, &state->dn,
8ea3d3
-                    &pw_expire_type, &pw_expire_data);
8ea3d3
+                    &state->pw_expire_type, &pw_expire_data);
8ea3d3
     talloc_free(subreq);
8ea3d3
 
8ea3d3
     if ((ret == EOK || ret == ERR_PASSWORD_EXPIRED) &&
8ea3d3
@@ -1361,7 +1361,7 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
8ea3d3
     }
8ea3d3
 
8ea3d3
     if (ret == EOK) {
8ea3d3
-        switch (pw_expire_type) {
8ea3d3
+        switch (state->pw_expire_type) {
8ea3d3
         case PWEXPIRE_SHADOW:
8ea3d3
             ret = check_pwexpire_shadow(pw_expire_data, time(NULL), NULL);
8ea3d3
             break;
8ea3d3
@@ -1381,7 +1381,8 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
8ea3d3
             break;
8ea3d3
         default:
8ea3d3
             DEBUG(SSSDBG_CRIT_FAILURE,
8ea3d3
-                  "Unknown password expiration type %d.\n", pw_expire_type);
8ea3d3
+                  "Unknown password expiration type %d.\n",
8ea3d3
+                  state->pw_expire_type);
8ea3d3
             state->pd->pam_status = PAM_SYSTEM_ERR;
8ea3d3
             goto done;
8ea3d3
         }
8ea3d3
@@ -1392,7 +1393,8 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq)
8ea3d3
         case ERR_PASSWORD_EXPIRED:
8ea3d3
             DEBUG(SSSDBG_TRACE_LIBS,
8ea3d3
                   "user [%s] successfully authenticated.\n", state->dn);
8ea3d3
-            ret = sdap_pam_chpass_handler_change_step(state, req, pw_expire_type);
8ea3d3
+            ret = sdap_pam_chpass_handler_change_step(state, req,
8ea3d3
+                                                      state->pw_expire_type);
8ea3d3
             if (ret != EOK) {
8ea3d3
                 DEBUG(SSSDBG_OP_FAILURE,
8ea3d3
                       "sdap_pam_chpass_handler_change_step() failed.\n");
8ea3d3
@@ -1506,6 +1508,15 @@ static void sdap_pam_chpass_handler_chpass_done(struct tevent_req *subreq)
8ea3d3
 
8ea3d3
     switch (ret) {
8ea3d3
     case EOK:
8ea3d3
+        if (state->pw_expire_type == PWEXPIRE_SHADOW) {
8ea3d3
+            ret = sysdb_update_user_shadow_last_change(state->be_ctx->domain,
8ea3d3
+                    state->pd->user, SYSDB_SHADOWPW_LASTCHANGE);
8ea3d3
+            if (ret != EOK) {
8ea3d3
+                state->pd->pam_status = PAM_SYSTEM_ERR;
8ea3d3
+                goto done;
8ea3d3
+            }
8ea3d3
+        }
8ea3d3
+
8ea3d3
         state->pd->pam_status = PAM_SUCCESS;
8ea3d3
         break;
8ea3d3
     case ERR_CHPASS_DENIED:
8ea3d3
-- 
8ea3d3
2.37.3
8ea3d3