[SSSD] [PATCH] Add support for ADS pwdLastSet

Pierre Carrier prc at redhat.com
Sun Apr 10 09:58:34 UTC 2011


Documented on http://msdn.microsoft.com/en-us/library/cc220785(v=prot.10).aspx

Introduced in nss_ldap 208:
* add support for native Active Directory password
  policy attributes (enabled if shadowLastChange is
  mapped to pwdLastSet)
---
 src/config/SSSDConfig.py                 |    1 +
 src/config/etc/sssd.api.d/sssd-ldap.conf |    1 +
 src/man/sssd-ldap.5.xml                  |   15 ++++++++++
 src/providers/ldap/ldap_auth.c           |    9 +++++-
 src/providers/ldap/ldap_common.c         |   43 ++++++++++++++++++++++++++++++
 src/providers/ldap/ldap_common.h         |    1 +
 src/providers/ldap/sdap.h                |    1 +
 7 files changed, 70 insertions(+), 1 deletions(-)

diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index 5135174..992e1f4 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -167,6 +167,7 @@ option_strings = {
     'ldap_user_modify_timestamp' : _('Modification time attribute'),
     #replaced by ldap_entry_usn# 'ldap_user_entry_usn' : _('entryUSN attribute'),
     'ldap_user_shadow_last_change' : _('shadowLastChange attribute'),
+    'ldap_user_ads_last_change' : _('pwdLastSet attribute'),
     'ldap_user_shadow_min' : _('shadowMin attribute'),
     'ldap_user_shadow_max' : _('shadowMax attribute'),
     'ldap_user_shadow_warning' : _('shadowWarning attribute'),
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
index 5fd0cfb..6700df9 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -51,6 +51,7 @@ ldap_user_member_of = str, None, false
 ldap_user_modify_timestamp = str, None, false
 ldap_user_entry_usn = str, None, false
 ldap_user_shadow_last_change = str, None, false
+ldap_user_ads_last_change = str, None, false
 ldap_user_shadow_min = str, None, false
 ldap_user_shadow_max = str, None, false
 ldap_user_shadow_warning = str, None, false
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index 2a39732..0db3ce7 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -313,6 +313,21 @@
                 </varlistentry>
 
                 <varlistentry>
+                    <term>ldap_user_ads_last_change (string)</term>
+                    <listitem>
+                        <para>
+                            When using ldap_pwd_policy=shadow, this parameter
+                            contains the name of an LDAP attribute corresponding
+                            to pwdLastSet in Active Directory server, fell back to
+                            when ldap_user_shadow_last_change was not available.
+                        </para>
+                        <para>
+                            Default: pwdLastSet
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
                     <term>ldap_user_shadow_min (string)</term>
                     <listitem>
                         <para>
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index e45d5b3..5ebd72c 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -286,7 +286,8 @@ static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx,
             return EINVAL;
         }
     } else if (strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) == 0) {
-        mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL);
+        mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL) |
+               ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_ADS_LASTCHANGE, NULL);
         if (mark != NULL) {
             DEBUG(9, ("Found shadow password expiration attributes.\n"))
             spwd = talloc_zero(mem_ctx, struct spwd);
@@ -297,6 +298,12 @@ static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx,
 
             val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL);
             ret = string_to_shadowpw_days(val, &spwd->sp_lstchg);
+            
+            /* Fallback to pwdLastSet for ADS */
+            if (ret != EOK) {
+                val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_ADS_LASTCHANGE, NULL);
+                ret = ads_pwdlastset_to_shadowpw_days(val, &spwd->sp_lstchg);
+            }
             if (ret != EOK) goto shadow_fail;
 
             val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MIN, NULL);
diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c
index 9eb9cc3..22c9bb7 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -163,6 +163,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
     { "ldap_user_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL },
     { "ldap_user_entry_usn", NULL, SYSDB_USN, NULL },
     { "ldap_user_shadow_last_change", "shadowLastChange", SYSDB_SHADOWPW_LASTCHANGE, NULL },
+    { "ldap_user_ads_last_change", "pwdLastSet", SYSDB_SHADOWPW_ADS_LASTCHANGE, NULL },
     { "ldap_user_shadow_min", "shadowMin", SYSDB_SHADOWPW_MIN, NULL },
     { "ldap_user_shadow_max", "shadowMax", SYSDB_SHADOWPW_MAX, NULL },
     { "ldap_user_shadow_warning", "shadowWarning", SYSDB_SHADOWPW_WARNING, NULL },
@@ -878,6 +879,48 @@ errno_t string_to_shadowpw_days(const char *s, long *d)
     return EOK;
 }
 
+errno_t ads_pwdlastset_to_shadowpw_days(const char *s, long *d)
+{
+    long long ll;
+    long days;
+    char *endptr;
+
+    if (s == NULL || *s == '\0') {
+        *d = -1;
+        return EOK;
+    }
+
+    errno = 0;
+    ll = strtoll(s, &endptr, 10);
+    if (errno != 0) {
+        DEBUG(1, ("strtoll failed [%d][%s].\n", errno, strerror(errno)));
+        return errno;
+    }
+
+    if (*endptr != '\0') {
+        DEBUG(1, ("Input string [%s] is invalid.\n", s));
+        return EINVAL;
+    }
+    
+    /* Magic value for password reset */
+    if (ll = 0LL) {
+        DEBUG(9, ("Magic pwdLastSet date 0, password change forced.\n"));
+        *d = 0L;
+        return EOK;
+    }
+    
+    days = ll / 864000000000LL - 134774LL;
+
+    if (days < 0L) {
+        DEBUG(1, ("Date is before Jan 1, 1970 [%d].\n", ll));
+        return EINVAL;
+    }
+
+    *d = days;
+
+    return EOK;
+}
+
 errno_t get_sysdb_attr_name(TALLOC_CTX *mem_ctx,
                             struct sdap_attr_map *map,
                             size_t map_size,
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 9146da5..cf301de 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -146,6 +146,7 @@ int setup_child(struct sdap_id_ctx *ctx);
 
 
 errno_t string_to_shadowpw_days(const char *s, long *d);
+errno_t ads_pwdlastset_to_shadowpw_days(const char *s, long *d);
 
 errno_t get_sysdb_attr_name(TALLOC_CTX *mem_ctx,
                             struct sdap_attr_map *map,
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 32dc344..fdd5b7a 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -115,6 +115,7 @@ struct sdap_ppolicy_data {
 };
 
 #define SYSDB_SHADOWPW_LASTCHANGE "shadowLastChange"
+#define SYSDB_SHADOWPW_ADS_LASTCHANGE "pwdLastSet"
 #define SYSDB_SHADOWPW_MIN "shadowMin"
 #define SYSDB_SHADOWPW_MAX "shadowMax"
 #define SYSDB_SHADOWPW_WARNING "shadowWarning"
-- 
1.7.4.4




More information about the sssd-devel mailing list