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

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