]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
dsdb:password_hash: reject password reset with UNWILLING_TO_PERFORM
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Sun, 11 Jan 2026 09:31:04 +0000 (22:31 +1300)
committerDouglas Bagnall <dbagnall@samba.org>
Thu, 15 Jan 2026 01:48:37 +0000 (01:48 +0000)
This is what Windows does: where a password change would cause
CONSTRAINT_VIOLATION, a reset causes UNWILLING_TO_PERFORM.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=12020

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Gary Lockyer <gary@catalyst.net.nz>
python/samba/tests/samba_tool/user.py
source4/dsdb/samdb/ldb_modules/password_hash.c
source4/dsdb/tests/python/password_settings.py

index caef93407bf5425f21e03ce2f6ebfea98812fd8c..cdfd48a15c43734d9548491f8c6ede39b49a3017 100644 (file)
@@ -162,7 +162,7 @@ class UserCmdTestCase(SambaToolCmdTest):
                                           f'-U{dc_username}%{dc_password}')
         self.assertCmdFail(result)
         self.assertIn('Failed to add user', err)
-        self.assertIn('LDAP_CONSTRAINT_VIOLATION', err)
+        self.assertIn('LDAP_UNWILLING_TO_PERFORM', err)
         self.assertIn(f'{werror.WERR_PASSWORD_RESTRICTION:08X}', err)
 
         # Now search for the user, and make sure we don't find anything.
index 1b91d363c214bce9293d77860ef4f0f23ba4fc16..fdc7068d8c67addab2cf8b0553ef32defab56313 100644 (file)
@@ -2994,7 +2994,11 @@ static int check_password_restrictions(struct setup_password_fields_io *io, WERR
                        break;
 
                case SAMR_VALIDATION_STATUS_PWD_TOO_SHORT:
-                       ret = LDB_ERR_CONSTRAINT_VIOLATION;
+                       if (io->ac->pwd_reset) {
+                               ret = LDB_ERR_UNWILLING_TO_PERFORM;
+                       } else {
+                               ret = LDB_ERR_CONSTRAINT_VIOLATION;
+                       }
                        *werror = WERR_PASSWORD_RESTRICTION;
                        ldb_asprintf_errstring(ldb,
                                "%08X: %s - check_password_restrictions: "
@@ -3006,7 +3010,11 @@ static int check_password_restrictions(struct setup_password_fields_io *io, WERR
                        return ret;
 
                case SAMR_VALIDATION_STATUS_NOT_COMPLEX_ENOUGH:
-                       ret = LDB_ERR_CONSTRAINT_VIOLATION;
+                       if (io->ac->pwd_reset) {
+                               ret = LDB_ERR_UNWILLING_TO_PERFORM;
+                       } else {
+                               ret = LDB_ERR_CONSTRAINT_VIOLATION;
+                       }
                        *werror = WERR_PASSWORD_RESTRICTION;
                        ldb_asprintf_errstring(ldb,
                                "%08X: %s - check_password_restrictions: "
@@ -3017,7 +3025,11 @@ static int check_password_restrictions(struct setup_password_fields_io *io, WERR
                        return ret;
 
                default:
-                       ret = LDB_ERR_CONSTRAINT_VIOLATION;
+                       if (io->ac->pwd_reset) {
+                               ret = LDB_ERR_UNWILLING_TO_PERFORM;
+                       } else {
+                               ret = LDB_ERR_CONSTRAINT_VIOLATION;
+                       }
                        *werror = WERR_PASSWORD_RESTRICTION;
                        ldb_asprintf_errstring(ldb,
                                "%08X: %s - check_password_restrictions: "
index cdaad051a62ba22c74a2fc262f2df2b0013e8db0..b4ab19b4ff762fcd7114c9a30bc3682e1b73f1f7 100644 (file)
@@ -107,7 +107,8 @@ class PasswordSettingsTestCase(PasswordTestCase):
             self.fail("Password '%s' should have been rejected" % password)
         except ldb.LdbError as e:
             (num, msg) = e.args
-            self.assertEqual(num, ldb.ERR_CONSTRAINT_VIOLATION, msg)
+            self.assertIn(num, (ldb.ERR_UNWILLING_TO_PERFORM,
+                                ldb.ERR_CONSTRAINT_VIOLATION), msg)
             self.assertTrue('0000052D' in msg, msg)
 
     def assert_password_valid(self, user, password):
@@ -804,7 +805,8 @@ unicodePwd:: %s
             self.fail()
         except ldb.LdbError as e:
                 (num, msg) = e.args
-                self.assertEqual(num, ldb.ERR_CONSTRAINT_VIOLATION, msg)
+                self.assertIn(num, (ldb.ERR_CONSTRAINT_VIOLATION,
+                                    ldb.ERR_UNWILLING_TO_PERFORM), msg)
                 self.assertTrue('0000052D' in msg, msg)
 
         # check setting a password that meets the PSO settings works