from samba.dcerpc import security, samr
from samba.ndr import ndr_unpack
-parser = optparse.OptionParser("passwords.py [options] <host>")
+parser = optparse.OptionParser("password_lockout.py [options] <host>")
sambaopts = options.SambaOptions(parser)
parser.add_option_group(sambaopts)
parser.add_option_group(options.VersionOptions(parser))
global_creds.set_gensec_features(global_creds.get_gensec_features() |
gensec.FEATURE_SEAL)
-def insta_creds(template=global_creds):
- # get a copy of the global creds or a the passed in creds
- c = Credentials()
- c.set_username("testuser")
- c.set_password("thatsAcomplPASS1")
- c.set_domain(template.get_domain())
- c.set_realm(template.get_realm())
- c.set_workstation(template.get_workstation())
- c.set_gensec_features(c.get_gensec_features()
- | gensec.FEATURE_SEAL)
- c.set_kerberos_state(template.get_kerberos_state())
- return c
+template_creds = Credentials()
+template_creds.set_username("testuser")
+template_creds.set_password("thatsAcomplPASS1")
+template_creds.set_domain(global_creds.get_domain())
+template_creds.set_realm(global_creds.get_realm())
+template_creds.set_workstation(global_creds.get_workstation())
+template_creds.set_gensec_features(global_creds.get_gensec_features())
+template_creds.set_kerberos_state(global_creds.get_kerberos_state())
#
# Tests start here
#
-class PasswordTests(samba.tests.TestCase):
-
+class BasePasswordTestCase(samba.tests.TestCase):
def _open_samr_user(self, res):
self.assertTrue("objectSid" in res[0])
self.samr.SetUserInfo(samr_user, 16, acb_info)
self.samr.Close(samr_user)
- def _reset_ldap_lockoutTime(self, res):
- self.ldb.modify_ldif("""
-dn: """ + str(res[0].dn) + """
-changetype: modify
-replace: lockoutTime
-lockoutTime: 0
-""")
-
- def _reset_ldap_userAccountControl(self, res):
- self.assertTrue("userAccountControl" in res[0])
- self.assertTrue("msDS-User-Account-Control-Computed" in res[0])
-
- uac = int(res[0]["userAccountControl"][0])
- uacc = int(res[0]["msDS-User-Account-Control-Computed"][0])
-
- uac |= uacc
- uac = uac & ~dsdb.UF_LOCKOUT
-
- self.ldb.modify_ldif("""
-dn: """ + str(res[0].dn) + """
-changetype: modify
-replace: userAccountControl
-userAccountControl: %d
-""" % uac)
-
- def _reset_by_method(self, res, method):
- if method is "ldap_userAccountControl":
- self._reset_ldap_userAccountControl(res)
- elif method is "ldap_lockoutTime":
- self._reset_ldap_lockoutTime(res)
- elif method is "samr":
- self._reset_samr(res)
- else:
- self.assertTrue(False, msg="Invalid reset method[%s]" % method)
-
def _check_attribute(self, res, name, value):
if value is None:
self.assertTrue(name not in res[0],
def _check_account(self, dn,
badPwdCount=None,
badPasswordTime=None,
+ logonCount=None,
lastLogon=None,
lastLogonTimestamp=None,
lockoutTime=None,
"badPasswordTime",
"lastLogon",
"lastLogonTimestamp",
+ "logonCount",
"lockoutTime",
"userAccountControl",
"msDS-User-Account-Control-Computed"
self.assertTrue(len(res) == 1)
self._check_attribute(res, "badPwdCount", badPwdCount)
self._check_attribute(res, "badPasswordTime", badPasswordTime)
+ self._check_attribute(res, "logonCount", logonCount)
self._check_attribute(res, "lastLogon", lastLogon)
self._check_attribute(res, "lastLogonTimestamp", lastLogonTimestamp)
self._check_attribute(res, "lockoutTime", lockoutTime)
self._check_attribute(res, "msDS-User-Account-Control-Computed",
msDSUserAccountControlComputed)
+ lastLogon = int(res[0]["lastLogon"][0])
+ logonCount = int(res[0]["logonCount"][0])
+
samr_user = self._open_samr_user(res)
uinfo3 = self.samr.QueryUserInfo(samr_user, 3)
uinfo5 = self.samr.QueryUserInfo(samr_user, 5)
self.assertEquals(uinfo3.acct_flags, expected_acb_info)
self.assertEquals(uinfo3.bad_password_count, expected_bad_password_count)
+ self.assertEquals(uinfo3.last_logon, lastLogon)
+ self.assertEquals(uinfo3.logon_count, logonCount)
self.assertEquals(uinfo5.acct_flags, expected_acb_info)
self.assertEquals(uinfo5.bad_password_count, effective_bad_password_count)
+ self.assertEquals(uinfo5.last_logon, lastLogon)
+ self.assertEquals(uinfo5.logon_count, logonCount)
self.assertEquals(uinfo16.acct_flags, expected_acb_info)
self.assertEquals(uinfo21.acct_flags, expected_acb_info)
self.assertEquals(uinfo21.bad_password_count, effective_bad_password_count)
+ self.assertEquals(uinfo21.last_logon, lastLogon)
+ self.assertEquals(uinfo21.logon_count, logonCount)
# check LDAP again and make sure the samr.QueryUserInfo
# doesn't have any impact.
time.sleep(0.01)
return res
- def assertLoginFailure(self, url, creds, lp, errno=ERR_INVALID_CREDENTIALS):
- try:
- ldb = SamDB(url=url, credentials=creds, lp=lp)
- self.fail("Login unexpectedly succeeded")
- except LdbError, (num, msg):
- if errno is not None:
- self.assertEquals(num, errno, ("Login failed in the wrong way"
- "(got err %d, expected %d)" %
- (num, errno)))
-
- def setUp(self):
- super(PasswordTests, self).setUp()
-
- self.ldb = SamDB(url=host_url, session_info=system_session(lp),
- credentials=global_creds, lp=lp)
-
- # Gets back the basedn
- base_dn = self.ldb.domain_dn()
-
- # Gets back the configuration basedn
- configuration_dn = self.ldb.get_config_basedn().get_linearized()
-
- # Get the old "dSHeuristics" if it was set
- dsheuristics = self.ldb.get_dsheuristics()
-
- # Reset the "dSHeuristics" as they were before
- self.addCleanup(self.ldb.set_dsheuristics, dsheuristics)
-
- res = self.ldb.search(base_dn,
- scope=SCOPE_BASE, attrs=["lockoutDuration", "lockOutObservationWindow", "lockoutThreshold"])
-
- if "lockoutDuration" in res[0]:
- lockoutDuration = res[0]["lockoutDuration"][0]
- else:
- lockoutDuration = 0
-
- if "lockoutObservationWindow" in res[0]:
- lockoutObservationWindow = res[0]["lockoutObservationWindow"][0]
- else:
- lockoutObservationWindow = 0
+ def _readd_user(self, creds, lockOutObservationWindow=0):
+ username = creds.get_username()
+ userpass = creds.get_password()
+ userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
- if "lockoutThreshold" in res[0]:
- lockoutThreshold = res[0]["lockoutThreshold"][0]
+ use_kerberos = creds.get_kerberos_state()
+ if use_kerberos == MUST_USE_KERBEROS:
+ logoncount_relation = 'greater'
+ lastlogon_relation = 'greater'
else:
- lockoutTreshold = 0
-
- self.addCleanup(self.ldb.modify_ldif, """
-dn: """ + base_dn + """
-changetype: modify
-replace: lockoutDuration
-lockoutDuration: """ + str(lockoutDuration) + """
-replace: lockoutObservationWindow
-lockoutObservationWindow: """ + str(lockoutObservationWindow) + """
-replace: lockoutThreshold
-lockoutThreshold: """ + str(lockoutThreshold) + """
-""")
-
- m = Message()
- m.dn = Dn(self.ldb, base_dn)
-
- self.account_lockout_duration = 10
- 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 = 5
- 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)
-
- # Set the "dSHeuristics" to activate the correct "userPassword" behaviour
- self.ldb.set_dsheuristics("000000001")
-
- # Get the old "minPwdAge"
- minPwdAge = self.ldb.get_minPwdAge()
-
- # Reset the "minPwdAge" as it was before
- self.addCleanup(self.ldb.set_minPwdAge, minPwdAge)
-
- # Set it temporarely to "0"
- self.ldb.set_minPwdAge("0")
-
- 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[sign]" % host, lp, global_creds)
- self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
- self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)
+ logoncount_relation = 'equal'
+ if lockOutObservationWindow == 0:
+ lastlogon_relation = 'greater'
+ else:
+ lastlogon_relation = 'equal'
- # (Re)adds the test user "testuser" with no password atm
- delete_force(self.ldb, "cn=testuser,cn=users," + self.base_dn)
+ delete_force(self.ldb, userdn)
self.ldb.add({
- "dn": "cn=testuser,cn=users," + self.base_dn,
+ "dn": userdn,
"objectclass": "user",
- "sAMAccountName": "testuser"})
+ "sAMAccountName": username})
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ self.addCleanup(delete_force, self.ldb, userdn)
+
+ res = self._check_account(userdn,
badPwdCount=0,
badPasswordTime=0,
+ logonCount=0,
lastLogon=0,
lastLogonTimestamp=('absent', None),
userAccountControl=
# It doesn't create "lockoutTime" = 0.
self._reset_samr(res)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=0,
badPasswordTime=0,
+ logonCount=0,
lastLogon=0,
lastLogonTimestamp=('absent', None),
userAccountControl=
# wrong old password
try:
self.ldb.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+dn: """ + userdn + """
changetype: modify
delete: userPassword
userPassword: noPassword
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
# Windows (2008 at least) seems to have some small bug here: it
# returns "0000056A" on longer (always wrong) previous passwords.
- self.assertTrue('00000056' in msg)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=1,
badPasswordTime=("greater", 0),
+ logonCount=0,
lastLogon=0,
lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_PASSWD_NOTREQD,
msDSUserAccountControlComputed=
dsdb.UF_PASSWORD_EXPIRED)
+ badPwdCount = int(res[0]["badPwdCount"][0])
badPasswordTime = int(res[0]["badPasswordTime"][0])
# Sets the initial user password with a "special" password change
# only be performed by someone which has password set privileges on the
# account (at least in s4 we do handle it like that).
self.ldb.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+dn: """ + userdn + """
changetype: modify
delete: userPassword
add: userPassword
-userPassword: thatsAcomplPASS1
+userPassword: """ + userpass + """
""")
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=1,
+ res = self._check_account(userdn,
+ badPwdCount=badPwdCount,
badPasswordTime=badPasswordTime,
+ logonCount=0,
lastLogon=0,
lastLogonTimestamp=('absent', None),
userAccountControl=
msDSUserAccountControlComputed=0)
# Enables the user account
- self.ldb.enable_account("(sAMAccountName=testuser)")
+ self.ldb.enable_account("(sAMAccountName=%s)" % username)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=1,
+ res = self._check_account(userdn,
+ badPwdCount=badPwdCount,
badPasswordTime=badPasswordTime,
+ logonCount=0,
lastLogon=0,
lastLogonTimestamp=('absent', None),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+ if lockOutObservationWindow != 0:
+ time.sleep(lockOutObservationWindow + 1)
+ effective_bad_password_count = 0
+ else:
+ effective_bad_password_count = badPwdCount
- # Open a second LDB connection with the user credentials. Use the
- # command line credentials for informations like the domain, the realm
- # and the workstation.
- creds2 = insta_creds()
+ res = self._check_account(userdn,
+ badPwdCount=badPwdCount,
+ effective_bad_password_count=effective_bad_password_count,
+ badPasswordTime=badPasswordTime,
+ logonCount=0,
+ lastLogon=0,
+ lastLogonTimestamp=('absent', None),
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
- self.ldb2 = SamDB(url=host_url, credentials=creds2, lp=lp)
+ ldb = SamDB(url=host_url, credentials=creds, lp=lp)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
+ if lockOutObservationWindow == 0:
+ badPwdCount = 0
+ effective_bad_password_count = 0
+ if use_kerberos == MUST_USE_KERBEROS:
+ badPwdCount = 0
+ effective_bad_password_count = 0
+
+ res = self._check_account(userdn,
+ badPwdCount=badPwdCount,
+ effective_bad_password_count=effective_bad_password_count,
badPasswordTime=badPasswordTime,
- lastLogon=('greater', 0),
- lastLogonTimestamp=('greater', 0),
+ logonCount=(logoncount_relation, 0),
+ lastLogon=(lastlogon_relation, 0),
+ lastLogonTimestamp=('greater', badPasswordTime),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+ logonCount = int(res[0]["logonCount"][0])
lastLogon = int(res[0]["lastLogon"][0])
- self.assertGreater(lastLogon, badPasswordTime)
-
- # (Re)adds the test user "testuser3" with no password atm
- delete_force(self.ldb, "cn=testuser3,cn=users," + self.base_dn)
- self.ldb.add({
- "dn": "cn=testuser3,cn=users," + self.base_dn,
- "objectclass": "user",
- "sAMAccountName": "testuser3"})
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+ if lastlogon_relation == 'greater':
+ self.assertGreater(lastLogon, badPasswordTime)
+ self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
- res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
- badPwdCount=0,
- badPasswordTime=0,
- lastLogon=0,
- lastLogonTimestamp=('absent', None),
+ res = self._check_account(userdn,
+ badPwdCount=badPwdCount,
+ effective_bad_password_count=effective_bad_password_count,
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT |
- dsdb.UF_ACCOUNTDISABLE |
- dsdb.UF_PASSWD_NOTREQD,
- msDSUserAccountControlComputed=
- dsdb.UF_PASSWORD_EXPIRED)
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
+ return ldb
- # Tests a password change when we don't have any password yet with a
- # wrong old password
+ def assertLoginFailure(self, url, creds, lp, errno=ERR_INVALID_CREDENTIALS):
try:
- self.ldb.modify_ldif("""
-dn: cn=testuser3,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: noPassword
-add: userPassword
-userPassword: thatsAcomplPASS2
-""")
- self.fail()
+ ldb = SamDB(url=url, credentials=creds, lp=lp)
+ self.fail("Login unexpectedly succeeded")
except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- # Windows (2008 at least) seems to have some small bug here: it
- # returns "0000056A" on longer (always wrong) previous passwords.
- self.assertTrue('00000056' in msg)
-
- res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
- badPwdCount=1,
- badPasswordTime=("greater", 0),
- lastLogon=0,
- lastLogonTimestamp=('absent', None),
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT |
- dsdb.UF_ACCOUNTDISABLE |
- dsdb.UF_PASSWD_NOTREQD,
- msDSUserAccountControlComputed=
- dsdb.UF_PASSWORD_EXPIRED)
- badPasswordTime3 = int(res[0]["badPasswordTime"][0])
+ if errno is not None:
+ self.assertEquals(num, errno, ("Login failed in the wrong way"
+ "(got err %d, expected %d)" %
+ (num, errno)))
- # Sets the initial user password with a "special" password change
- # I think that this internally is a password set operation and it can
- # only be performed by someone which has password set privileges on the
- # account (at least in s4 we do handle it like that).
- self.ldb.modify_ldif("""
-dn: cn=testuser3,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-add: userPassword
-userPassword: thatsAcomplPASS1
-""")
+ def setUp(self):
+ super(BasePasswordTestCase, self).setUp()
- res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
- badPwdCount=1,
- badPasswordTime=badPasswordTime3,
- lastLogon=0,
- lastLogonTimestamp=('absent', None),
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT |
- dsdb.UF_ACCOUNTDISABLE |
- dsdb.UF_PASSWD_NOTREQD,
- msDSUserAccountControlComputed=0)
+ self.ldb = SamDB(url=host_url, session_info=system_session(lp),
+ credentials=global_creds, lp=lp)
- # Enables the user account
- self.ldb.enable_account("(sAMAccountName=testuser3)")
+ # Gets back the basedn
+ base_dn = self.ldb.domain_dn()
- res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
- badPwdCount=1,
- badPasswordTime=badPasswordTime3,
- lastLogon=0,
- lastLogonTimestamp=('absent', None),
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ # Gets back the configuration basedn
+ configuration_dn = self.ldb.get_config_basedn().get_linearized()
- # Open a second LDB connection with the user credentials. Use the
- # command line credentials for informations like the domain, the realm
- # and the workstation.
- creds3 = insta_creds()
- creds3.set_username("testuser3")
- creds3.set_password("thatsAcomplPASS1")
- self.ldb3 = SamDB(url=host_url, credentials=creds3, lp=lp)
+ # Get the old "dSHeuristics" if it was set
+ dsheuristics = self.ldb.get_dsheuristics()
- res = self._check_account("cn=testuser3,cn=users," + self.base_dn,
- badPwdCount=0,
- badPasswordTime=badPasswordTime3,
- lastLogon=('greater', badPasswordTime3),
- lastLogonTimestamp=('greater', badPasswordTime3),
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ # Reset the "dSHeuristics" as they were before
+ self.addCleanup(self.ldb.set_dsheuristics, dsheuristics)
- def _test_userPassword_lockout_with_clear_change(self, method):
- print "Performs a password cleartext change operation on 'userPassword'"
- # Notice: This works only against Windows if "dSHeuristics" has been set
- # properly
+ res = self.ldb.search(base_dn,
+ scope=SCOPE_BASE, attrs=["lockoutDuration", "lockOutObservationWindow", "lockoutThreshold"])
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
- badPasswordTime=("greater", 0),
- lastLogon=('greater', 0),
- lastLogonTimestamp=('greater', 0),
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
- badPasswordTime = int(res[0]["badPasswordTime"][0])
- lastLogon = int(res[0]["lastLogon"][0])
- lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+ if "lockoutDuration" in res[0]:
+ lockoutDuration = res[0]["lockoutDuration"][0]
+ else:
+ lockoutDuration = 0
- # Change password on a connection as another user
+ if "lockoutObservationWindow" in res[0]:
+ lockoutObservationWindow = res[0]["lockoutObservationWindow"][0]
+ else:
+ lockoutObservationWindow = 0
- # Wrong old password
- try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ if "lockoutThreshold" in res[0]:
+ lockoutThreshold = res[0]["lockoutThreshold"][0]
+ else:
+ lockoutTreshold = 0
+
+ self.addCleanup(self.ldb.modify_ldif, """
+dn: """ + base_dn + """
changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1x
-add: userPassword
-userPassword: thatsAcomplPASS2
+replace: lockoutDuration
+lockoutDuration: """ + str(lockoutDuration) + """
+replace: lockoutObservationWindow
+lockoutObservationWindow: """ + str(lockoutObservationWindow) + """
+replace: lockoutThreshold
+lockoutThreshold: """ + str(lockoutThreshold) + """
""")
- self.fail()
- except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ m = Message()
+ m.dn = Dn(self.ldb, base_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)
+
+ # Set the "dSHeuristics" to activate the correct "userPassword" behaviour
+ self.ldb.set_dsheuristics("000000001")
+
+ # Get the old "minPwdAge"
+ minPwdAge = self.ldb.get_minPwdAge()
+
+ # Reset the "minPwdAge" as it was before
+ self.addCleanup(self.ldb.set_minPwdAge, minPwdAge)
+
+ # Set it temporarely to "0"
+ self.ldb.set_minPwdAge("0")
+
+ 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]" % host, lp, global_creds)
+ self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
+ self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)
+
+ # (Re)adds the test user accounts
+ self.lockout1krb5_creds = self.insta_creds(template_creds,
+ username="lockout1krb5",
+ userpass="thatsAcomplPASS0",
+ kerberos_state=MUST_USE_KERBEROS)
+ self.lockout1krb5_ldb = self._readd_user(self.lockout1krb5_creds)
+ self.lockout2krb5_creds = self.insta_creds(template_creds,
+ username="lockout2krb5",
+ userpass="thatsAcomplPASS0",
+ kerberos_state=MUST_USE_KERBEROS)
+ self.lockout2krb5_ldb = self._readd_user(self.lockout2krb5_creds,
+ lockOutObservationWindow=self.lockout_observation_window)
+ self.lockout1ntlm_creds = self.insta_creds(template_creds,
+ username="lockout1ntlm",
+ userpass="thatsAcomplPASS0",
+ kerberos_state=DONT_USE_KERBEROS)
+ self.lockout1ntlm_ldb = self._readd_user(self.lockout1ntlm_creds)
+ self.lockout2ntlm_creds = self.insta_creds(template_creds,
+ username="lockout2ntlm",
+ userpass="thatsAcomplPASS0",
+ kerberos_state=DONT_USE_KERBEROS)
+ self.lockout2ntlm_ldb = self._readd_user(self.lockout2ntlm_creds,
+ lockOutObservationWindow=self.lockout_observation_window)
+
+ def tearDown(self):
+ super(BasePasswordTestCase, self).tearDown()
+
+ def _test_login_lockout(self, creds):
+ username = creds.get_username()
+ userpass = creds.get_password()
+ userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
+
+ use_kerberos = creds.get_kerberos_state()
+ # This unlocks by waiting for account_lockout_duration
+ if use_kerberos == MUST_USE_KERBEROS:
+ logoncount_relation = 'greater'
+ lastlogon_relation = 'greater'
+ print "Performs a lockout attempt against LDAP using Kerberos"
+ else:
+ logoncount_relation = 'equal'
+ lastlogon_relation = 'equal'
+ print "Performs a lockout attempt against LDAP using NTLM"
+
+ # Change password on a connection as another user
+ res = self._check_account(userdn,
+ badPwdCount=0,
+ badPasswordTime=("greater", 0),
+ logonCount=(logoncount_relation, 0),
+ lastLogon=("greater", 0),
+ lastLogonTimestamp=("greater", 0),
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
+ logonCount = int(res[0]["logonCount"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+ firstLogon = lastLogon
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+ print firstLogon
+ print lastLogonTimestamp
+
+
+ self.assertGreater(lastLogon, badPasswordTime)
+ self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
+
+ # Open a second LDB connection with the user credentials. Use the
+ # command line credentials for informations like the domain, the realm
+ # and the workstation.
+ creds_lockout = self.insta_creds(creds)
+
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
+
+ self.assertLoginFailure(host_url, creds_lockout, lp)
+
+ res = self._check_account(userdn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ msDSUserAccountControlComputed=0,
+ msg='lastlogontimestamp with wrong password')
badPasswordTime = int(res[0]["badPasswordTime"][0])
# Correct old password
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1
-add: userPassword
-userPassword: thatsAcomplPASS2
-""")
+ creds_lockout.set_password(userpass)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=1,
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+
+ # lastLogonTimestamp should not change
+ # lastLogon increases if badPwdCount is non-zero (!)
+ res = self._check_account(userdn,
+ badPwdCount=0,
badPasswordTime=badPasswordTime,
+ logonCount=(logoncount_relation, logonCount),
+ lastLogon=('greater', lastLogon),
+ lastLogonTimestamp=lastLogonTimestamp,
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0,
+ msg='LLTimestamp is updated to lastlogon')
+
+ logonCount = int(res[0]["logonCount"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+ self.assertGreater(lastLogon, badPasswordTime)
+ self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
+
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
+
+ self.assertLoginFailure(host_url, creds_lockout, lp)
+
+ res = self._check_account(userdn,
+ badPwdCount=1,
+ badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
+
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
- # Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1x
-add: userPassword
-userPassword: thatsAcomplPASS2
-""")
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
self.fail()
+
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
print "two failed password change"
- # Wrong old password
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
+
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1x
-add: userPassword
-userPassword: thatsAcomplPASS2
-""")
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
self.fail()
+
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=("greater", badPasswordTime),
badPasswordTime = int(res[0]["badPasswordTime"][0])
lockoutTime = int(res[0]["lockoutTime"][0])
- # Wrong old password
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1x
-add: userPassword
-userPassword: thatsAcomplPASS2
-""")
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('00000775' in msg)
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # Wrong old password
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1x
-add: userPassword
-userPassword: thatsAcomplPASS2
-""")
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('00000775' in msg)
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
- lockoutTime=lockoutTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+ # The correct password, but we are locked out
+ creds_lockout.set_password(userpass)
try:
- # Correct old password
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS2
-add: userPassword
-userPassword: thatsAcomplPASS2x
-""")
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('0000775' in msg)
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # Now reset the password, which does NOT change the lockout!
- self.ldb.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-replace: userPassword
-userPassword: thatsAcomplPASS2
-""")
+ # wait for the lockout to end
+ time.sleep(self.account_lockout_duration + 1)
+ print self.account_lockout_duration + 1
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3,
+ res = self._check_account(userdn,
+ badPwdCount=3, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
+ lockoutTime=lockoutTime,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
- lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+ msDSUserAccountControlComputed=0)
- try:
- # Correct old password
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS2
-add: userPassword
-userPassword: thatsAcomplPASS2x
-""")
- self.fail()
- except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('0000775' in msg)
+ # The correct password after letting the timeout expire
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3,
- badPasswordTime=badPasswordTime,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogonTimestamp,
- lockoutTime=lockoutTime,
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+ creds_lockout.set_password(userpass)
- m = Message()
- m.dn = Dn(self.ldb, "cn=testuser,cn=users," + self.base_dn)
- m["userAccountControl"] = MessageElement(
- str(dsdb.UF_LOCKOUT),
- FLAG_MOD_REPLACE, "userAccountControl")
+ creds_lockout2 = self.insta_creds(creds_lockout)
- self.ldb.modify(m)
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout2, lp=lp)
+ time.sleep(3)
- # This shows that setting the UF_LOCKOUT flag alone makes no difference
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3,
+ res = self._check_account(userdn,
+ badPwdCount=0,
badPasswordTime=badPasswordTime,
- lastLogon=lastLogon,
+ logonCount=(logoncount_relation, logonCount),
+ lastLogon=(lastlogon_relation, lastLogon),
lastLogonTimestamp=lastLogonTimestamp,
- lockoutTime=lockoutTime,
+ lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+ msDSUserAccountControlComputed=0,
+ msg="lastLogon is way off")
- # This shows that setting the UF_LOCKOUT flag makes no difference
+ logonCount = int(res[0]["logonCount"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
try:
- # Correct old password
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le')) + """
-""")
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('0000775' in msg)
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3,
- badPasswordTime=badPasswordTime,
- lockoutTime=lockoutTime,
+ res = self._check_account(userdn,
+ badPwdCount=1,
+ badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
+ lockoutTime=0,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+ msDSUserAccountControlComputed=0)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
- self._reset_by_method(res, method)
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
+ try:
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ self.fail()
+ except LdbError, (num, msg):
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- # Here bad password counts are reset without logon success.
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
- badPasswordTime=badPasswordTime,
+ res = self._check_account(userdn,
+ badPwdCount=2,
+ badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lockoutTime=0,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
- # The correct password after doing the unlock
-
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le')) + """
-""")
+ time.sleep(self.lockout_observation_window + 1)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
+ res = self._check_account(userdn,
+ badPwdCount=2, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lockoutTime=0,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- # Wrong old password
+ # The wrong password
+ creds_lockout.set_password("thatsAcomplPASS1x")
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1xyz
-add: userPassword
-userPassword: thatsAcomplPASS2XYZ
-""")
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('00000056' in msg)
+ self.assertEquals(num, ERR_INVALID_CREDENTIALS)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lockoutTime=0,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
- # Wrong old password
- try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
-changetype: modify
-delete: userPassword
-userPassword: thatsAcomplPASS1xyz
-add: userPassword
-userPassword: thatsAcomplPASS2XYZ
-""")
- self.fail()
- except LdbError, (num, msg):
- self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('00000056' in msg)
+ # The correct password without letting the timeout expire
+ creds_lockout.set_password(userpass)
+ ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=2,
- badPasswordTime=("greater", badPasswordTime),
+ res = self._check_account(userdn,
+ badPwdCount=0,
+ badPasswordTime=badPasswordTime,
+ logonCount=(logoncount_relation, logonCount),
lockoutTime=0,
- lastLogon=lastLogon,
+ lastLogon=("greater", lastLogon),
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+
+ def _test_multiple_logon(self, creds):
+ # Test the happy case in which a user logs on correctly, then
+ # logs on correctly again, so that the bad password and
+ # lockout times are both zero the second time. The lastlogon
+ # time should increase.
+
+ # Open a second LDB connection with the user credentials. Use the
+ # command line credentials for informations like the domain, the realm
+ # and the workstation.
+ username = creds.get_username()
+ userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
+
+ use_kerberos = creds.get_kerberos_state()
+ if use_kerberos == MUST_USE_KERBEROS:
+ print "Testing multiple logon with Kerberos"
+ logoncount_relation = 'greater'
+ lastlogon_relation = 'greater'
+ else:
+ print "Testing multiple logon with NTLM"
+ logoncount_relation = 'equal'
+ lastlogon_relation = 'equal'
+
+ SamDB(url=host_url, credentials=self.insta_creds(creds), lp=lp)
+
+ res = self._check_account(userdn,
+ badPwdCount=0,
+ badPasswordTime=("greater", 0),
+ logonCount=(logoncount_relation, 0),
+ lastLogon=("greater", 0),
+ lastLogonTimestamp=("greater", 0),
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
+ logonCount = int(res[0]["logonCount"][0])
+ lastLogon = int(res[0]["lastLogon"][0])
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+ firstLogon = lastLogon
+ print "last logon is %d" % lastLogon
+ self.assertGreater(lastLogon, badPasswordTime)
+ self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
- self._reset_ldap_lockoutTime(res)
+ time.sleep(1)
+ SamDB(url=host_url, credentials=self.insta_creds(creds), lp=lp)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
- lastLogon=lastLogon,
+ logonCount=(logoncount_relation, logonCount),
+ lastLogon=(lastlogon_relation, lastLogon),
+ lastLogonTimestamp=lastLogonTimestamp,
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0,
+ msg=("second logon, firstlogon was %s" %
+ firstLogon))
+
+
+ lastLogon = int(res[0]["lastLogon"][0])
+
+ time.sleep(1)
+
+ SamDB(url=host_url, credentials=self.insta_creds(creds), lp=lp)
+
+ res = self._check_account(userdn,
+ badPwdCount=0,
+ badPasswordTime=badPasswordTime,
+ logonCount=(logoncount_relation, logonCount),
+ lastLogon=(lastlogon_relation, lastLogon),
lastLogonTimestamp=lastLogonTimestamp,
- lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- def test_userPassword_lockout_with_clear_change_ldap_userAccountControl(self):
- self._test_userPassword_lockout_with_clear_change("ldap_userAccountControl")
- def test_userPassword_lockout_with_clear_change_ldap_lockoutTime(self):
- self._test_userPassword_lockout_with_clear_change("ldap_lockoutTime")
+class PasswordTests(BasePasswordTestCase):
+ def _reset_ldap_lockoutTime(self, res):
+ self.ldb.modify_ldif("""
+dn: """ + str(res[0].dn) + """
+changetype: modify
+replace: lockoutTime
+lockoutTime: 0
+""")
+
+ def _reset_ldap_userAccountControl(self, res):
+ self.assertTrue("userAccountControl" in res[0])
+ self.assertTrue("msDS-User-Account-Control-Computed" in res[0])
+
+ uac = int(res[0]["userAccountControl"][0])
+ uacc = int(res[0]["msDS-User-Account-Control-Computed"][0])
+
+ uac |= uacc
+ uac = uac & ~dsdb.UF_LOCKOUT
+
+ self.ldb.modify_ldif("""
+dn: """ + str(res[0].dn) + """
+changetype: modify
+replace: userAccountControl
+userAccountControl: %d
+""" % uac)
+
+ def _reset_by_method(self, res, method):
+ if method is "ldap_userAccountControl":
+ self._reset_ldap_userAccountControl(res)
+ elif method is "ldap_lockoutTime":
+ self._reset_ldap_lockoutTime(res)
+ elif method is "samr":
+ self._reset_samr(res)
+ else:
+ self.assertTrue(False, msg="Invalid reset method[%s]" % method)
- def test_userPassword_lockout_with_clear_change_samr(self):
- self._test_userPassword_lockout_with_clear_change("samr")
+ def _test_userPassword_lockout_with_clear_change(self, creds, other_ldb, method,
+ initial_lastlogon_relation=None):
+ # Notice: This works only against Windows if "dSHeuristics" has been set
+ # properly
+ username = creds.get_username()
+ userpass = creds.get_password()
+ userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
+ use_kerberos = creds.get_kerberos_state()
+ if use_kerberos == MUST_USE_KERBEROS:
+ logoncount_relation = 'greater'
+ lastlogon_relation = 'greater'
+ print "Performs a password cleartext change operation on 'userPassword' using Kerberos"
+ else:
+ logoncount_relation = 'equal'
+ lastlogon_relation = 'equal'
+ print "Performs a password cleartext change operation on 'userPassword' using NTLMSSP"
- def test_unicodePwd_lockout_with_clear_change(self):
- print "Performs a password cleartext change operation on 'unicodePwd'"
+ if initial_lastlogon_relation is not None:
+ lastlogon_relation = initial_lastlogon_relation
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=0,
badPasswordTime=("greater", 0),
- lastLogon=("greater", 0),
- lastLogonTimestamp=("greater", 0),
+ logonCount=(logoncount_relation, 0),
+ lastLogon=(lastlogon_relation, 0),
+ lastLogonTimestamp=('greater', 0),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
+ logonCount = int(res[0]["logonCount"][0])
lastLogon = int(res[0]["lastLogon"][0])
+ lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
+ if lastlogon_relation == 'greater':
+ self.assertGreater(lastLogon, badPasswordTime)
+ self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
# Change password on a connection as another user
# Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS1x
+add: userPassword
+userPassword: thatsAcomplPASS2
""")
self.fail()
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
# Correct old password
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: """ + userpass + """
+add: userPassword
+userPassword: thatsAcomplPASS2
""")
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=1,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
# Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS1x
+add: userPassword
+userPassword: thatsAcomplPASS2
""")
self.fail()
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
- # SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
- # It doesn't create "lockoutTime" = 0 and doesn't
- # reset "badPwdCount" = 0.
- self._reset_samr(res)
-
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=2,
- badPasswordTime=badPasswordTime,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
-
print "two failed password change"
# Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS1x
+add: userPassword
+userPassword: thatsAcomplPASS2
""")
self.fail()
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- # this is strange, why do we have lockoutTime=badPasswordTime here?
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=("greater", badPasswordTime),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
# Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS1x
+add: userPassword
+userPassword: thatsAcomplPASS2
""")
self.fail()
except LdbError, (num, msg):
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('00000775' in msg)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
# Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS1x
+add: userPassword
+userPassword: thatsAcomplPASS2
""")
self.fail()
except LdbError, (num, msg):
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('00000775' in msg)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ logonCount=logonCount,
lockoutTime=lockoutTime,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
try:
# Correct old password
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS2
+add: userPassword
+userPassword: thatsAcomplPASS2x
""")
self.fail()
except LdbError, (num, msg):
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
- self.assertTrue('0000775' in msg)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # Now reset the lockout, by removing ACB_AUTOLOCK (which removes the lock, despite being a generated attribute)
- self._reset_samr(res);
-
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
- badPasswordTime=badPasswordTime,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
- lockoutTime=0,
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
-
- # Correct old password
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ # Now reset the password, which does NOT change the lockout!
+ self.ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le')) + """
+replace: userPassword
+userPassword: thatsAcomplPASS2
""")
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
+ res = self._check_account(userdn,
+ badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
- lockoutTime=0,
+ lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ # Correct old password
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS2
+add: userPassword
+userPassword: thatsAcomplPASS2x
""")
self.fail()
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=1,
- badPasswordTime=("greater", badPasswordTime),
+ res = self._check_account(userdn,
+ badPwdCount=3,
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
- lockoutTime=0,
+ lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
- badPasswordTime = int(res[0]["badPasswordTime"][0])
+ msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # Wrong old password
+ m = Message()
+ m.dn = Dn(self.ldb, userdn)
+ m["userAccountControl"] = MessageElement(
+ str(dsdb.UF_LOCKOUT),
+ FLAG_MOD_REPLACE, "userAccountControl")
+
+ self.ldb.modify(m)
+
+ # This shows that setting the UF_LOCKOUT flag alone makes no difference
+ res = self._check_account(userdn,
+ badPwdCount=3,
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=lockoutTime,
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+
+ # This shows that setting the UF_LOCKOUT flag makes no difference
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ # Correct old password
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
-add: unicodePwd
unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le')) + """
""")
self.fail()
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=2,
- badPasswordTime=("greater", badPasswordTime),
+ res = self._check_account(userdn,
+ badPwdCount=3,
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
+ lockoutTime=lockoutTime,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
+ userAccountControl=
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+
+ self._reset_by_method(res, method)
+
+ # Here bad password counts are reset without logon success.
+ res = self._check_account(userdn,
+ badPwdCount=0,
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- badPasswordTime = int(res[0]["badPasswordTime"][0])
- # SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
- # It doesn't reset "badPwdCount" = 0.
- self._reset_samr(res)
+ # The correct password after doing the unlock
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=2,
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2x\"".encode('utf-16-le')) + """
+""")
+ userpass = "thatsAcomplPASS2x"
+ creds.set_password(userpass)
+
+ res = self._check_account(userdn,
+ badPwdCount=0,
badPasswordTime=badPasswordTime,
- lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ logonCount=logonCount,
lockoutTime=0,
+ lastLogon=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
# Wrong old password
try:
- self.ldb3.modify_ldif("""
-dn: cn=testuser,cn=users,""" + self.base_dn + """
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
changetype: modify
-delete: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
-add: unicodePwd
-unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+delete: userPassword
+userPassword: thatsAcomplPASS1xyz
+add: userPassword
+userPassword: thatsAcomplPASS2XYZ
""")
self.fail()
except LdbError, (num, msg):
- self.assertTrue('00000056' in msg)
self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3,
+ res = self._check_account(userdn,
+ badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
+ lockoutTime=0,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
- lockoutTime=("greater", badPasswordTime),
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
+ msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
- lockoutTime = int(res[0]["lockoutTime"][0])
- time.sleep(self.account_lockout_duration + 1)
+ # Wrong old password
+ try:
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: userPassword
+userPassword: thatsAcomplPASS1xyz
+add: userPassword
+userPassword: thatsAcomplPASS2XYZ
+""")
+ self.fail()
+ except LdbError, (num, msg):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3, effective_bad_password_count=0,
- badPasswordTime=badPasswordTime,
+ res = self._check_account(userdn,
+ badPwdCount=2,
+ badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
+ lockoutTime=0,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
- lockoutTime=lockoutTime,
+ lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
+ badPasswordTime = int(res[0]["badPasswordTime"][0])
- # SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
- # It doesn't reset "lockoutTime" = 0 and doesn't
- # reset "badPwdCount" = 0.
- self._reset_samr(res)
+ self._reset_ldap_lockoutTime(res)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3, effective_bad_password_count=0,
+ res = self._check_account(userdn,
+ badPwdCount=0,
badPasswordTime=badPasswordTime,
- lockoutTime=lockoutTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
- lastLogonTimestamp=lastLogon,
+ lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- def _test_login_lockout(self, use_kerberos):
- # This unlocks by waiting for account_lockout_duration
- if use_kerberos == MUST_USE_KERBEROS:
- lastlogon_relation = 'greater'
- print "Performs a lockout attempt against LDAP using Kerberos"
+ def test_userPassword_lockout_with_clear_change_krb5_ldap_userAccountControl(self):
+ self._test_userPassword_lockout_with_clear_change(self.lockout1krb5_creds,
+ self.lockout2krb5_ldb,
+ "ldap_userAccountControl")
+
+ def test_userPassword_lockout_with_clear_change_krb5_ldap_lockoutTime(self):
+ self._test_userPassword_lockout_with_clear_change(self.lockout1krb5_creds,
+ self.lockout2krb5_ldb,
+ "ldap_lockoutTime")
+
+ def test_userPassword_lockout_with_clear_change_krb5_samr(self):
+ self._test_userPassword_lockout_with_clear_change(self.lockout1krb5_creds,
+ self.lockout2krb5_ldb,
+ "samr")
+
+ def test_userPassword_lockout_with_clear_change_ntlm_ldap_userAccountControl(self):
+ self._test_userPassword_lockout_with_clear_change(self.lockout1ntlm_creds,
+ self.lockout2ntlm_ldb,
+ "ldap_userAccountControl",
+ initial_lastlogon_relation='greater')
+
+ def test_userPassword_lockout_with_clear_change_ntlm_ldap_lockoutTime(self):
+ self._test_userPassword_lockout_with_clear_change(self.lockout1ntlm_creds,
+ self.lockout2ntlm_ldb,
+ "ldap_lockoutTime",
+ initial_lastlogon_relation='greater')
+
+ def test_userPassword_lockout_with_clear_change_ntlm_samr(self):
+ self._test_userPassword_lockout_with_clear_change(self.lockout1ntlm_creds,
+ self.lockout2ntlm_ldb,
+ "samr",
+ initial_lastlogon_relation='greater')
+
+ def _test_unicodePwd_lockout_with_clear_change(self, creds, other_ldb,
+ initial_logoncount_relation=None):
+ print "Performs a password cleartext change operation on 'unicodePwd'"
+ username = creds.get_username()
+ userpass = creds.get_password()
+ userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
+ if initial_logoncount_relation is not None:
+ logoncount_relation = initial_logoncount_relation
else:
- lastlogon_relation = 'equal'
- print "Performs a lockout attempt against LDAP using NTLM"
+ logoncount_relation = "greater"
- # Change password on a connection as another user
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=0,
badPasswordTime=("greater", 0),
+ logonCount=(logoncount_relation, 0),
lastLogon=("greater", 0),
lastLogonTimestamp=("greater", 0),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
+ logonCount = int(res[0]["logonCount"][0])
lastLogon = int(res[0]["lastLogon"][0])
- firstLogon = lastLogon
lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
- print firstLogon
- print lastLogonTimestamp
-
+ self.assertGreater(lastLogonTimestamp, badPasswordTime)
+ self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
- self.assertGreater(lastLogon, badPasswordTime)
-
- # Open a second LDB connection with the user credentials. Use the
- # command line credentials for informations like the domain, the realm
- # and the workstation.
- creds_lockout = insta_creds()
- creds_lockout.set_kerberos_state(use_kerberos)
-
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
+ # Change password on a connection as another user
- self.assertLoginFailure(host_url, creds_lockout, lp)
+ # Wrong old password
+ try:
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1x\"".encode('utf-16-le')) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
+""")
+ self.fail()
+ except LdbError, (num, msg):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0,
- msg='lastlogontimestamp with wrong password')
+ msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
# Correct old password
- creds_lockout.set_password("thatsAcomplPASS1")
-
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ old_utf16 = ("\"%s\"" % userpass).encode('utf-16-le')
+ invalid_utf16 = "\"thatsAcomplPASSX\"".encode('utf-16-le')
+ userpass = "thatsAcomplPASS2"
+ creds.set_password(userpass)
+ new_utf16 = ("\"%s\"" % userpass).encode('utf-16-le')
+
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(old_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
- # lastLogonTimestamp should not change
- # lastLogon increases if badPwdCount is non-zero (!)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
+ res = self._check_account(userdn,
+ badPwdCount=1,
badPasswordTime=badPasswordTime,
- lastLogon=('greater', lastLogon),
+ logonCount=logonCount,
+ lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0,
- msg='LLTimestamp is updated to lastlogon')
-
- lastLogon = int(res[0]["lastLogon"][0])
- self.assertGreater(lastLogon, badPasswordTime)
-
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
+ msDSUserAccountControlComputed=0)
- self.assertLoginFailure(host_url, creds_lockout, lp)
+ # Wrong old password
+ try:
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(old_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
+ self.fail()
+ except LdbError, (num, msg):
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=1,
+ res = self._check_account(userdn,
+ badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
-
- try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
- self.fail()
-
- except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ # SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
+ # It doesn't create "lockoutTime" = 0 and doesn't
+ # reset "badPwdCount" = 0.
+ self._reset_samr(res)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=2,
- badPasswordTime=("greater", badPasswordTime),
+ badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- badPasswordTime = int(res[0]["badPasswordTime"][0])
print "two failed password change"
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
-
+ # Wrong old password
try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(invalid_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
self.fail()
-
except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ # this is strange, why do we have lockoutTime=badPasswordTime here?
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=("greater", badPasswordTime),
badPasswordTime = int(res[0]["badPasswordTime"][0])
lockoutTime = int(res[0]["lockoutTime"][0])
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
+ # Wrong old password
try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(invalid_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
+ # Wrong old password
try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(invalid_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # The correct password, but we are locked out
- creds_lockout.set_password("thatsAcomplPASS1")
try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ # Correct old password
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(invalid_utf16) + """
+""")
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000775' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=3,
badPasswordTime=badPasswordTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=lockoutTime,
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
- # wait for the lockout to end
- time.sleep(self.account_lockout_duration + 1)
- print self.account_lockout_duration + 1
+ # Now reset the lockout, by removing ACB_AUTOLOCK (which removes the lock, despite being a generated attribute)
+ self._reset_samr(res);
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=3, effective_bad_password_count=0,
+ res = self._check_account(userdn,
+ badPwdCount=0,
badPasswordTime=badPasswordTime,
- lockoutTime=lockoutTime,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- lastLogon = int(res[0]["lastLogon"][0])
-
- # The correct password after letting the timeout expire
-
- creds_lockout.set_password("thatsAcomplPASS1")
-
- creds_lockout2 = insta_creds(creds_lockout)
-
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout2, lp=lp)
- time.sleep(3)
+ # Correct old password
+ old_utf16 = ("\"%s\"" % userpass).encode('utf-16-le')
+ invalid_utf16 = "\"thatsAcomplPASSiX\"".encode('utf-16-le')
+ userpass = "thatsAcomplPASS2x"
+ creds.set_password(userpass)
+ new_utf16 = ("\"%s\"" % userpass).encode('utf-16-le')
+
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(old_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=0,
badPasswordTime=badPasswordTime,
- lastLogon=(lastlogon_relation, lastLogon),
+ logonCount=logonCount,
+ lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0,
- msg="lastLogon is way off")
-
- lastLogon = int(res[0]["lastLogon"][0])
+ msDSUserAccountControlComputed=0)
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
+ # Wrong old password
try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(invalid_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=1,
badPasswordTime=("greater", badPasswordTime),
- lockoutTime=0,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
+ # Wrong old password
try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(invalid_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
+ res = self._check_account(userdn,
badPwdCount=2,
badPasswordTime=("greater", badPasswordTime),
- lockoutTime=0,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
badPasswordTime = int(res[0]["badPasswordTime"][0])
- time.sleep(self.lockout_observation_window + 1)
+ # SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
+ # It doesn't reset "badPwdCount" = 0.
+ self._reset_samr(res)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=2, effective_bad_password_count=0,
+ res = self._check_account(userdn,
+ badPwdCount=2,
badPasswordTime=badPasswordTime,
- lockoutTime=0,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=0,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- # The wrong password
- creds_lockout.set_password("thatsAcomplPASS1x")
+ # Wrong old password
try:
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ other_ldb.modify_ldif("""
+dn: """ + userdn + """
+changetype: modify
+delete: unicodePwd
+unicodePwd:: """ + base64.b64encode(invalid_utf16) + """
+add: unicodePwd
+unicodePwd:: """ + base64.b64encode(new_utf16) + """
+""")
self.fail()
except LdbError, (num, msg):
- self.assertEquals(num, ERR_INVALID_CREDENTIALS)
+ self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
+ self.assertTrue('00000056' in msg, msg)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=1,
+ res = self._check_account(userdn,
+ badPwdCount=3,
badPasswordTime=("greater", badPasswordTime),
- lockoutTime=0,
+ logonCount=logonCount,
lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=("greater", badPasswordTime),
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
badPasswordTime = int(res[0]["badPasswordTime"][0])
+ lockoutTime = int(res[0]["lockoutTime"][0])
- # The correct password without letting the timeout expire
- creds_lockout.set_password("thatsAcomplPASS1")
- ldb_lockout = SamDB(url=host_url, credentials=creds_lockout, lp=lp)
+ time.sleep(self.account_lockout_duration + 1)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
+ res = self._check_account(userdn,
+ badPwdCount=3, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
- lockoutTime=0,
- lastLogon=("greater", lastLogon),
+ logonCount=logonCount,
+ lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
+ lockoutTime=lockoutTime,
userAccountControl=
dsdb.UF_NORMAL_ACCOUNT,
msDSUserAccountControlComputed=0)
- def test_login_lockout_ntlm(self):
- self._test_login_lockout(DONT_USE_KERBEROS)
-
- def test_login_lockout_kerberos(self):
- self._test_login_lockout(MUST_USE_KERBEROS)
-
- def _test_multiple_logon(self, use_kerberos):
- # Test the happy case in which a user logs on correctly, then
- # logs on correctly again, so that the bad password and
- # lockout times are both zero the second time. The lastlogon
- # time should increase.
-
- # Open a second LDB connection with the user credentials. Use the
- # command line credentials for informations like the domain, the realm
- # and the workstation.
- creds2 = insta_creds()
- creds2.set_kerberos_state(use_kerberos)
- self.assertEqual(creds2.get_kerberos_state(), use_kerberos)
-
- if use_kerberos == MUST_USE_KERBEROS:
- print "Testing multiple logon with Kerberos"
- lastlogon_relation = 'greater'
- else:
- print "Testing multiple logon with NTLM"
- lastlogon_relation = 'equal'
-
- SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
-
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
- badPasswordTime=("greater", 0),
- lastLogon=("greater", 0),
- lastLogonTimestamp=("greater", 0),
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
- badPasswordTime = int(res[0]["badPasswordTime"][0])
- lastLogon = int(res[0]["lastLogon"][0])
- lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
- firstLogon = lastLogon
- print "last logon is %d" % lastLogon
- self.assertGreater(lastLogon, badPasswordTime)
-
- time.sleep(1)
- SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+ # SAMR doesn't have any impact if dsdb.UF_LOCKOUT isn't present.
+ # It doesn't reset "lockoutTime" = 0 and doesn't
+ # reset "badPwdCount" = 0.
+ self._reset_samr(res)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
+ res = self._check_account(userdn,
+ badPwdCount=3, effective_bad_password_count=0,
badPasswordTime=badPasswordTime,
- lastLogon=(lastlogon_relation, lastLogon),
+ logonCount=logonCount,
+ lockoutTime=lockoutTime,
+ lastLogon=lastLogon,
lastLogonTimestamp=lastLogonTimestamp,
userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0,
- msg=("second logon, firstlogon was %s" %
- firstLogon))
+ dsdb.UF_NORMAL_ACCOUNT,
+ msDSUserAccountControlComputed=0)
+ def test_unicodePwd_lockout_with_clear_change_krb5(self):
+ self._test_unicodePwd_lockout_with_clear_change(self.lockout1krb5_creds,
+ self.lockout2krb5_ldb)
- lastLogon = int(res[0]["lastLogon"][0])
+ def test_unicodePwd_lockout_with_clear_change_ntlm(self):
+ self._test_unicodePwd_lockout_with_clear_change(self.lockout1ntlm_creds,
+ self.lockout2ntlm_ldb,
+ initial_logoncount_relation="equal")
- time.sleep(1)
+ def test_login_lockout_krb5(self):
+ self._test_login_lockout(self.lockout1krb5_creds)
- SamDB(url=host_url, credentials=insta_creds(creds2), lp=lp)
+ def test_login_lockout_ntlm(self):
+ self._test_login_lockout(self.lockout1ntlm_creds)
- res = self._check_account("cn=testuser,cn=users," + self.base_dn,
- badPwdCount=0,
- badPasswordTime=badPasswordTime,
- lastLogon=(lastlogon_relation, lastLogon),
- lastLogonTimestamp=lastLogonTimestamp,
- userAccountControl=
- dsdb.UF_NORMAL_ACCOUNT,
- msDSUserAccountControlComputed=0)
+ def test_multiple_logon_krb5(self):
+ self._test_multiple_logon(self.lockout1krb5_creds)
def test_multiple_logon_ntlm(self):
- self._test_multiple_logon(DONT_USE_KERBEROS)
+ self._test_multiple_logon(self.lockout1ntlm_creds)
- def test_multiple_logon_kerberos(self):
- self._test_multiple_logon(MUST_USE_KERBEROS)
-
- def tearDown(self):
- super(PasswordTests, self).tearDown()
- delete_force(self.ldb, "cn=testuser,cn=users," + self.base_dn)
- delete_force(self.ldb, "cn=testuser2,cn=users," + self.base_dn)
- delete_force(self.ldb, "cn=testuser3,cn=users," + self.base_dn)
- # Close the second LDB connection (with the user credentials)
- self.ldb2 = None
host_url = "ldap://%s" % host