[SSSD] [PATCH] Add more warnings about nearly expired passwords

Sumit Bose sbose at redhat.com
Tue Apr 27 15:50:32 UTC 2010


Hi,

this patch is (hopefully) the final patch in a series of patches to fix
#420 '[RFE] Password Expiration Notification'. The other patch in this
series are:

- 'Improvements for LDAP Password Policy support' which is already
  commited and handles the case of LDAP server password policies
- 'Handle Krb5 password expiration warning' which handles the warning
  for the Kerberos provider

bye,
Sumit
-------------- next part --------------
From 2bc2ce2d6df038ca1cca1edb6daf040d1878d0bc Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Thu, 22 Apr 2010 15:28:50 +0200
Subject: [PATCH] Add more warnings about nearly expired passwords

For the shadow and mit_kerberos password policy warnings are sent to the
client if the password is about to expire.
---
 src/providers/ldap/ldap_auth.c |   71 +++++++++++++++++++++++++++++++++++++---
 1 files changed, 66 insertions(+), 5 deletions(-)

diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 95931ac..6be7ee0 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -46,6 +46,12 @@
 #include "providers/ldap/ldap_common.h"
 #include "providers/ldap/sdap_async.h"
 
+/* MIT Kerberos has the same hardcoded warning interval of 7 days. Due to the
+ * fact that using the expiration time of a Kerberos password with LDAP
+ * authentication is presumably a rare case a separate config option is not
+ * necessary. */
+#define KERBEROS_PWEXPIRE_WARNING_TIME (7 * 24 * 60 * 60)
+
 enum pwexpire {
     PWEXPIRE_NONE = 0,
     PWEXPIRE_LDAP_PASSWORD_POLICY,
@@ -53,12 +59,42 @@ enum pwexpire {
     PWEXPIRE_SHADOW
 };
 
+static errno_t add_expired_warning(struct pam_data *pd, long exp_time)
+{
+    int ret;
+    uint32_t *data;
+
+    if (exp_time < 0 || exp_time > UINT32_MAX) {
+        DEBUG(1, ("Time to expire out of range.\n"));
+        return EINVAL;
+    }
+
+    data = talloc_array(pd, uint32_t, 2);
+    if (data == NULL) {
+        DEBUG(1, ("talloc_size failed.\n"));
+        return ENOMEM;
+    }
+
+    data[0] = SSS_PAM_USER_INFO_EXPIRE_WARN;
+    data[1] = (uint32_t) exp_time;
+
+    ret = pam_add_response(pd, SSS_PAM_USER_INFO, 2 * sizeof(uint32_t),
+                           (uint8_t *) data);
+    if (ret != EOK) {
+        DEBUG(1, ("pam_add_response failed.\n"));
+    }
+
+    return EOK;
+}
+
 static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now,
+                                       struct pam_data *pd,
                                        enum sdap_result *result)
 {
     char *end;
     struct tm tm;
     time_t expire_time;
+    int ret;
 
     memset(&tm, 0, sizeof(tm));
 
@@ -92,16 +128,27 @@ static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now,
         *result = SDAP_AUTH_PW_EXPIRED;
     } else {
         *result = SDAP_AUTH_SUCCESS;
+
+        if (pd != NULL &&
+            difftime(now + KERBEROS_PWEXPIRE_WARNING_TIME, expire_time) > 0.0) {
+            ret = add_expired_warning(pd, (long) difftime(expire_time, now));
+            if (ret != EOK) {
+                DEBUG(1, ("add_expired_warning failed.\n"));
+            }
+        }
     }
 
     return EOK;
 }
 
 static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now,
+                                     struct pam_data *pd,
                                      enum sdap_result *result)
 {
     long today;
     long password_age;
+    long exp;
+    int ret;
 
     if (spwd->sp_lstchg <= 0) {
         DEBUG(4, ("Last change day is not set, new password needed.\n"));
@@ -132,7 +179,21 @@ static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now,
         return EOK;
     }
 
-/* TODO: evaluate spwd->min and spwd->warn */
+    if (pd != NULL && spwd->sp_max != -1 && spwd->sp_warn != -1 &&
+        password_age > spwd->sp_max - spwd->sp_warn ) {
+
+        /* add_expired_warning() expects time in seconds */
+        exp = (spwd->sp_max - password_age) * (60 * 60 * 24);
+        if (exp == 0) {
+            /* Seconds until next midnight */
+            exp = ((today + 1) * (60 * 60 * 24)) - now;
+        }
+
+        ret = add_expired_warning(pd, exp);
+        if (ret != EOK) {
+            DEBUG(1, ("add_expired_warning failed.\n"));
+        }
+    }
 
     *result = SDAP_AUTH_SUCCESS;
     return EOK;
@@ -718,7 +779,7 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
     if (result == SDAP_AUTH_SUCCESS) {
         switch (pw_expire_type) {
             case PWEXPIRE_SHADOW:
-                ret = check_pwexpire_shadow(pw_expire_data, time(NULL),
+                ret = check_pwexpire_shadow(pw_expire_data, time(NULL), NULL,
                                             &result);
                 if (ret != EOK) {
                     DEBUG(1, ("check_pwexpire_shadow failed.\n"));
@@ -727,7 +788,7 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
                 }
                 break;
             case PWEXPIRE_KERBEROS:
-                ret = check_pwexpire_kerberos(pw_expire_data, time(NULL),
+                ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), NULL,
                                               &result);
                 if (ret != EOK) {
                     DEBUG(1, ("check_pwexpire_kerberos failed.\n"));
@@ -927,7 +988,7 @@ static void sdap_pam_auth_done(struct tevent_req *req)
         switch (pw_expire_type) {
             case PWEXPIRE_SHADOW:
                 ret = check_pwexpire_shadow(pw_expire_data, time(NULL),
-                                            &result);
+                                            state->pd, &result);
                 if (ret != EOK) {
                     DEBUG(1, ("check_pwexpire_shadow failed.\n"));
                     state->pd->pam_status = PAM_SYSTEM_ERR;
@@ -936,7 +997,7 @@ static void sdap_pam_auth_done(struct tevent_req *req)
                 break;
             case PWEXPIRE_KERBEROS:
                 ret = check_pwexpire_kerberos(pw_expire_data, time(NULL),
-                                              &result);
+                                              state->pd, &result);
                 if (ret != EOK) {
                     DEBUG(1, ("check_pwexpire_kerberos failed.\n"));
                     state->pd->pam_status = PAM_SYSTEM_ERR;
-- 
1.6.6.1



More information about the sssd-devel mailing list