tests: Add PSO test case to existing password_lockout tests
authorTim Beale <timbeale@catalyst.net.nz>
Sun, 18 Mar 2018 23:56:14 +0000 (12:56 +1300)
committerGarming Sam <garming@samba.org>
Fri, 11 May 2018 04:01:24 +0000 (06:01 +0200)
This checks that the lockout settings of the PSO take effect when one is
applied to a user. Import the password_settings code to create/apply a
PSO with the same lockout settings that the test cases normally use.
Then update the global settings so that the default lockout settings are
wildly different (i.e. so the test fails if the default lockout settings
get used instead of the PSO's).

As the password-lockout tests are quite slow, I've selected test cases
that should provide sufficient PSO coverage (rather than repeat every
single password-lockout test case in its entirety).

Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
selftest/knownfail.d/password_lockout [new file with mode: 0644]
source4/dsdb/tests/python/password_lockout.py
source4/dsdb/tests/python/password_lockout_base.py

diff --git a/selftest/knownfail.d/password_lockout b/selftest/knownfail.d/password_lockout
new file mode 100644 (file)
index 0000000..a62c7d1
--- /dev/null
@@ -0,0 +1,5 @@
+samba4.ldap.password_lockout.python\(ad_dc_ntvfs\).__main__.PasswordTests.test_pso_login_lockout_ntlm\(ad_dc_ntvfs\)
+samba4.ldap.password_lockout.python\(ad_dc_ntvfs\).__main__.PasswordTests.test_pso_login_lockout_krb5\(ad_dc_ntvfs\)
+samba4.ldap.password_lockout.python\(ad_dc_ntvfs\).__main__.PasswordTests.test_pso_userPassword_lockout_with_clear_change_krb5_ldap_userAccountControl\(ad_dc_ntvfs\)
+samba4.ldap.password_lockout.python\(ad_dc_ntvfs\).__main__.PasswordTests.test_pso_userPassword_lockout_with_clear_change_ntlm_ldap_lockoutTime\(ad_dc_ntvfs\)
+samba4.ldap.password_lockout.python\(ad_dc_ntvfs\).__main__.PasswordTests.test_pso_userPassword_lockout_with_clear_change_ntlm_samr\(ad_dc_ntvfs\)
index 763d7626c9e5ee885cc3825356dfd25a6c666ac3..99e9ef6004451a98c5c241c06b6cd49fd1be4c32 100755 (executable)
@@ -33,6 +33,7 @@ import samba.tests
 from samba.tests import delete_force
 from samba.dcerpc import security, samr
 from samba.ndr import ndr_unpack
+from samba.tests.pso import PasswordSettings
 
 parser = optparse.OptionParser("password_lockout.py [options] <host>")
 sambaopts = options.SambaOptions(parser)
@@ -590,6 +591,41 @@ userPassword: thatsAcomplPASS2XYZ
                                                           "samr",
                                                           initial_lastlogon_relation='greater')
 
+    # For PSOs, just test a selection of the above combinations
+    def test_pso_userPassword_lockout_with_clear_change_krb5_ldap_userAccountControl(self):
+        self.use_pso_lockout_settings(self.lockout1krb5_creds)
+        self._test_userPassword_lockout_with_clear_change(self.lockout1krb5_creds,
+                                                          self.lockout2krb5_ldb,
+                                                          "ldap_userAccountControl")
+
+    def test_pso_userPassword_lockout_with_clear_change_ntlm_ldap_lockoutTime(self):
+        self.use_pso_lockout_settings(self.lockout1ntlm_creds)
+        self._test_userPassword_lockout_with_clear_change(self.lockout1ntlm_creds,
+                                                          self.lockout2ntlm_ldb,
+                                                          "ldap_lockoutTime",
+                                                          initial_lastlogon_relation='greater')
+
+    def test_pso_userPassword_lockout_with_clear_change_ntlm_samr(self):
+        self.use_pso_lockout_settings(self.lockout1ntlm_creds)
+        self._test_userPassword_lockout_with_clear_change(self.lockout1ntlm_creds,
+                                                          self.lockout2ntlm_ldb,
+                                                          "samr",
+                                                          initial_lastlogon_relation='greater')
+
+    def use_pso_lockout_settings(self, creds):
+        # create a PSO with the lockout settings the test cases normally expect
+        pso = PasswordSettings("lockout-PSO", self.ldb, lockout_attempts=3,
+                               lockout_duration=2)
+        self.addCleanup(self.ldb.delete, pso.dn)
+
+        userdn = "cn=%s,cn=users,%s" % (creds.get_username(), self.base_dn)
+        pso.apply_to(userdn)
+
+        # update the global lockout settings to be wildly different to what
+        # the test cases normally expect
+        self.update_lockout_settings(threshold=10, duration=600,
+                                     observation_window=600)
+
     def _test_unicodePwd_lockout_with_clear_change(self, creds, other_ldb,
                                                    initial_logoncount_relation=None):
         print("Performs a password cleartext change operation on 'unicodePwd'")
@@ -1012,6 +1048,17 @@ unicodePwd:: """ + base64.b64encode(new_utf16) + """
     def test_login_lockout_ntlm(self):
         self._test_login_lockout(self.lockout1ntlm_creds)
 
+    # Repeat the login lockout tests using PSOs
+    def test_pso_login_lockout_krb5(self):
+        """Check the PSO lockout settings get applied to the user correctly"""
+        self.use_pso_lockout_settings(self.lockout1krb5_creds)
+        self._test_login_lockout(self.lockout1krb5_creds)
+
+    def test_pso_login_lockout_ntlm(self):
+        """Check the PSO lockout settings get applied to the user correctly"""
+        self.use_pso_lockout_settings(self.lockout1ntlm_creds)
+        self._test_login_lockout(self.lockout1ntlm_creds)
+
     def test_multiple_logon_krb5(self):
         self._test_multiple_logon(self.lockout1krb5_creds)
 
index 721948ce00ff20a87803f9869c7030b8a14d9e5a..843eaff1ab2cfe3311276a994fdc7fffdee6e752 100644 (file)
@@ -200,6 +200,20 @@ class BasePasswordTestCase(PasswordTestCase):
         time.sleep(0.01)
         return res
 
+    def update_lockout_settings(self, threshold, duration, observation_window):
+        """Updates the global user lockout settings"""
+        m = Message()
+        m.dn = Dn(self.ldb, self.base_dn)
+        account_lockout_duration_ticks = -int(duration * (1e7))
+        m["lockoutDuration"] = MessageElement(str(account_lockout_duration_ticks),
+                                              FLAG_MOD_REPLACE, "lockoutDuration")
+        m["lockoutThreshold"] = MessageElement(str(threshold),
+                                               FLAG_MOD_REPLACE, "lockoutThreshold")
+        lockout_observation_window_ticks = -int(observation_window * (1e7))
+        m["lockOutObservationWindow"] = MessageElement(str(lockout_observation_window_ticks),
+                                                       FLAG_MOD_REPLACE, "lockOutObservationWindow")
+        self.ldb.modify(m)
+
     def _readd_user(self, creds, lockOutObservationWindow=0):
         username = creds.get_username()
         userpass = creds.get_password()
@@ -308,32 +322,15 @@ replace: lockoutThreshold
 lockoutThreshold: """ + str(lockoutThreshold) + """
 """)
 
-        m = Message()
-        m.dn = Dn(self.ldb, base_dn)
-
+        self.base_dn = self.ldb.domain_dn()
         self.account_lockout_duration = 2
-        account_lockout_duration_ticks = -int(self.account_lockout_duration * (1e7))
-
-        m["lockoutDuration"] = MessageElement(str(account_lockout_duration_ticks),
-                                              FLAG_MOD_REPLACE, "lockoutDuration")
-
-        account_lockout_threshold = 3
-        m["lockoutThreshold"] = MessageElement(str(account_lockout_threshold),
-                                               FLAG_MOD_REPLACE, "lockoutThreshold")
-
         self.lockout_observation_window = 2
-        lockout_observation_window_ticks = -int(self.lockout_observation_window * (1e7))
-
-        m["lockOutObservationWindow"] = MessageElement(str(lockout_observation_window_ticks),
-                                                       FLAG_MOD_REPLACE, "lockOutObservationWindow")
-
-        self.ldb.modify(m)
+        self.update_lockout_settings(threshold=3, duration=2,
+                                     observation_window=2)
 
         # update DC to allow password changes for the duration of this test
         self.allow_password_changes()
 
-        self.base_dn = self.ldb.domain_dn()
-
         self.domain_sid = security.dom_sid(self.ldb.get_domain_sid())
         self.samr = samr.samr("ncacn_ip_tcp:%s[seal]" % self.host, self.lp, self.global_creds)
         self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)