> On 07/05/2011 09:46 PM, Stephen Gallagher wrote:
> > On Fri, 2011-04-15 at 15:14 +0100, Pierre Carrier wrote:
> >> Hello Stephen,
> >> 
> >> On 15 Apr 2011, at 14:54, Stephen Gallagher wrote:
> >>> It would make much more sense to implement a new policy type and handle
> >>> this there.
> >> 
> >> Agreed. We could then cleanly implement the policies defined in
> >> [MS-ADTS].
> >> 
> >> Hopefully I'll get a test env up and running soon to work on that.
> >> 
> >> 
> >> Best regards,
> > 
> > Hello Pierre,
> > 
> >     This discussion fell off my radar, but I wanted to follow up and see
> > 
> > if you had done any further work on finishing up this patch. Anything we
> > can do to help?
> 
> As far as I know Pierre left Red Hat, so I doubt he will be finishing
> the patch.

Stephen,
I took the original patch and I made changes you requested along with some 
fixes you missed. Please take a look if the patch needs anything else.

Thanks
Jan
From a3ce285c32326171bf9bd4e0ec48a02ffe5de426 Mon Sep 17 00:00:00 2001
From: Jan Zeleny <jzel...@redhat.com>
Date: Tue, 23 Aug 2011 11:28:53 -0400
Subject: [PATCH] Initial support for AD pwdLastSet attribute

This patch just implements expiring the password when this attribute is
set to 0.

https://fedorahosted.org/sssd/ticket/919
---
 src/config/SSSDConfig.py                 |    1 +
 src/config/etc/sssd.api.d/sssd-ldap.conf |    1 +
 src/man/sssd-ldap.5.xml                  |   17 ++++++++++++
 src/providers/ldap/ldap_auth.c           |   10 +++++++
 src/providers/ldap/ldap_common.c         |   43 ++++++++++++++++++++++++++++++
 src/providers/ldap/ldap_common.h         |    7 +++++
 src/providers/ldap/sdap.h                |    1 +
 7 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index 53bd14f0d4a9d366f825ca49d1e8d55466cb4b3b..0c14003129fcc004e7b888cc1e0aa6311e8363b0 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -177,6 +177,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 18321cade7f73da0430b090448636717ce8c3526..6bae55f87098119b6f3ead59247c9a40484ff45f 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -53,6 +53,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 7c364abea3a5269f490fb3228a85d10cc7057a27..967a37558b5d7fec9be815a2ad255441064291d4 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -328,6 +328,23 @@
                 </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 the Active Directory pwdLastSet attribute. If
+                            the ldap_user_shadow_last_change attribute does not
+                            exist on the server, it will fall back to using
+                            ldap_user_ads_last_change.
+                        </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 ad4549e7c1c2003b7220c7e1d1e73668d8d036d7..4fe6d26b4893acce2674033d2a67e40daaca3f80 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -283,6 +283,10 @@ static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx,
         }
     } else if (strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) == 0) {
         mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL);
+        if (mark == NULL) {
+            mark = 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);
@@ -293,6 +297,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 f26a428df1851c98b7460ab07f3b9e10b2cb6593..1e04dcccb4e9171fbb218788fe292bb50ddf2e48 100644
--- a/src/providers/ldap/ldap_common.c
+++ b/src/providers/ldap/ldap_common.c
@@ -169,6 +169,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 },
@@ -927,6 +928,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 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 / HUNDRED_NS_PER_DAY - AD_DAYS_BEFORE_THE_EPOCH;
+
+    if (days < 0L) {
+        DEBUG(1, ("Date is before Jan 1, 1970 [%d].\n", ll));
+        return EINVAL;
+    }
+
+    *d = (long) 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 2d4b1755681ab6dad30273f41e26a602d8e33a6c..dd2d0f27c246480c460fba6e5e922f4502b80113 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -38,6 +38,12 @@
 #define LDAP_SSL_URI "ldaps://"
 #define LDAP_LDAPI_URI "ldapi://"
 
+/* pwdLastSet uses 100ns slices */
+#define HUNDRED_NS_PER_DAY (24LL * 60LL * 60LL * 1000LL * 1000LL * 10LL)
+/* Days from January 1, 1601 to January 1, 1970 */
+#define AD_DAYS_BEFORE_THE_EPOCH 134774LL
+
+
 /* a fd the child process would log into */
 extern int ldap_child_debug_fd;
 
@@ -146,6 +152,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 baac956be8fcfe747448ca26724c689b5c14519b..fb1df5b6142db4c98349a67a673e0f678d3e8330 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -107,6 +107,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.6

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to