dsdb: Update password_hash to use PSO settings for password changes
authorTim Beale <timbeale@catalyst.net.nz>
Wed, 18 Apr 2018 22:46:48 +0000 (10:46 +1200)
committerGarming Sam <garming@samba.org>
Wed, 23 May 2018 04:55:31 +0000 (06:55 +0200)
Honour the settings in the PSO when changing the password, i.e.
msDS-PasswordComplexityEnabled, msDS-PasswordHistoryLength, etc.

The password_hash code populates dsdb_control_password_change_status's
domain_data with the password settings to use - these are currently
based on the settings for the domain.

Now, if the password_hash code has worked out that a PSO applies to the
user, we override the domain settings with the PSO's values.

This change means the password_settings tests now pass.

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_hash_gpgme [deleted file]
selftest/knownfail.d/password_settings
source4/dsdb/samdb/ldb_modules/password_hash.c

diff --git a/selftest/knownfail.d/password_hash_gpgme b/selftest/knownfail.d/password_hash_gpgme
deleted file mode 100644 (file)
index a382714..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-samba.tests.password_hash_gpgme.samba.tests.password_hash_gpgme.PassWordHashGpgmeTests.test_supplementalCredentials_cleartext_pso\(ad_dc:local\)
-
index a0cf46fda71dcc8480ad1d4b0289353701ae1229..b23f3f9ef42927b891250b3b14ee404e5f6e35cd 100644 (file)
@@ -1,8 +1,2 @@
-samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_basics\(ad_dc_ntvfs\)
-samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_equal_precedence\(ad_dc_ntvfs\)
-samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_nested_groups\(ad_dc_ntvfs\)
-samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_special_groups\(ad_dc_ntvfs\)
-samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_min_age\(ad_dc_ntvfs\)
 samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_max_age\(ad_dc_ntvfs\)
-samba4.ldap.password_settings.python.password_settings.PasswordSettingsTestCase.test_pso_add_user\(ad_dc_ntvfs\)
 
index ac97415ffff5d617296dfae7096fa39c34ebf668..56ecdaf81c0f5a3be210874971e834e98083624e 100644 (file)
@@ -3855,6 +3855,9 @@ static int get_pso_data_callback(struct ldb_request *req,
 {
        struct ldb_context *ldb = NULL;
        struct ph_context *ac = NULL;
+       bool domain_complexity = true;
+       bool pso_complexity = true;
+       struct dsdb_user_pwd_settings *settings = NULL;
        int ret = LDB_SUCCESS;
 
        ac = talloc_get_type(req->context, struct ph_context);
@@ -3880,6 +3883,47 @@ static int get_pso_data_callback(struct ldb_request *req,
                        goto done;
                }
 
+               /*
+                * use the PSO's values instead of the domain defaults (the PSO
+                * attributes should always exist, but use the domain default
+                * values as a fallback).
+                */
+               settings = &ac->status->domain_data;
+               settings->store_cleartext =
+                       ldb_msg_find_attr_as_bool(ares->message,
+                                                 "msDS-PasswordReversibleEncryptionEnabled",
+                                                 settings->store_cleartext);
+
+               settings->pwdHistoryLength =
+                       ldb_msg_find_attr_as_uint(ares->message,
+                                                 "msDS-PasswordHistoryLength",
+                                                 settings->pwdHistoryLength);
+               settings->maxPwdAge =
+                       ldb_msg_find_attr_as_int64(ares->message,
+                                                  "msDS-MaximumPasswordAge",
+                                                  settings->maxPwdAge);
+               settings->minPwdAge =
+                       ldb_msg_find_attr_as_int64(ares->message,
+                                                  "msDS-MinimumPasswordAge",
+                                                  settings->minPwdAge);
+               settings->minPwdLength =
+                       ldb_msg_find_attr_as_uint(ares->message,
+                                                 "msDS-MinimumPasswordLength",
+                                                 settings->minPwdLength);
+               domain_complexity =
+                       (settings->pwdProperties & DOMAIN_PASSWORD_COMPLEX);
+               pso_complexity =
+                       ldb_msg_find_attr_as_bool(ares->message,
+                                                 "msDS-PasswordComplexityEnabled",
+                                                  domain_complexity);
+
+               /* set or clear the complexity bit if required */
+               if (pso_complexity && !domain_complexity) {
+                       settings->pwdProperties |= DOMAIN_PASSWORD_COMPLEX;
+               } else if (domain_complexity && !pso_complexity) {
+                       settings->pwdProperties &= ~DOMAIN_PASSWORD_COMPLEX;
+               }
+
                if (ac->pso_res != NULL) {
                        DBG_ERR("Too many PSO results for %s",
                                ldb_dn_get_linearized(ac->search_res->message->dn));
@@ -3949,7 +3993,13 @@ static struct ldb_request * build_pso_data_request(struct ph_context *ac)
        /* attrs[] is returned from this function in
           pso_req->op.search.attrs, so it must be static, as
           otherwise the compiler can put it on the stack */
-       static const char * const attrs[] = { "msDS-LockoutThreshold",
+       static const char * const attrs[] = { "msDS-PasswordComplexityEnabled",
+                                             "msDS-PasswordReversibleEncryptionEnabled",
+                                             "msDS-PasswordHistoryLength",
+                                             "msDS-MaximumPasswordAge",
+                                             "msDS-MinimumPasswordAge",
+                                             "msDS-MinimumPasswordLength",
+                                             "msDS-LockoutThreshold",
                                              "msDS-LockoutObservationWindow",
                                              NULL };
        struct ldb_context *ldb = NULL;