dsdb: Use PSO maxPwdAge for operational msDS-PasswordExpiryTimeComputed
authorTim Beale <timbeale@catalyst.net.nz>
Thu, 19 Apr 2018 01:51:36 +0000 (13:51 +1200)
committerGarming Sam <garming@samba.org>
Wed, 23 May 2018 04:55:32 +0000 (06:55 +0200)
When calculating the Password-Expiry-Time, we should use the PSO's
max-password-age setting, if one applies to the user.

This is code may be inefficient, as it may repeat the PSO-lookup work
several times (once for each constructed attribute that tries to use
it). For now, I've gone for the simplest code change, and efficiency can
be addressed in a subsequent patch (once we have a good test to measure
it).

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
selftest/knownfail.d/password_settings [deleted file]
source4/dsdb/samdb/ldb_modules/operational.c

diff --git a/selftest/knownfail.d/password_settings b/selftest/knownfail.d/password_settings
deleted file mode 100644 (file)
index b23f3f9..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_max_age\(ad_dc_ntvfs\)
-
index e72ebb9415d39f5ca124a3db6301ceeee30498a3..c2968a4b802fd83e6eafbb8ba67d84deba6892ff 100644 (file)
@@ -695,11 +695,43 @@ static int construct_msds_keyversionnumber(struct ldb_module *module,
        _UF_TRUST_ACCOUNTS \
 )
 
+
+/*
+ * Returns the Effective-MaximumPasswordAge for a user
+ */
+static int64_t get_user_max_pwd_age(struct ldb_module *module,
+                                   struct ldb_message *user_msg,
+                                   struct ldb_request *parent,
+                                   struct ldb_dn *nc_root)
+{
+       int ret;
+       struct ldb_message *pso = NULL;
+       struct ldb_context *ldb = ldb_module_get_ctx(module);
+
+       /* if a PSO applies to the user, use its maxPwdAge */
+       ret = get_pso_for_user(module, user_msg, parent, &pso);
+       if (ret != LDB_SUCCESS) {
+
+               /* log the error, but fallback to the domain default */
+               DBG_ERR("Error retrieving PSO for %s\n",
+                       ldb_dn_get_linearized(user_msg->dn));
+       }
+
+       if (pso != NULL) {
+               return ldb_msg_find_attr_as_int64(pso,
+                                                 "msDS-MaximumPasswordAge", 0);
+       }
+
+       /* otherwise return the default domain value */
+       return samdb_search_int64(ldb, user_msg, 0, nc_root, "maxPwdAge", NULL);
+}
+
 /*
   calculate msDS-UserPasswordExpiryTimeComputed
 */
 static NTTIME get_msds_user_password_expiry_time_computed(struct ldb_module *module,
                                                struct ldb_message *msg,
+                                               struct ldb_request *parent,
                                                struct ldb_dn *domain_dn)
 {
        int64_t pwdLastSet, maxPwdAge;
@@ -742,8 +774,7 @@ static NTTIME get_msds_user_password_expiry_time_computed(struct ldb_module *mod
         * maxPwdAge: -9223372036854775808 (-0x8000000000000000ULL)
         *
         */
-       maxPwdAge = samdb_search_int64(ldb_module_get_ctx(module), msg, 0,
-                                      domain_dn, "maxPwdAge", NULL);
+       maxPwdAge = get_user_max_pwd_age(module, msg, parent, domain_dn);
        if (maxPwdAge >= -864000000000) {
                /*
                 * This is not really possible...
@@ -859,7 +890,9 @@ static int construct_msds_user_account_control_computed(struct ldb_module *modul
        if (!(userAccountControl & _UF_NO_EXPIRY_ACCOUNTS)) {
                NTTIME must_change_time
                        = get_msds_user_password_expiry_time_computed(module,
-                                                                     msg, nc_root);
+                                                                     msg,
+                                                                     parent,
+                                                                     nc_root);
                /* check for expired password */
                if (must_change_time < now) {
                        msDS_User_Account_Control_Computed |= UF_PASSWORD_EXPIRED;
@@ -900,7 +933,7 @@ static int construct_msds_user_password_expiry_time_computed(struct ldb_module *
 
        password_expiry_time
                = get_msds_user_password_expiry_time_computed(module, msg,
-                                                             nc_root);
+                                                             parent, nc_root);
 
        return samdb_msg_add_int64(ldb,
                                   msg->elements, msg,
@@ -993,6 +1026,7 @@ static int pso_search_by_sids(struct ldb_module *module, TALLOC_CTX *mem_ctx,
                "msDS-PasswordSettingsPrecedence",
                "objectGUID",
                "msDS-LockoutDuration",
+               "msDS-MaximumPasswordAge",
                NULL
        };
 
@@ -1246,6 +1280,7 @@ static const char *user_account_control_computed_attrs[] =
 static const char *user_password_expiry_time_computed_attrs[] =
 {
        "pwdLastSet",
+       PSO_ATTR_DEPENDENCIES,
        NULL
 };