1 from __future__ import print_function
4 from samba.auth import system_session
5 from samba.credentials import Credentials, DONT_USE_KERBEROS, MUST_USE_KERBEROS
6 from ldb import SCOPE_BASE, LdbError
7 from ldb import ERR_CONSTRAINT_VIOLATION
8 from ldb import ERR_INVALID_CREDENTIALS
9 from ldb import Message, MessageElement, Dn
10 from ldb import FLAG_MOD_REPLACE
11 from samba import gensec, dsdb
12 from samba.samdb import SamDB
14 from samba.tests import delete_force
15 from samba.dcerpc import security, samr
16 from samba.ndr import ndr_unpack
17 from samba.tests.password_test import PasswordTestCase
21 class BasePasswordTestCase(PasswordTestCase):
22 def _open_samr_user(self, res):
23 self.assertTrue("objectSid" in res[0])
25 (domain_sid, rid) = ndr_unpack(security.dom_sid, res[0]["objectSid"][0]).split()
26 self.assertEquals(self.domain_sid, domain_sid)
28 return self.samr.OpenUser(self.samr_domain, security.SEC_FLAG_MAXIMUM_ALLOWED, rid)
30 def _check_attribute(self, res, name, value):
32 self.assertTrue(name not in res[0],
33 msg="attr[%s]=%r on dn[%s]" %
34 (name, res[0], res[0].dn))
37 if isinstance(value, tuple):
46 self.assertFalse(name in res[0],
47 msg="attr[%s] not missing on dn[%s]" %
51 self.assertTrue(name in res[0],
52 msg="attr[%s] missing on dn[%s]" %
54 self.assertTrue(len(res[0][name]) == 1,
55 msg="attr[%s]=%r on dn[%s]" %
56 (name, res[0][name], res[0].dn))
59 print("%s = '%s'" % (name, res[0][name][0]))
65 v = int(res[0][name][0])
67 msg = ("attr[%s]=[%s] != [%s] on dn[%s]\n"
68 "(diff %d; actual value is %s than expected)" %
69 (name, v, value, res[0].dn, v - value,
70 ('less' if v < value else 'greater')))
72 self.assertTrue(v == value, msg)
76 v = int(res[0][name][0])
77 self.assertTrue(v > int(value),
78 msg="attr[%s]=[%s] <= [%s] on dn[%s] (diff %d)" %
79 (name, v, int(value), res[0].dn, v - int(value)))
82 v = int(res[0][name][0])
83 self.assertTrue(v < int(value),
84 msg="attr[%s]=[%s] >= [%s] on dn[%s] (diff %d)" %
85 (name, v, int(value), res[0].dn, v - int(value)))
87 self.assertEqual(mode, not mode, "Invalid Mode[%s]" % mode)
89 def _check_account_initial(self, userdn):
90 self._check_account(userdn,
95 lastLogonTimestamp=("absent", None),
97 dsdb.UF_NORMAL_ACCOUNT,
98 msDSUserAccountControlComputed=0)
100 def _check_account(self, dn,
102 badPasswordTime=None,
105 lastLogonTimestamp=None,
107 userAccountControl=None,
108 msDSUserAccountControlComputed=None,
109 effective_bad_password_count=None,
111 badPwdCountOnly=False):
114 print("\033[01;32m %s \033[00m\n" % msg)
120 "lastLogonTimestamp",
123 "userAccountControl",
124 "msDS-User-Account-Control-Computed"
127 # in order to prevent some time resolution problems we sleep for
131 res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
132 self.assertTrue(len(res) == 1)
133 self._check_attribute(res, "badPwdCount", badPwdCount)
134 self._check_attribute(res, "lockoutTime", lockoutTime)
135 self._check_attribute(res, "badPasswordTime", badPasswordTime)
136 if not badPwdCountOnly:
137 self._check_attribute(res, "logonCount", logonCount)
138 self._check_attribute(res, "lastLogon", lastLogon)
139 self._check_attribute(res, "lastLogonTimestamp", lastLogonTimestamp)
140 self._check_attribute(res, "userAccountControl", userAccountControl)
141 self._check_attribute(res, "msDS-User-Account-Control-Computed",
142 msDSUserAccountControlComputed)
144 lastLogon = int(res[0]["lastLogon"][0])
145 logonCount = int(res[0]["logonCount"][0])
147 samr_user = self._open_samr_user(res)
148 uinfo3 = self.samr.QueryUserInfo(samr_user, 3)
149 uinfo5 = self.samr.QueryUserInfo(samr_user, 5)
150 uinfo16 = self.samr.QueryUserInfo(samr_user, 16)
151 uinfo21 = self.samr.QueryUserInfo(samr_user, 21)
152 self.samr.Close(samr_user)
154 expected_acb_info = 0
155 if not badPwdCountOnly:
156 if userAccountControl & dsdb.UF_NORMAL_ACCOUNT:
157 expected_acb_info |= samr.ACB_NORMAL
158 if userAccountControl & dsdb.UF_ACCOUNTDISABLE:
159 expected_acb_info |= samr.ACB_DISABLED
160 if userAccountControl & dsdb.UF_PASSWD_NOTREQD:
161 expected_acb_info |= samr.ACB_PWNOTREQ
162 if msDSUserAccountControlComputed & dsdb.UF_LOCKOUT:
163 expected_acb_info |= samr.ACB_AUTOLOCK
164 if msDSUserAccountControlComputed & dsdb.UF_PASSWORD_EXPIRED:
165 expected_acb_info |= samr.ACB_PW_EXPIRED
167 self.assertEquals(uinfo3.acct_flags, expected_acb_info)
168 self.assertEquals(uinfo3.last_logon, lastLogon)
169 self.assertEquals(uinfo3.logon_count, logonCount)
171 expected_bad_password_count = 0
172 if badPwdCount is not None:
173 expected_bad_password_count = badPwdCount
174 if effective_bad_password_count is None:
175 effective_bad_password_count = expected_bad_password_count
177 self.assertEquals(uinfo3.bad_password_count, expected_bad_password_count)
179 if not badPwdCountOnly:
180 self.assertEquals(uinfo5.acct_flags, expected_acb_info)
181 self.assertEquals(uinfo5.bad_password_count, effective_bad_password_count)
182 self.assertEquals(uinfo5.last_logon, lastLogon)
183 self.assertEquals(uinfo5.logon_count, logonCount)
185 self.assertEquals(uinfo16.acct_flags, expected_acb_info)
187 self.assertEquals(uinfo21.acct_flags, expected_acb_info)
188 self.assertEquals(uinfo21.bad_password_count, effective_bad_password_count)
189 self.assertEquals(uinfo21.last_logon, lastLogon)
190 self.assertEquals(uinfo21.logon_count, logonCount)
193 # check LDAP again and make sure the samr.QueryUserInfo
194 # doesn't have any impact.
195 res2 = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs)
196 self.assertEquals(res[0], res2[0])
198 # in order to prevent some time resolution problems we sleep for
203 def update_lockout_settings(self, threshold, duration, observation_window):
204 """Updates the global user lockout settings"""
206 m.dn = Dn(self.ldb, self.base_dn)
207 account_lockout_duration_ticks = -int(duration * (1e7))
208 m["lockoutDuration"] = MessageElement(str(account_lockout_duration_ticks),
209 FLAG_MOD_REPLACE, "lockoutDuration")
210 m["lockoutThreshold"] = MessageElement(str(threshold),
211 FLAG_MOD_REPLACE, "lockoutThreshold")
212 lockout_observation_window_ticks = -int(observation_window * (1e7))
213 m["lockOutObservationWindow"] = MessageElement(str(lockout_observation_window_ticks),
214 FLAG_MOD_REPLACE, "lockOutObservationWindow")
217 def _readd_user(self, creds, lockOutObservationWindow=0):
218 username = creds.get_username()
219 userpass = creds.get_password()
220 userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
222 delete_force(self.ldb, userdn)
225 "objectclass": "user",
226 "sAMAccountName": username})
228 self.addCleanup(delete_force, self.ldb, userdn)
230 # Sets the initial user password with a "special" password change
231 # I think that this internally is a password set operation and it can
232 # only be performed by someone which has password set privileges on the
233 # account (at least in s4 we do handle it like that).
234 self.ldb.modify_ldif("""
235 dn: """ + userdn + """
239 userPassword: """ + userpass + """
241 # Enables the user account
242 self.ldb.enable_account("(sAMAccountName=%s)" % username)
244 use_kerberos = creds.get_kerberos_state()
245 fail_creds = self.insta_creds(self.template_creds,
247 userpass=userpass+"X",
248 kerberos_state=use_kerberos)
249 self._check_account_initial(userdn)
251 # Fail once to get a badPasswordTime
253 ldb = SamDB(url=self.host_url, credentials=fail_creds, lp=self.lp)
255 except LdbError as e:
257 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
259 # Succeed to reset everything to 0
260 ldb = SamDB(url=self.host_url, credentials=creds, lp=self.lp)
264 def assertLoginFailure(self, url, creds, lp, errno=ERR_INVALID_CREDENTIALS):
266 ldb = SamDB(url=url, credentials=creds, lp=lp)
267 self.fail("Login unexpectedly succeeded")
268 except LdbError as e1:
270 if errno is not None:
271 self.assertEquals(num, errno, ("Login failed in the wrong way"
272 "(got err %d, expected %d)" %
276 super(BasePasswordTestCase, self).setUp()
278 self.global_creds.set_gensec_features(self.global_creds.get_gensec_features() |
281 self.template_creds = Credentials()
282 self.template_creds.set_username("testuser")
283 self.template_creds.set_password("thatsAcomplPASS1")
284 self.template_creds.set_domain(self.global_creds.get_domain())
285 self.template_creds.set_realm(self.global_creds.get_realm())
286 self.template_creds.set_workstation(self.global_creds.get_workstation())
287 self.template_creds.set_gensec_features(self.global_creds.get_gensec_features())
288 self.template_creds.set_kerberos_state(self.global_creds.get_kerberos_state())
290 # Gets back the basedn
291 base_dn = self.ldb.domain_dn()
293 # Gets back the configuration basedn
294 configuration_dn = self.ldb.get_config_basedn().get_linearized()
296 res = self.ldb.search(base_dn,
297 scope=SCOPE_BASE, attrs=["lockoutDuration", "lockOutObservationWindow", "lockoutThreshold"])
299 if "lockoutDuration" in res[0]:
300 lockoutDuration = res[0]["lockoutDuration"][0]
304 if "lockoutObservationWindow" in res[0]:
305 lockoutObservationWindow = res[0]["lockoutObservationWindow"][0]
307 lockoutObservationWindow = 0
309 if "lockoutThreshold" in res[0]:
310 lockoutThreshold = res[0]["lockoutThreshold"][0]
314 self.addCleanup(self.ldb.modify_ldif, """
315 dn: """ + base_dn + """
317 replace: lockoutDuration
318 lockoutDuration: """ + str(lockoutDuration) + """
319 replace: lockoutObservationWindow
320 lockoutObservationWindow: """ + str(lockoutObservationWindow) + """
321 replace: lockoutThreshold
322 lockoutThreshold: """ + str(lockoutThreshold) + """
325 self.base_dn = self.ldb.domain_dn()
326 self.account_lockout_duration = 2
327 self.lockout_observation_window = 2
328 self.update_lockout_settings(threshold=3, duration=2,
329 observation_window=2)
331 # update DC to allow password changes for the duration of this test
332 self.allow_password_changes()
334 self.domain_sid = security.dom_sid(self.ldb.get_domain_sid())
335 self.samr = samr.samr("ncacn_ip_tcp:%s[seal]" % self.host, self.lp, self.global_creds)
336 self.samr_handle = self.samr.Connect2(None, security.SEC_FLAG_MAXIMUM_ALLOWED)
337 self.samr_domain = self.samr.OpenDomain(self.samr_handle, security.SEC_FLAG_MAXIMUM_ALLOWED, self.domain_sid)
339 self.addCleanup(self.delete_ldb_connections)
341 # (Re)adds the test user accounts
342 self.lockout1krb5_creds = self.insta_creds(self.template_creds,
343 username="lockout1krb5",
344 userpass="thatsAcomplPASS0",
345 kerberos_state=MUST_USE_KERBEROS)
346 self.lockout1krb5_ldb = self._readd_user(self.lockout1krb5_creds)
347 self.lockout1ntlm_creds = self.insta_creds(self.template_creds,
348 username="lockout1ntlm",
349 userpass="thatsAcomplPASS0",
350 kerberos_state=DONT_USE_KERBEROS)
351 self.lockout1ntlm_ldb = self._readd_user(self.lockout1ntlm_creds)
353 def delete_ldb_connections(self):
354 del self.lockout1krb5_ldb
355 del self.lockout1ntlm_ldb
359 super(BasePasswordTestCase, self).tearDown()
361 def _test_login_lockout(self, creds):
362 username = creds.get_username()
363 userpass = creds.get_password()
364 userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
366 use_kerberos = creds.get_kerberos_state()
367 # This unlocks by waiting for account_lockout_duration
368 if use_kerberos == MUST_USE_KERBEROS:
369 logoncount_relation = 'greater'
370 lastlogon_relation = 'greater'
371 print("Performs a lockout attempt against LDAP using Kerberos")
373 logoncount_relation = 'equal'
374 lastlogon_relation = 'equal'
375 print("Performs a lockout attempt against LDAP using NTLM")
377 # Change password on a connection as another user
378 res = self._check_account(userdn,
380 badPasswordTime=("greater", 0),
381 logonCount=(logoncount_relation, 0),
382 lastLogon=("greater", 0),
383 lastLogonTimestamp=("greater", 0),
385 dsdb.UF_NORMAL_ACCOUNT,
386 msDSUserAccountControlComputed=0)
387 badPasswordTime = int(res[0]["badPasswordTime"][0])
388 logonCount = int(res[0]["logonCount"][0])
389 lastLogon = int(res[0]["lastLogon"][0])
390 firstLogon = lastLogon
391 lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
393 print(lastLogonTimestamp)
396 self.assertGreater(lastLogon, badPasswordTime)
397 self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
399 # Open a second LDB connection with the user credentials. Use the
400 # command line credentials for informations like the domain, the realm
401 # and the workstation.
402 creds_lockout = self.insta_creds(creds)
405 creds_lockout.set_password("thatsAcomplPASS1x")
407 self.assertLoginFailure(self.host_url, creds_lockout, self.lp)
409 res = self._check_account(userdn,
411 badPasswordTime=("greater", badPasswordTime),
412 logonCount=logonCount,
414 lastLogonTimestamp=lastLogonTimestamp,
416 dsdb.UF_NORMAL_ACCOUNT,
417 msDSUserAccountControlComputed=0,
418 msg='lastlogontimestamp with wrong password')
419 badPasswordTime = int(res[0]["badPasswordTime"][0])
421 # Correct old password
422 creds_lockout.set_password(userpass)
424 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
426 # lastLogonTimestamp should not change
427 # lastLogon increases if badPwdCount is non-zero (!)
428 res = self._check_account(userdn,
430 badPasswordTime=badPasswordTime,
431 logonCount=(logoncount_relation, logonCount),
432 lastLogon=('greater', lastLogon),
433 lastLogonTimestamp=lastLogonTimestamp,
435 dsdb.UF_NORMAL_ACCOUNT,
436 msDSUserAccountControlComputed=0,
437 msg='LLTimestamp is updated to lastlogon')
439 logonCount = int(res[0]["logonCount"][0])
440 lastLogon = int(res[0]["lastLogon"][0])
441 self.assertGreater(lastLogon, badPasswordTime)
442 self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
445 creds_lockout.set_password("thatsAcomplPASS1x")
447 self.assertLoginFailure(self.host_url, creds_lockout, self.lp)
449 res = self._check_account(userdn,
451 badPasswordTime=("greater", badPasswordTime),
452 logonCount=logonCount,
454 lastLogonTimestamp=lastLogonTimestamp,
456 dsdb.UF_NORMAL_ACCOUNT,
457 msDSUserAccountControlComputed=0)
458 badPasswordTime = int(res[0]["badPasswordTime"][0])
461 creds_lockout.set_password("thatsAcomplPASS1x")
464 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
467 except LdbError as e2:
469 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
471 res = self._check_account(userdn,
473 badPasswordTime=("greater", badPasswordTime),
474 logonCount=logonCount,
476 lastLogonTimestamp=lastLogonTimestamp,
478 dsdb.UF_NORMAL_ACCOUNT,
479 msDSUserAccountControlComputed=0)
480 badPasswordTime = int(res[0]["badPasswordTime"][0])
482 print("two failed password change")
485 creds_lockout.set_password("thatsAcomplPASS1x")
488 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
491 except LdbError as e3:
493 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
495 res = self._check_account(userdn,
497 badPasswordTime=("greater", badPasswordTime),
498 logonCount=logonCount,
500 lastLogonTimestamp=lastLogonTimestamp,
501 lockoutTime=("greater", badPasswordTime),
503 dsdb.UF_NORMAL_ACCOUNT,
504 msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
505 badPasswordTime = int(res[0]["badPasswordTime"][0])
506 lockoutTime = int(res[0]["lockoutTime"][0])
509 creds_lockout.set_password("thatsAcomplPASS1x")
511 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
513 except LdbError as e4:
515 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
517 res = self._check_account(userdn,
519 badPasswordTime=badPasswordTime,
520 logonCount=logonCount,
522 lastLogonTimestamp=lastLogonTimestamp,
523 lockoutTime=lockoutTime,
525 dsdb.UF_NORMAL_ACCOUNT,
526 msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
529 creds_lockout.set_password("thatsAcomplPASS1x")
531 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
533 except LdbError as e5:
535 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
537 res = self._check_account(userdn,
539 badPasswordTime=badPasswordTime,
540 logonCount=logonCount,
542 lastLogonTimestamp=lastLogonTimestamp,
543 lockoutTime=lockoutTime,
545 dsdb.UF_NORMAL_ACCOUNT,
546 msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
548 # The correct password, but we are locked out
549 creds_lockout.set_password(userpass)
551 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
553 except LdbError as e6:
555 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
557 res = self._check_account(userdn,
559 badPasswordTime=badPasswordTime,
560 logonCount=logonCount,
562 lastLogonTimestamp=lastLogonTimestamp,
563 lockoutTime=lockoutTime,
565 dsdb.UF_NORMAL_ACCOUNT,
566 msDSUserAccountControlComputed=dsdb.UF_LOCKOUT)
568 # wait for the lockout to end
569 time.sleep(self.account_lockout_duration + 1)
570 print(self.account_lockout_duration + 1)
572 res = self._check_account(userdn,
573 badPwdCount=3, effective_bad_password_count=0,
574 badPasswordTime=badPasswordTime,
575 logonCount=logonCount,
576 lockoutTime=lockoutTime,
578 lastLogonTimestamp=lastLogonTimestamp,
580 dsdb.UF_NORMAL_ACCOUNT,
581 msDSUserAccountControlComputed=0)
583 # The correct password after letting the timeout expire
585 creds_lockout.set_password(userpass)
587 creds_lockout2 = self.insta_creds(creds_lockout)
589 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout2, lp=self.lp)
592 res = self._check_account(userdn,
594 badPasswordTime=badPasswordTime,
595 logonCount=(logoncount_relation, logonCount),
596 lastLogon=(lastlogon_relation, lastLogon),
597 lastLogonTimestamp=lastLogonTimestamp,
600 dsdb.UF_NORMAL_ACCOUNT,
601 msDSUserAccountControlComputed=0,
602 msg="lastLogon is way off")
604 logonCount = int(res[0]["logonCount"][0])
605 lastLogon = int(res[0]["lastLogon"][0])
608 creds_lockout.set_password("thatsAcomplPASS1x")
610 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
612 except LdbError as e7:
614 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
616 res = self._check_account(userdn,
618 badPasswordTime=("greater", badPasswordTime),
619 logonCount=logonCount,
622 lastLogonTimestamp=lastLogonTimestamp,
624 dsdb.UF_NORMAL_ACCOUNT,
625 msDSUserAccountControlComputed=0)
626 badPasswordTime = int(res[0]["badPasswordTime"][0])
629 creds_lockout.set_password("thatsAcomplPASS1x")
631 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
633 except LdbError as e8:
635 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
637 res = self._check_account(userdn,
639 badPasswordTime=("greater", badPasswordTime),
640 logonCount=logonCount,
643 lastLogonTimestamp=lastLogonTimestamp,
645 dsdb.UF_NORMAL_ACCOUNT,
646 msDSUserAccountControlComputed=0)
647 badPasswordTime = int(res[0]["badPasswordTime"][0])
649 time.sleep(self.lockout_observation_window + 1)
651 res = self._check_account(userdn,
652 badPwdCount=2, effective_bad_password_count=0,
653 badPasswordTime=badPasswordTime,
654 logonCount=logonCount,
657 lastLogonTimestamp=lastLogonTimestamp,
659 dsdb.UF_NORMAL_ACCOUNT,
660 msDSUserAccountControlComputed=0)
663 creds_lockout.set_password("thatsAcomplPASS1x")
665 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
667 except LdbError as e9:
669 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
671 res = self._check_account(userdn,
673 badPasswordTime=("greater", badPasswordTime),
674 logonCount=logonCount,
677 lastLogonTimestamp=lastLogonTimestamp,
679 dsdb.UF_NORMAL_ACCOUNT,
680 msDSUserAccountControlComputed=0)
681 badPasswordTime = int(res[0]["badPasswordTime"][0])
683 # The correct password without letting the timeout expire
684 creds_lockout.set_password(userpass)
685 ldb_lockout = SamDB(url=self.host_url, credentials=creds_lockout, lp=self.lp)
687 res = self._check_account(userdn,
689 badPasswordTime=badPasswordTime,
690 logonCount=(logoncount_relation, logonCount),
692 lastLogon=("greater", lastLogon),
693 lastLogonTimestamp=lastLogonTimestamp,
695 dsdb.UF_NORMAL_ACCOUNT,
696 msDSUserAccountControlComputed=0)
698 def _test_multiple_logon(self, creds):
699 # Test the happy case in which a user logs on correctly, then
700 # logs on correctly again, so that the bad password and
701 # lockout times are both zero the second time. The lastlogon
702 # time should increase.
704 # Open a second LDB connection with the user credentials. Use the
705 # command line credentials for informations like the domain, the realm
706 # and the workstation.
707 username = creds.get_username()
708 userdn = "cn=%s,cn=users,%s" % (username, self.base_dn)
710 use_kerberos = creds.get_kerberos_state()
711 if use_kerberos == MUST_USE_KERBEROS:
712 print("Testing multiple logon with Kerberos")
713 logoncount_relation = 'greater'
714 lastlogon_relation = 'greater'
716 print("Testing multiple logon with NTLM")
717 logoncount_relation = 'equal'
718 lastlogon_relation = 'equal'
720 SamDB(url=self.host_url, credentials=self.insta_creds(creds), lp=self.lp)
722 res = self._check_account(userdn,
724 badPasswordTime=("greater", 0),
725 logonCount=(logoncount_relation, 0),
726 lastLogon=("greater", 0),
727 lastLogonTimestamp=("greater", 0),
729 dsdb.UF_NORMAL_ACCOUNT,
730 msDSUserAccountControlComputed=0)
731 badPasswordTime = int(res[0]["badPasswordTime"][0])
732 logonCount = int(res[0]["logonCount"][0])
733 lastLogon = int(res[0]["lastLogon"][0])
734 lastLogonTimestamp = int(res[0]["lastLogonTimestamp"][0])
735 firstLogon = lastLogon
736 print("last logon is %d" % lastLogon)
737 self.assertGreater(lastLogon, badPasswordTime)
738 self.assertGreaterEqual(lastLogon, lastLogonTimestamp)
741 SamDB(url=self.host_url, credentials=self.insta_creds(creds), lp=self.lp)
743 res = self._check_account(userdn,
745 badPasswordTime=badPasswordTime,
746 logonCount=(logoncount_relation, logonCount),
747 lastLogon=(lastlogon_relation, lastLogon),
748 lastLogonTimestamp=lastLogonTimestamp,
750 dsdb.UF_NORMAL_ACCOUNT,
751 msDSUserAccountControlComputed=0,
752 msg=("second logon, firstlogon was %s" %
756 lastLogon = int(res[0]["lastLogon"][0])
760 SamDB(url=self.host_url, credentials=self.insta_creds(creds), lp=self.lp)
762 res = self._check_account(userdn,
764 badPasswordTime=badPasswordTime,
765 logonCount=(logoncount_relation, logonCount),
766 lastLogon=(lastlogon_relation, lastLogon),
767 lastLogonTimestamp=lastLogonTimestamp,
769 dsdb.UF_NORMAL_ACCOUNT,
770 msDSUserAccountControlComputed=0)