summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2018-09-02 18:03:06 +1200
committerAndrew Bartlett <abartlet@samba.org>2018-09-03 06:14:55 +0200
commit74357bf347348d3a8b7483c58e5250e98f7e8810 (patch)
treea7233981d9656ad19877598789412867190d49bd /source4
parenta740a6131c967f9640b19a6964fd5d6f85ce853a (diff)
downloadsamba-74357bf347348d3a8b7483c58e5250e98f7e8810.tar.gz
selftest: Split up password_lockout into tests with and without a call to sleep()
This means we can have a long observation window for many of the tests and so make them much more reliable. Many of these cause frustrating flapping failures in our CI systems. Signed-off-by: Andrew Bartlett <abartlet@samba.org> Reviewed-by: Gary Lockyer <gary@catalyst.net.nz> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Mon Sep 3 06:14:55 CEST 2018 on sn-devel-144
Diffstat (limited to 'source4')
-rwxr-xr-xsource4/dsdb/tests/python/password_lockout.py299
1 files changed, 157 insertions, 142 deletions
diff --git a/source4/dsdb/tests/python/password_lockout.py b/source4/dsdb/tests/python/password_lockout.py
index be3e3fa53e2..aceebd66072 100755
--- a/source4/dsdb/tests/python/password_lockout.py
+++ b/source4/dsdb/tests/python/password_lockout.py
@@ -89,6 +89,42 @@ class PasswordTests(password_lockout_base.BasePasswordTestCase):
self.lockout2ntlm_ldb = self._readd_user(self.lockout2ntlm_creds,
lockOutObservationWindow=self.lockout_observation_window)
+
+ def use_pso_lockout_settings(self, creds):
+
+ # create a PSO with the lockout settings the test cases normally expect
+ #
+ # Some test cases sleep() for self.account_lockout_duration
+ pso = PasswordSettings("lockout-PSO", self.ldb, lockout_attempts=3,
+ lockout_duration=self.account_lockout_duration)
+ 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 _reset_samr(self, res):
+
+ # Now reset the lockout, by removing ACB_AUTOLOCK (which removes the lock, despite being a generated attribute)
+ samr_user = self._open_samr_user(res)
+ acb_info = self.samr.QueryUserInfo(samr_user, 16)
+ acb_info.acct_flags &= ~samr.ACB_AUTOLOCK
+ self.samr.SetUserInfo(samr_user, 16, acb_info)
+ self.samr.Close(samr_user)
+
+
+class PasswordTestsWithoutSleep(PasswordTests):
+ def setUp(self):
+ # The tests in this class do not sleep, so we can have a
+ # longer window and not flap on slower hosts
+ self.account_lockout_duration = 30
+ self.lockout_observation_window = 30
+ super(PasswordTestsWithoutSleep, self).setUp()
+
def _reset_ldap_lockoutTime(self, res):
self.ldb.modify_ldif("""
dn: """ + str(res[0].dn) + """
@@ -599,22 +635,130 @@ userPassword: thatsAcomplPASS2XYZ
"samr",
initial_lastlogon_relation='greater')
- def use_pso_lockout_settings(self, creds):
+ def test_multiple_logon_krb5(self):
+ self._test_multiple_logon(self.lockout1krb5_creds)
- # create a PSO with the lockout settings the test cases normally expect
- #
- # Some test cases sleep() for self.account_lockout_duration
- pso = PasswordSettings("lockout-PSO", self.ldb, lockout_attempts=3,
- lockout_duration=self.account_lockout_duration)
- self.addCleanup(self.ldb.delete, pso.dn)
+ def test_multiple_logon_ntlm(self):
+ self._test_multiple_logon(self.lockout1ntlm_creds)
- userdn = "cn=%s,cn=users,%s" % (creds.get_username(), self.base_dn)
- pso.apply_to(userdn)
+ def _test_samr_password_change(self, creds, other_creds, lockout_threshold=3):
+ """Tests user lockout by using bad password in SAMR password_change"""
- # 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)
+ # create a connection for SAMR using another user's credentials
+ lp = self.get_loadparm()
+ net = Net(other_creds, lp, server=self.host)
+
+ # work out the initial account values for this user
+ username = creds.get_username()
+ userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
+ res = self._check_account(userdn,
+ badPwdCount=0,
+ badPasswordTime=("greater", 0),
+ badPwdCountOnly=True)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
+ logonCount = int(res[0]["logonCount"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+
+ # prove we can change the user password (using the correct password)
+ new_password = "thatsAcomplPASS2"
+ net.change_password(newpassword=new_password.encode('utf-8'),
+ username=username,
+ oldpassword=creds.get_password())
+ creds.set_password(new_password)
+
+ # try entering 'x' many bad passwords in a row to lock the user out
+ new_password = "thatsAcomplPASS3"
+ for i in range(lockout_threshold):
+ badPwdCount = i + 1
+ try:
+ print("Trying bad password, attempt #%u" % badPwdCount)
+ net.change_password(newpassword=new_password.encode('utf-8'),
+ username=creds.get_username(),
+ oldpassword="bad-password")
+ self.fail("Invalid SAMR change_password accepted")
+ except NTSTATUSError as e:
+ enum = ctypes.c_uint32(e[0]).value
+ self.assertEquals(enum, ntstatus.NT_STATUS_WRONG_PASSWORD)
+
+ # check the status of the account is updated after each bad attempt
+ account_flags = 0
+ lockoutTime = None
+ if badPwdCount >= lockout_threshold:
+ account_flags = dsdb.UF_LOCKOUT
+ lockoutTime = ("greater", badPasswordTime)
+
+ res = self._check_account(userdn,
+ badPwdCount=badPwdCount,
+ badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=lockoutTime,
+ userAccountControl=dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=account_flags)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
+
+ # the user is now locked out
+ lockoutTime = int(res[0]["lockoutTime"][0])
+
+ # check the user remains locked out regardless of whether they use a
+ # good or a bad password now
+ for password in (creds.get_password(), "bad-password"):
+ try:
+ print("Trying password %s" % password)
+ net.change_password(newpassword=new_password.encode('utf-8'),
+ username=creds.get_username(),
+ oldpassword=password)
+ self.fail("Invalid SAMR change_password accepted")
+ except NTSTATUSError as e:
+ enum = ctypes.c_uint32(e[0]).value
+ self.assertEquals(enum, ntstatus.NT_STATUS_ACCOUNT_LOCKED_OUT)
+
+ res = self._check_account(userdn,
+ badPwdCount=lockout_threshold,
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=lockoutTime,
+ userAccountControl=dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+
+ # reset the user account lockout
+ self._reset_samr(res)
+
+ # check bad password counts are reset
+ res = self._check_account(userdn,
+ badPwdCount=0,
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
+ lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
+ userAccountControl=dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
+
+ # check we can change the user password successfully now
+ net.change_password(newpassword=new_password.encode('utf-8'),
+ username=username,
+ oldpassword=creds.get_password())
+ creds.set_password(new_password)
+
+ def test_samr_change_password(self):
+ self._test_samr_password_change(self.lockout1ntlm_creds,
+ other_creds=self.lockout2ntlm_creds)
+
+ # same as above, but use a PSO to enforce the lockout
+ def test_pso_samr_change_password(self):
+ self.use_pso_lockout_settings(self.lockout1ntlm_creds)
+ self._test_samr_password_change(self.lockout1ntlm_creds,
+ other_creds=self.lockout2ntlm_creds)
+
+
+class PasswordTestsWithSleep(PasswordTests):
+ def setUp(self):
+ super(PasswordTestsWithSleep, self).setUp()
def _test_unicodePwd_lockout_with_clear_change(self, creds, other_ldb,
initial_logoncount_relation=None):
@@ -1032,12 +1176,6 @@ unicodePwd:: """ + base64.b64encode(new_utf16).decode('utf8') + """
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)
-
- def test_multiple_logon_ntlm(self):
- self._test_multiple_logon(self.lockout1ntlm_creds)
-
def _testing_add_user(self, creds, lockOutObservationWindow=0):
username = creds.get_username()
userpass = creds.get_password()
@@ -1207,15 +1345,6 @@ userPassword: """ + userpass + """
msDSUserAccountControlComputed=0)
return ldb
- def _reset_samr(self, res):
-
- # Now reset the lockout, by removing ACB_AUTOLOCK (which removes the lock, despite being a generated attribute)
- samr_user = self._open_samr_user(res)
- acb_info = self.samr.QueryUserInfo(samr_user, 16)
- acb_info.acct_flags &= ~samr.ACB_AUTOLOCK
- self.samr.SetUserInfo(samr_user, 16, acb_info)
- self.samr.Close(samr_user)
-
def test_lockout_observation_window(self):
lockout3krb5_creds = self.insta_creds(self.template_creds,
username="lockout3krb5",
@@ -1242,120 +1371,6 @@ userPassword: """ + userpass + """
self._testing_add_user(lockout4ntlm_creds,
lockOutObservationWindow=self.lockout_observation_window)
- def _test_samr_password_change(self, creds, other_creds, lockout_threshold=3):
- """Tests user lockout by using bad password in SAMR password_change"""
-
- # create a connection for SAMR using another user's credentials
- lp = self.get_loadparm()
- net = Net(other_creds, lp, server=self.host)
-
- # work out the initial account values for this user
- username = creds.get_username()
- userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
- res = self._check_account(userdn,
- badPwdCount=0,
- badPasswordTime=("greater", 0),
- badPwdCountOnly=True)
- badPasswordTime = int(res[0]["badPasswordTime"][0])
- logonCount = int(res[0]["logonCount"][0])
- lastLogon = int(res[0]["lastLogon"][0])
- lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
-
- # prove we can change the user password (using the correct password)
- new_password = "thatsAcomplPASS2"
- net.change_password(newpassword=new_password.encode('utf-8'),
- username=username,
- oldpassword=creds.get_password())
- creds.set_password(new_password)
-
- # try entering 'x' many bad passwords in a row to lock the user out
- new_password = "thatsAcomplPASS3"
- for i in range(lockout_threshold):
- badPwdCount = i + 1
- try:
- print("Trying bad password, attempt #%u" % badPwdCount)
- net.change_password(newpassword=new_password.encode('utf-8'),
- username=creds.get_username(),
- oldpassword="bad-password")
- self.fail("Invalid SAMR change_password accepted")
- except NTSTATUSError as e:
- enum = ctypes.c_uint32(e[0]).value
- self.assertEquals(enum, ntstatus.NT_STATUS_WRONG_PASSWORD)
-
- # check the status of the account is updated after each bad attempt
- account_flags = 0
- lockoutTime = None
- if badPwdCount >= lockout_threshold:
- account_flags = dsdb.UF_LOCKOUT
- lockoutTime = ("greater", badPasswordTime)
-
- res = self._check_account(userdn,
- badPwdCount=badPwdCount,
- badPasswordTime=("greater", badPasswordTime),
- logonCount=logonCount,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogonTimestamp,
- lockoutTime=lockoutTime,
- userAccountControl=dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=account_flags)
- badPasswordTime = int(res[0]["badPasswordTime"][0])
-
- # the user is now locked out
- lockoutTime = int(res[0]["lockoutTime"][0])
-
- # check the user remains locked out regardless of whether they use a
- # good or a bad password now
- for password in (creds.get_password(), "bad-password"):
- try:
- print("Trying password %s" % password)
- net.change_password(newpassword=new_password.encode('utf-8'),
- username=creds.get_username(),
- oldpassword=password)
- self.fail("Invalid SAMR change_password accepted")
- except NTSTATUSError as e:
- enum = ctypes.c_uint32(e[0]).value
- self.assertEquals(enum, ntstatus.NT_STATUS_ACCOUNT_LOCKED_OUT)
-
- res = self._check_account(userdn,
- badPwdCount=lockout_threshold,
- badPasswordTime=badPasswordTime,
- logonCount=logonCount,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogonTimestamp,
- lockoutTime=lockoutTime,
- userAccountControl=dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
-
- # reset the user account lockout
- self._reset_samr(res)
-
- # check bad password counts are reset
- res = self._check_account(userdn,
- badPwdCount=0,
- badPasswordTime=badPasswordTime,
- logonCount=logonCount,
- lockoutTime=0,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogonTimestamp,
- userAccountControl=dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
-
- # check we can change the user password successfully now
- net.change_password(newpassword=new_password.encode('utf-8'),
- username=username,
- oldpassword=creds.get_password())
- creds.set_password(new_password)
-
- def test_samr_change_password(self):
- self._test_samr_password_change(self.lockout1ntlm_creds,
- other_creds=self.lockout2ntlm_creds)
-
- # same as above, but use a PSO to enforce the lockout
- def test_pso_samr_change_password(self):
- self.use_pso_lockout_settings(self.lockout1ntlm_creds)
- self._test_samr_password_change(self.lockout1ntlm_creds,
- other_creds=self.lockout2ntlm_creds)
-
host_url = "ldap://%s" % host