2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
5 from __future__ import print_function
11 sys.path.insert(0, "bin/python")
13 from samba.tests.subunitrun import SubunitOptions, TestProgram
15 import samba.getopt as options
17 from samba.credentials import Credentials, DONT_USE_KERBEROS
18 from samba.auth import system_session
19 from ldb import SCOPE_BASE, LdbError
20 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
21 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
22 from ldb import ERR_OTHER, ERR_NO_SUCH_ATTRIBUTE
23 from ldb import ERR_OBJECT_CLASS_VIOLATION
24 from ldb import ERR_CONSTRAINT_VIOLATION
25 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
26 from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS
27 from ldb import ERR_INVALID_CREDENTIALS
28 from ldb import ERR_STRONG_AUTH_REQUIRED
29 from ldb import Message, MessageElement, Dn
30 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
31 from samba.samdb import SamDB
32 from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_ACCOUNTDISABLE,
33 UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
34 UF_PARTIAL_SECRETS_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT,
35 UF_INTERDOMAIN_TRUST_ACCOUNT, UF_SMARTCARD_REQUIRED,
36 UF_PASSWD_NOTREQD, UF_LOCKOUT, UF_PASSWORD_EXPIRED, ATYPE_NORMAL_ACCOUNT,
37 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
38 GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP,
39 GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP, GTYPE_DISTRIBUTION_GLOBAL_GROUP,
40 GTYPE_DISTRIBUTION_UNIVERSAL_GROUP,
41 ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_UNIVERSAL_GROUP,
42 ATYPE_SECURITY_LOCAL_GROUP, ATYPE_DISTRIBUTION_GLOBAL_GROUP,
43 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP, ATYPE_DISTRIBUTION_LOCAL_GROUP,
44 ATYPE_WORKSTATION_TRUST)
45 from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_ADMINS,
46 DOMAIN_RID_DOMAIN_MEMBERS, DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS)
48 from samba.ndr import ndr_unpack
49 from samba.dcerpc import drsblobs
50 from samba.dcerpc import drsuapi
51 from samba.dcerpc import security
52 from samba.tests import delete_force
53 from samba import gensec
54 from samba import werror
56 parser = optparse.OptionParser("sam.py [options] <host>")
57 sambaopts = options.SambaOptions(parser)
58 parser.add_option_group(sambaopts)
59 parser.add_option_group(options.VersionOptions(parser))
60 # use command line creds if available
61 credopts = options.CredentialsOptions(parser)
62 parser.add_option_group(credopts)
63 subunitopts = SubunitOptions(parser)
64 parser.add_option_group(subunitopts)
65 opts, args = parser.parse_args()
73 lp = sambaopts.get_loadparm()
74 creds = credopts.get_credentials(lp)
75 creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
77 class SamTests(samba.tests.TestCase):
80 super(SamTests, self).setUp()
82 self.base_dn = ldb.domain_dn()
84 print("baseDN: %s\n" % self.base_dn)
86 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
87 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
88 delete_force(self.ldb, "cn=ldaptest\,specialuser,cn=users," + self.base_dn)
89 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
90 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
91 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
93 def test_users_groups(self):
94 """This tests the SAM users and groups behaviour"""
95 print("Testing users and groups behaviour\n")
98 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
99 "objectclass": "group"})
102 "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
103 "objectclass": "group"})
105 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
106 scope=SCOPE_BASE, attrs=["objectSID"])
107 self.assertTrue(len(res1) == 1)
108 group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
109 res1[0]["objectSID"][0])).split()[1]
111 res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
112 scope=SCOPE_BASE, attrs=["objectSID"])
113 self.assertTrue(len(res1) == 1)
114 group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
115 res1[0]["objectSID"][0])).split()[1]
117 # Try to create a user with an invalid account name
120 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
121 "objectclass": "user",
122 "sAMAccountName": "administrator"})
124 except LdbError as e9:
126 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
127 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
129 # Try to create a user with an invalid account name
132 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
133 "objectclass": "user",
134 "sAMAccountName": []})
136 except LdbError as e10:
138 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
139 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
141 # Try to create a user with an invalid primary group
144 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
145 "objectclass": "user",
146 "primaryGroupID": "0"})
148 except LdbError as e11:
150 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
151 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
153 # Try to Create a user with a valid primary group
156 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
157 "objectclass": "user",
158 "primaryGroupID": str(group_rid_1)})
160 except LdbError as e12:
162 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
163 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
165 # Test to see how we should behave when the user account doesn't
168 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
169 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
174 except LdbError as e13:
176 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
178 # Test to see how we should behave when the account isn't a user
180 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
181 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
186 except LdbError as e14:
188 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
190 # Test default primary groups on add operations
193 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
194 "objectclass": "user"})
196 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
197 scope=SCOPE_BASE, attrs=["primaryGroupID"])
198 self.assertTrue(len(res1) == 1)
199 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
201 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
204 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
205 "objectclass": "user",
206 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD) })
208 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
209 scope=SCOPE_BASE, attrs=["primaryGroupID"])
210 self.assertTrue(len(res1) == 1)
211 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
213 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
215 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
216 # since such accounts aren't directly creatable (ACCESS_DENIED)
219 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
220 "objectclass": "computer",
221 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
223 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
224 scope=SCOPE_BASE, attrs=["primaryGroupID"])
225 self.assertTrue(len(res1) == 1)
226 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
228 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
231 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
232 "objectclass": "computer",
233 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
235 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
236 scope=SCOPE_BASE, attrs=["primaryGroupID"])
237 self.assertTrue(len(res1) == 1)
238 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
240 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
242 # Read-only DC accounts are only creatable by
243 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
244 # we have a fallback in the assertion)
246 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
247 "objectclass": "computer",
248 "userAccountControl": str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
250 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
251 scope=SCOPE_BASE, attrs=["primaryGroupID"])
252 self.assertTrue(len(res1) == 1)
253 self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
254 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
256 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
258 # Test default primary groups on modify operations
261 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
262 "objectclass": "user"})
265 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
266 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
267 "userAccountControl")
270 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
271 scope=SCOPE_BASE, attrs=["primaryGroupID"])
272 self.assertTrue(len(res1) == 1)
273 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
275 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
276 # since such accounts aren't directly creatable (ACCESS_DENIED)
278 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
281 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
282 "objectclass": "computer"})
284 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
285 scope=SCOPE_BASE, attrs=["primaryGroupID"])
286 self.assertTrue(len(res1) == 1)
287 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
290 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
291 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
292 "userAccountControl")
295 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
296 scope=SCOPE_BASE, attrs=["primaryGroupID"])
297 self.assertTrue(len(res1) == 1)
298 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
301 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
302 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
303 "userAccountControl")
306 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
307 scope=SCOPE_BASE, attrs=["primaryGroupID"])
308 self.assertTrue(len(res1) == 1)
309 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
311 # Read-only DC accounts are only creatable by
312 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
313 # we have a fallback in the assertion)
315 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
316 m["userAccountControl"] = MessageElement(str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
317 "userAccountControl")
320 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
321 scope=SCOPE_BASE, attrs=["primaryGroupID"])
322 self.assertTrue(len(res1) == 1)
323 self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
324 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
326 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
328 # Recreate account for further tests
331 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
332 "objectclass": "user"})
334 # Try to set an invalid account name
336 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
337 m["sAMAccountName"] = MessageElement("administrator", FLAG_MOD_REPLACE,
342 except LdbError as e15:
344 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
346 # But to reset the actual "sAMAccountName" should still be possible
347 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
348 scope=SCOPE_BASE, attrs=["sAMAccountName"])
349 self.assertTrue(len(res1) == 1)
351 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
352 m["sAMAccountName"] = MessageElement(res1[0]["sAMAccountName"][0], FLAG_MOD_REPLACE,
356 # And another (free) name should be possible as well
358 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
359 m["sAMAccountName"] = MessageElement("xxx_ldaptestuser_xxx", FLAG_MOD_REPLACE,
363 # We should be able to reset our actual primary group
365 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
366 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS), FLAG_MOD_REPLACE,
370 # Try to add invalid primary group
372 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
373 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
378 except LdbError as e16:
380 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
382 # Try to make group 1 primary - should be denied since it is not yet
385 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
386 m["primaryGroupID"] = MessageElement(str(group_rid_1),
387 FLAG_MOD_REPLACE, "primaryGroupID")
391 except LdbError as e17:
393 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
395 # Make group 1 secondary
397 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
398 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
399 FLAG_MOD_REPLACE, "member")
402 # Make group 1 primary
404 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
405 m["primaryGroupID"] = MessageElement(str(group_rid_1),
406 FLAG_MOD_REPLACE, "primaryGroupID")
409 # Try to delete group 1 - should be denied
411 ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
413 except LdbError as e18:
415 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
417 # Try to add group 1 also as secondary - should be denied
419 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
420 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
421 FLAG_MOD_ADD, "member")
425 except LdbError as e19:
427 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
429 # Try to add invalid member to group 1 - should be denied
431 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
432 m["member"] = MessageElement(
433 "cn=ldaptestuser3,cn=users," + self.base_dn,
434 FLAG_MOD_ADD, "member")
438 except LdbError as e20:
440 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
442 # Make group 2 secondary
444 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
445 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
446 FLAG_MOD_ADD, "member")
451 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
452 m["primaryGroupID"] = MessageElement(str(group_rid_2),
453 FLAG_MOD_REPLACE, "primaryGroupID")
456 # Swap the groups (does not really make sense but does the same)
458 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
459 m["primaryGroupID"] = MessageElement(str(group_rid_1),
460 FLAG_MOD_REPLACE, "primaryGroupID")
461 m["primaryGroupID"] = MessageElement(str(group_rid_2),
462 FLAG_MOD_REPLACE, "primaryGroupID")
465 # Old primary group should contain a "member" attribute for the user,
466 # the new shouldn't contain anymore one
467 res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
468 scope=SCOPE_BASE, attrs=["member"])
469 self.assertTrue(len(res1) == 1)
470 self.assertTrue(len(res1[0]["member"]) == 1)
471 self.assertEquals(res1[0]["member"][0].lower(),
472 ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
474 res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
475 scope=SCOPE_BASE, attrs=["member"])
476 self.assertTrue(len(res1) == 1)
477 self.assertFalse("member" in res1[0])
479 # Primary group member
481 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
482 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
483 FLAG_MOD_DELETE, "member")
487 except LdbError as e21:
489 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
491 # Delete invalid group member
493 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
494 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
495 FLAG_MOD_DELETE, "member")
499 except LdbError as e22:
501 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
503 # Also this should be denied
506 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
507 "objectclass": "user",
508 "primaryGroupID": "0"})
510 except LdbError as e23:
512 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
514 # Recreate user accounts
516 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
519 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
520 "objectclass": "user"})
523 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
524 "objectclass": "user"})
527 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
528 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
529 FLAG_MOD_ADD, "member")
534 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
535 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
536 FLAG_MOD_ADD, "member")
540 except LdbError as e24:
542 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
544 # Already added, but as <SID=...>
545 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
546 scope=SCOPE_BASE, attrs=["objectSid"])
547 self.assertTrue(len(res1) == 1)
548 sid_bin = res1[0]["objectSid"][0]
549 sid_str = ("<SID=" + ldb.schema_format_value("objectSid", sid_bin) + ">").upper()
552 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
553 m["member"] = MessageElement(sid_str, FLAG_MOD_ADD, "member")
557 except LdbError as e25:
559 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
563 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
564 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
565 FLAG_MOD_REPLACE, "member")
569 except LdbError as e26:
571 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
575 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
576 m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
577 "cn=ldaptestuser1,cn=users," + self.base_dn],
578 FLAG_MOD_REPLACE, "member")
582 except LdbError as e27:
584 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
588 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
589 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
590 FLAG_MOD_REPLACE, "member")
591 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
592 FLAG_MOD_ADD, "member")
596 except LdbError as e28:
598 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
601 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
602 m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
603 "cn=ldaptestuser2,cn=users," + self.base_dn],
604 FLAG_MOD_REPLACE, "member")
607 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
608 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
609 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
610 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
612 # Make also a small test for accounts with special DNs ("," in this case)
614 "dn": "cn=ldaptest\,specialuser,cn=users," + self.base_dn,
615 "objectclass": "user"})
616 delete_force(self.ldb, "cn=ldaptest\,specialuser,cn=users," + self.base_dn)
618 def test_sam_attributes(self):
619 """Test the behaviour of special attributes of SAM objects"""
620 print("Testing the behaviour of special attributes of SAM objects\n")
623 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
624 "objectclass": "user"})
626 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
627 "objectclass": "group"})
630 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
631 m["groupType"] = MessageElement(str(GTYPE_SECURITY_GLOBAL_GROUP), FLAG_MOD_ADD,
636 except LdbError as e29:
638 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
640 # Delete protection tests
642 for attr in ["nTSecurityDescriptor", "objectSid", "sAMAccountType",
643 "sAMAccountName", "groupType"]:
646 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
647 m[attr] = MessageElement([], FLAG_MOD_REPLACE, attr)
651 except LdbError as e:
653 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
656 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
657 m[attr] = MessageElement([], FLAG_MOD_DELETE, attr)
661 except LdbError as e1:
663 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
666 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
667 m["primaryGroupID"] = MessageElement("513", FLAG_MOD_ADD,
672 except LdbError as e30:
674 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
677 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
678 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_ADD,
679 "userAccountControl")
683 except LdbError as e31:
685 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
688 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
689 m["objectSid"] = MessageElement("xxxxxxxxxxxxxxxx", FLAG_MOD_ADD,
694 except LdbError as e32:
696 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
699 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
700 m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
705 except LdbError as e33:
707 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
710 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
711 m["sAMAccountName"] = MessageElement("test", FLAG_MOD_ADD,
716 except LdbError as e34:
718 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
720 # Delete protection tests
722 for attr in ["nTSecurityDescriptor", "objectSid", "sAMAccountType",
723 "sAMAccountName", "primaryGroupID", "userAccountControl",
724 "accountExpires", "badPasswordTime", "badPwdCount",
725 "codePage", "countryCode", "lastLogoff", "lastLogon",
726 "logonCount", "pwdLastSet"]:
729 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
730 m[attr] = MessageElement([], FLAG_MOD_REPLACE, attr)
734 except LdbError as e2:
736 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
739 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
740 m[attr] = MessageElement([], FLAG_MOD_DELETE, attr)
744 except LdbError as e3:
746 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
748 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
749 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
751 def test_primary_group_token_constructed(self):
752 """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
753 print("Testing primary group token behaviour and other constructed attributes\n")
757 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
758 "objectclass": "group",
759 "primaryGroupToken": "100"})
761 except LdbError as e35:
763 self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
764 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
767 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
768 "objectclass": "user"})
771 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
772 "objectclass": "group"})
774 # Testing for one invalid, and one valid operational attribute, but also the things they are built from
775 res1 = ldb.search(self.base_dn,
776 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
777 self.assertTrue(len(res1) == 1)
778 self.assertFalse("primaryGroupToken" in res1[0])
779 self.assertTrue("canonicalName" in res1[0])
780 self.assertTrue("objectClass" in res1[0])
781 self.assertTrue("objectSid" in res1[0])
783 res1 = ldb.search(self.base_dn,
784 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
785 self.assertTrue(len(res1) == 1)
786 self.assertFalse("primaryGroupToken" in res1[0])
787 self.assertFalse("objectSid" in res1[0])
788 self.assertFalse("objectClass" in res1[0])
789 self.assertTrue("canonicalName" in res1[0])
791 res1 = ldb.search("cn=users," + self.base_dn,
792 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
793 self.assertTrue(len(res1) == 1)
794 self.assertFalse("primaryGroupToken" in res1[0])
796 res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
797 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
798 self.assertTrue(len(res1) == 1)
799 self.assertFalse("primaryGroupToken" in res1[0])
801 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
803 self.assertTrue(len(res1) == 1)
804 self.assertFalse("primaryGroupToken" in res1[0])
806 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
807 scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
808 self.assertTrue(len(res1) == 1)
809 primary_group_token = int(res1[0]["primaryGroupToken"][0])
811 rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
812 self.assertEquals(primary_group_token, rid)
815 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
816 m["primaryGroupToken"] = "100"
820 except LdbError as e36:
822 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
824 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
825 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
827 def test_tokenGroups(self):
828 """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
829 print("Testing tokenGroups behaviour\n")
831 # The domain object shouldn't contain any "tokenGroups" entry
832 res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
833 self.assertTrue(len(res) == 1)
834 self.assertFalse("tokenGroups" in res[0])
836 # The domain administrator should contain "tokenGroups" entries
837 # (the exact number depends on the domain/forest function level and the
838 # DC software versions)
839 res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
840 scope=SCOPE_BASE, attrs=["tokenGroups"])
841 self.assertTrue(len(res) == 1)
842 self.assertTrue("tokenGroups" in res[0])
845 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
846 "objectclass": "user"})
848 # This testuser should contain at least two "tokenGroups" entries
849 # (exactly two on an unmodified "Domain Users" and "Users" group)
850 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
851 scope=SCOPE_BASE, attrs=["tokenGroups"])
852 self.assertTrue(len(res) == 1)
853 self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
855 # one entry which we need to find should point to domains "Domain Users"
856 # group and another entry should point to the builtin "Users"group
857 domain_users_group_found = False
858 users_group_found = False
859 for sid in res[0]["tokenGroups"]:
860 rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
862 domain_users_group_found = True
864 users_group_found = True
866 self.assertTrue(domain_users_group_found)
867 self.assertTrue(users_group_found)
869 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
871 def test_groupType(self):
872 """Test the groupType behaviour"""
873 print("Testing groupType behaviour\n")
875 # You can never create or change to a
876 # "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP"
883 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
884 "objectclass": "group",
887 except LdbError as e37:
889 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
890 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
894 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
895 "objectclass": "group",
896 "groupType": str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP)})
898 except LdbError as e38:
900 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
901 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
904 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
905 "objectclass": "group",
906 "groupType": str(GTYPE_SECURITY_GLOBAL_GROUP)})
908 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
909 scope=SCOPE_BASE, attrs=["sAMAccountType"])
910 self.assertTrue(len(res1) == 1)
911 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
912 ATYPE_SECURITY_GLOBAL_GROUP)
913 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
916 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
917 "objectclass": "group",
918 "groupType": str(GTYPE_SECURITY_UNIVERSAL_GROUP)})
920 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
921 scope=SCOPE_BASE, attrs=["sAMAccountType"])
922 self.assertTrue(len(res1) == 1)
923 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
924 ATYPE_SECURITY_UNIVERSAL_GROUP)
925 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
928 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
929 "objectclass": "group",
930 "groupType": str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP)})
932 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
933 scope=SCOPE_BASE, attrs=["sAMAccountType"])
934 self.assertTrue(len(res1) == 1)
935 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
936 ATYPE_SECURITY_LOCAL_GROUP)
937 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
940 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
941 "objectclass": "group",
942 "groupType": str(GTYPE_DISTRIBUTION_GLOBAL_GROUP)})
944 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
945 scope=SCOPE_BASE, attrs=["sAMAccountType"])
946 self.assertTrue(len(res1) == 1)
947 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
948 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
949 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
952 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
953 "objectclass": "group",
954 "groupType": str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP)})
956 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
957 scope=SCOPE_BASE, attrs=["sAMAccountType"])
958 self.assertTrue(len(res1) == 1)
959 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
960 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
961 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
964 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
965 "objectclass": "group",
966 "groupType": str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)})
968 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
969 scope=SCOPE_BASE, attrs=["sAMAccountType"])
970 self.assertTrue(len(res1) == 1)
971 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
972 ATYPE_DISTRIBUTION_LOCAL_GROUP)
973 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
978 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
979 "objectclass": "group"})
981 # We can change in this direction: global <-> universal <-> local
982 # On each step also the group type itself (security/distribution) is
985 # After creation we should have a "security global group"
986 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
987 scope=SCOPE_BASE, attrs=["sAMAccountType"])
988 self.assertTrue(len(res1) == 1)
989 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
990 ATYPE_SECURITY_GLOBAL_GROUP)
995 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
996 m["groupType"] = MessageElement("0",
997 FLAG_MOD_REPLACE, "groupType")
1000 except LdbError as e39:
1002 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1006 # Default is "global group"
1009 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1010 m["groupType"] = MessageElement(
1011 str(GTYPE_SECURITY_GLOBAL_GROUP),
1012 FLAG_MOD_REPLACE, "groupType")
1015 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1016 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1017 self.assertTrue(len(res1) == 1)
1018 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1019 ATYPE_SECURITY_GLOBAL_GROUP)
1021 # Change to "local" (shouldn't work)
1025 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1026 m["groupType"] = MessageElement(
1027 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1028 FLAG_MOD_REPLACE, "groupType")
1031 except LdbError as e40:
1033 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1035 # Change to "universal"
1038 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1039 m["groupType"] = MessageElement(
1040 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1041 FLAG_MOD_REPLACE, "groupType")
1044 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1045 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1046 self.assertTrue(len(res1) == 1)
1047 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1048 ATYPE_SECURITY_UNIVERSAL_GROUP)
1050 # Change back to "global"
1053 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1054 m["groupType"] = MessageElement(
1055 str(GTYPE_SECURITY_GLOBAL_GROUP),
1056 FLAG_MOD_REPLACE, "groupType")
1059 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1060 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1061 self.assertTrue(len(res1) == 1)
1062 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1063 ATYPE_SECURITY_GLOBAL_GROUP)
1065 # Change back to "universal"
1068 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1069 m["groupType"] = MessageElement(
1070 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1071 FLAG_MOD_REPLACE, "groupType")
1074 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1075 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1076 self.assertTrue(len(res1) == 1)
1077 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1078 ATYPE_SECURITY_UNIVERSAL_GROUP)
1083 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1084 m["groupType"] = MessageElement(
1085 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1086 FLAG_MOD_REPLACE, "groupType")
1089 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1090 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1091 self.assertTrue(len(res1) == 1)
1092 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1093 ATYPE_SECURITY_LOCAL_GROUP)
1095 # Change to "global" (shouldn't work)
1099 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1100 m["groupType"] = MessageElement(
1101 str(GTYPE_SECURITY_GLOBAL_GROUP),
1102 FLAG_MOD_REPLACE, "groupType")
1105 except LdbError as e41:
1107 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1109 # Change to "builtin local" (shouldn't work)
1113 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1114 m["groupType"] = MessageElement(
1115 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1116 FLAG_MOD_REPLACE, "groupType")
1119 except LdbError as e42:
1121 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1124 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1126 # Change back to "universal"
1129 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1130 m["groupType"] = MessageElement(
1131 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1132 FLAG_MOD_REPLACE, "groupType")
1135 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1136 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1137 self.assertTrue(len(res1) == 1)
1138 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1139 ATYPE_SECURITY_UNIVERSAL_GROUP)
1141 # Change to "builtin local" (shouldn't work)
1145 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1146 m["groupType"] = MessageElement(
1147 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1148 FLAG_MOD_REPLACE, "groupType")
1151 except LdbError as e43:
1153 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1155 # Change back to "global"
1158 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1159 m["groupType"] = MessageElement(
1160 str(GTYPE_SECURITY_GLOBAL_GROUP),
1161 FLAG_MOD_REPLACE, "groupType")
1164 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1165 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1166 self.assertTrue(len(res1) == 1)
1167 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1168 ATYPE_SECURITY_GLOBAL_GROUP)
1170 # Change to "builtin local" (shouldn't work)
1174 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1175 m["groupType"] = MessageElement(
1176 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1177 FLAG_MOD_REPLACE, "groupType")
1180 except LdbError as e44:
1182 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1184 # Distribution groups
1186 # Default is "global group"
1189 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1190 m["groupType"] = MessageElement(
1191 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1192 FLAG_MOD_REPLACE, "groupType")
1195 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1196 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1197 self.assertTrue(len(res1) == 1)
1198 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1199 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1201 # Change to local (shouldn't work)
1205 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1206 m["groupType"] = MessageElement(
1207 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1208 FLAG_MOD_REPLACE, "groupType")
1211 except LdbError as e45:
1213 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1215 # Change to "universal"
1218 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1219 m["groupType"] = MessageElement(
1220 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1221 FLAG_MOD_REPLACE, "groupType")
1224 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1225 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1226 self.assertTrue(len(res1) == 1)
1227 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1228 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1230 # Change back to "global"
1233 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1234 m["groupType"] = MessageElement(
1235 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1236 FLAG_MOD_REPLACE, "groupType")
1239 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1240 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1241 self.assertTrue(len(res1) == 1)
1242 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1243 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1245 # Change back to "universal"
1248 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1249 m["groupType"] = MessageElement(
1250 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1251 FLAG_MOD_REPLACE, "groupType")
1254 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1255 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1256 self.assertTrue(len(res1) == 1)
1257 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1258 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1263 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1264 m["groupType"] = MessageElement(
1265 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1266 FLAG_MOD_REPLACE, "groupType")
1269 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1270 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1271 self.assertTrue(len(res1) == 1)
1272 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1273 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1275 # Change to "global" (shouldn't work)
1279 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1280 m["groupType"] = MessageElement(
1281 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1282 FLAG_MOD_REPLACE, "groupType")
1285 except LdbError as e46:
1287 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1289 # Change back to "universal"
1291 # Try to add invalid member to group 1 - should be denied
1293 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1294 m["member"] = MessageElement(
1295 "cn=ldaptestuser3,cn=users," + self.base_dn,
1296 FLAG_MOD_ADD, "member")
1300 except LdbError as e47:
1302 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1304 # Make group 2 secondary
1306 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1307 m["groupType"] = MessageElement(
1308 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1309 FLAG_MOD_REPLACE, "groupType")
1312 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1313 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1314 self.assertTrue(len(res1) == 1)
1315 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1316 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1318 # Change back to "global"
1321 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1322 m["groupType"] = MessageElement(
1323 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1324 FLAG_MOD_REPLACE, "groupType")
1327 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1328 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1329 self.assertTrue(len(res1) == 1)
1330 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1331 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1333 # Both group types: this performs only random checks - all possibilities
1334 # would require too much code.
1336 # Default is "global group"
1339 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1340 m["groupType"] = MessageElement(
1341 str(GTYPE_SECURITY_GLOBAL_GROUP),
1342 FLAG_MOD_REPLACE, "groupType")
1345 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1346 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1347 self.assertTrue(len(res1) == 1)
1348 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1349 ATYPE_SECURITY_GLOBAL_GROUP)
1351 # Change to "local" (shouldn't work)
1355 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1356 m["groupType"] = MessageElement(
1357 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1358 FLAG_MOD_REPLACE, "groupType")
1361 except LdbError as e48:
1363 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1365 # Change to "universal"
1368 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1369 m["groupType"] = MessageElement(
1370 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1371 FLAG_MOD_REPLACE, "groupType")
1374 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1375 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1376 self.assertTrue(len(res1) == 1)
1377 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1378 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1380 # Change back to "global"
1383 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1384 m["groupType"] = MessageElement(
1385 str(GTYPE_SECURITY_GLOBAL_GROUP),
1386 FLAG_MOD_REPLACE, "groupType")
1389 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1390 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1391 self.assertTrue(len(res1) == 1)
1392 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1393 ATYPE_SECURITY_GLOBAL_GROUP)
1395 # Change back to "universal"
1398 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1399 m["groupType"] = MessageElement(
1400 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1401 FLAG_MOD_REPLACE, "groupType")
1404 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1405 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1406 self.assertTrue(len(res1) == 1)
1407 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1408 ATYPE_SECURITY_UNIVERSAL_GROUP)
1413 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1414 m["groupType"] = MessageElement(
1415 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1416 FLAG_MOD_REPLACE, "groupType")
1419 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1420 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1421 self.assertTrue(len(res1) == 1)
1422 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1423 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1425 # Change to "global" (shouldn't work)
1429 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1430 m["groupType"] = MessageElement(
1431 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1432 FLAG_MOD_REPLACE, "groupType")
1435 except LdbError as e49:
1437 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1439 # Change back to "universal"
1442 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1443 m["groupType"] = MessageElement(
1444 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1445 FLAG_MOD_REPLACE, "groupType")
1448 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1449 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1450 self.assertTrue(len(res1) == 1)
1451 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1452 ATYPE_SECURITY_UNIVERSAL_GROUP)
1454 # Change back to "global"
1457 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1458 m["groupType"] = MessageElement(
1459 str(GTYPE_SECURITY_GLOBAL_GROUP),
1460 FLAG_MOD_REPLACE, "groupType")
1463 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1464 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1465 self.assertTrue(len(res1) == 1)
1466 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1467 ATYPE_SECURITY_GLOBAL_GROUP)
1469 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1471 def test_pwdLastSet(self):
1472 """Test the pwdLastSet behaviour"""
1473 print("Testing pwdLastSet behaviour\n")
1476 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1477 "objectclass": "user",
1480 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1482 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1483 self.assertTrue(len(res1) == 1)
1484 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1485 ATYPE_NORMAL_ACCOUNT)
1486 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1487 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1488 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1489 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1492 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1493 "objectclass": "user",
1494 "pwdLastSet": "-1"})
1496 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1498 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1499 self.assertTrue(len(res1) == 1)
1500 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1501 ATYPE_NORMAL_ACCOUNT)
1502 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1503 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1504 self.assertNotEqual(int(res1[0]["pwdLastSet"][0]), 0)
1505 lastset = int(res1[0]["pwdLastSet"][0])
1506 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1510 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1511 "objectclass": "user",
1512 "pwdLastSet": str(1)})
1514 except LdbError as e50:
1515 (num, msg) = e50.args
1516 self.assertEquals(num, ERR_OTHER)
1517 self.assertTrue('00000057' in msg)
1521 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1522 "objectclass": "user",
1523 "pwdLastSet": str(lastset)})
1525 except LdbError as e51:
1526 (num, msg) = e51.args
1527 self.assertEquals(num, ERR_OTHER)
1528 self.assertTrue('00000057' in msg)
1531 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1532 "objectclass": "user"})
1534 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1536 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1537 self.assertTrue(len(res1) == 1)
1538 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1539 ATYPE_NORMAL_ACCOUNT)
1540 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1541 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1542 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1545 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1546 m["pls1"] = MessageElement(str(0),
1552 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1553 m["pls1"] = MessageElement(str(0),
1556 m["pls2"] = MessageElement(str(0),
1562 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1563 m["pls1"] = MessageElement(str(-1),
1567 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1569 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1570 self.assertTrue(len(res1) == 1)
1571 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1572 ATYPE_NORMAL_ACCOUNT)
1573 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1574 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1575 self.assertGreater(int(res1[0]["pwdLastSet"][0]), lastset)
1576 lastset = int(res1[0]["pwdLastSet"][0])
1580 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1581 m["pls1"] = MessageElement(str(0),
1584 m["pls2"] = MessageElement(str(0),
1589 except LdbError as e52:
1590 (num, msg) = e52.args
1591 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
1592 self.assertTrue('00002085' in msg)
1596 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1597 m["pls1"] = MessageElement(str(-1),
1600 m["pls2"] = MessageElement(str(0),
1605 except LdbError as e53:
1606 (num, msg) = e53.args
1607 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
1608 self.assertTrue('00002085' in msg)
1611 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1612 m["pls1"] = MessageElement(str(lastset),
1615 m["pls2"] = MessageElement(str(-1),
1620 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1622 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1623 self.assertTrue(len(res1) == 1)
1624 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1625 ATYPE_NORMAL_ACCOUNT)
1626 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1627 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1628 self.assertEqual(int(res1[0]["pwdLastSet"][0]), lastset)
1632 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1633 m["pls1"] = MessageElement(str(lastset),
1636 m["pls2"] = MessageElement(str(lastset),
1641 except LdbError as e54:
1642 (num, msg) = e54.args
1643 self.assertEquals(num, ERR_OTHER)
1644 self.assertTrue('00000057' in msg)
1647 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1648 m["pls1"] = MessageElement(str(lastset),
1651 m["pls2"] = MessageElement(str(0),
1655 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1657 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1658 self.assertTrue(len(res1) == 1)
1659 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1660 ATYPE_NORMAL_ACCOUNT)
1661 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1662 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1663 uac = int(res1[0]["userAccountControl"][0])
1664 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1667 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1668 m["uac1"] = MessageElement(str(uac|UF_PASSWORD_EXPIRED),
1670 "userAccountControl")
1672 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1674 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1675 self.assertTrue(len(res1) == 1)
1676 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1677 ATYPE_NORMAL_ACCOUNT)
1678 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1679 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1680 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1682 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1684 def test_ldap_bind_must_change_pwd(self):
1685 """Test the error messages for failing LDAP binds"""
1686 print("Test the error messages for failing LDAP binds\n")
1688 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1690 def format_error_msg(hresult_v, dsid_v, werror_v):
1692 # There are 4 lower case hex digits following 'v' at the end,
1693 # but different Windows Versions return different values:
1695 # Windows 2008R2 uses 'v1db1'
1696 # Windows 2012R2 uses 'v2580'
1698 return "%08X: LdapErr: DSID-%08X, comment: AcceptSecurityContext error, data %x, v" % (
1699 hresult_v, dsid_v, werror_v)
1701 HRES_SEC_E_LOGON_DENIED = 0x8009030C
1702 HRES_SEC_E_INVALID_TOKEN = 0x80090308
1704 sasl_bind_dsid = 0x0C0904DC
1705 simple_bind_dsid = 0x0C0903A9
1707 error_msg_sasl_wrong_pw = format_error_msg(
1708 HRES_SEC_E_LOGON_DENIED,
1710 werror.WERR_LOGON_FAILURE)
1711 error_msg_sasl_must_change = format_error_msg(
1712 HRES_SEC_E_LOGON_DENIED,
1714 werror.WERR_PASSWORD_MUST_CHANGE)
1715 error_msg_simple_wrong_pw = format_error_msg(
1716 HRES_SEC_E_INVALID_TOKEN,
1718 werror.WERR_LOGON_FAILURE)
1719 error_msg_simple_must_change = format_error_msg(
1720 HRES_SEC_E_INVALID_TOKEN,
1722 werror.WERR_PASSWORD_MUST_CHANGE)
1724 username = "ldaptestuser"
1725 password = "thatsAcomplPASS2"
1726 utf16pw = unicode('"' + password.encode('utf-8') + '"', 'utf-8').encode('utf-16-le')
1729 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1730 "objectclass": "user",
1731 "sAMAccountName": username,
1732 "userAccountControl": str(UF_NORMAL_ACCOUNT),
1733 "unicodePwd": utf16pw,
1736 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1738 attrs=["sAMAccountName", "sAMAccountType", "userAccountControl", "pwdLastSet"])
1739 self.assertTrue(len(res1) == 1)
1740 self.assertEqual(res1[0]["sAMAccountName"][0], username)
1741 self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1742 self.assertEqual(int(res1[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT)
1743 self.assertNotEqual(int(res1[0]["pwdLastSet"][0]), 0)
1745 # Open a second LDB connection with the user credentials. Use the
1746 # command line credentials for informations like the domain, the realm
1747 # and the workstation.
1748 sasl_creds = Credentials()
1749 sasl_creds.set_username(username)
1750 sasl_creds.set_password(password)
1751 sasl_creds.set_domain(creds.get_domain())
1752 sasl_creds.set_workstation(creds.get_workstation())
1753 sasl_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1754 sasl_creds.set_kerberos_state(DONT_USE_KERBEROS)
1756 sasl_wrong_creds = Credentials()
1757 sasl_wrong_creds.set_username(username)
1758 sasl_wrong_creds.set_password("wrong")
1759 sasl_wrong_creds.set_domain(creds.get_domain())
1760 sasl_wrong_creds.set_workstation(creds.get_workstation())
1761 sasl_wrong_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1762 sasl_wrong_creds.set_kerberos_state(DONT_USE_KERBEROS)
1764 simple_creds = Credentials()
1765 simple_creds.set_bind_dn("cn=ldaptestuser,cn=users," + self.base_dn)
1766 simple_creds.set_username(username)
1767 simple_creds.set_password(password)
1768 simple_creds.set_domain(creds.get_domain())
1769 simple_creds.set_workstation(creds.get_workstation())
1770 simple_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1771 simple_creds.set_kerberos_state(DONT_USE_KERBEROS)
1773 simple_wrong_creds = Credentials()
1774 simple_wrong_creds.set_bind_dn("cn=ldaptestuser,cn=users," + self.base_dn)
1775 simple_wrong_creds.set_username(username)
1776 simple_wrong_creds.set_password("wrong")
1777 simple_wrong_creds.set_domain(creds.get_domain())
1778 simple_wrong_creds.set_workstation(creds.get_workstation())
1779 simple_wrong_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1780 simple_wrong_creds.set_kerberos_state(DONT_USE_KERBEROS)
1782 sasl_ldb = SamDB(url=host, credentials=sasl_creds, lp=lp)
1783 self.assertIsNotNone(sasl_ldb)
1786 requires_strong_auth = False
1788 simple_ldb = SamDB(url=host, credentials=simple_creds, lp=lp)
1789 self.assertIsNotNone(simple_ldb)
1791 except LdbError as e55:
1792 (num, msg) = e55.args
1793 if num != ERR_STRONG_AUTH_REQUIRED:
1795 requires_strong_auth = True
1797 def assertLDAPErrorMsg(msg, expected_msg):
1798 self.assertTrue(expected_msg in msg,
1799 "msg[%s] does not contain expected[%s]" % (
1803 ldb_fail = SamDB(url=host, credentials=sasl_wrong_creds, lp=lp)
1805 except LdbError as e56:
1806 (num, msg) = e56.args
1807 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1808 self.assertTrue(error_msg_sasl_wrong_pw in msg)
1810 if not requires_strong_auth:
1812 ldb_fail = SamDB(url=host, credentials=simple_wrong_creds, lp=lp)
1814 except LdbError as e4:
1815 (num, msg) = e4.args
1816 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1817 assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw)
1820 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1821 m["pls1"] = MessageElement(str(0),
1826 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1827 scope=SCOPE_BASE, attrs=["pwdLastSet"])
1828 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1831 ldb_fail = SamDB(url=host, credentials=sasl_wrong_creds, lp=lp)
1833 except LdbError as e57:
1834 (num, msg) = e57.args
1835 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1836 assertLDAPErrorMsg(msg, error_msg_sasl_wrong_pw)
1839 ldb_fail = SamDB(url=host, credentials=sasl_creds, lp=lp)
1841 except LdbError as e58:
1842 (num, msg) = e58.args
1843 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1844 assertLDAPErrorMsg(msg, error_msg_sasl_must_change)
1846 if not requires_strong_auth:
1848 ldb_fail = SamDB(url=host, credentials=simple_wrong_creds, lp=lp)
1850 except LdbError as e5:
1851 (num, msg) = e5.args
1852 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1853 assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw)
1856 ldb_fail = SamDB(url=host, credentials=simple_creds, lp=lp)
1858 except LdbError as e6:
1859 (num, msg) = e6.args
1860 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1861 assertLDAPErrorMsg(msg, error_msg_simple_must_change)
1863 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1865 def test_userAccountControl(self):
1866 """Test the userAccountControl behaviour"""
1867 print("Testing userAccountControl behaviour\n")
1869 # With a user object
1873 # As user you can only set a normal account.
1874 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1876 # With SYSTEM rights you can set a interdomain trust account.
1879 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1880 "objectclass": "user",
1881 "userAccountControl": "0"})
1883 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1885 attrs=["sAMAccountType", "userAccountControl"])
1886 self.assertTrue(len(res1) == 1)
1887 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1888 ATYPE_NORMAL_ACCOUNT)
1889 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
1890 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0)
1891 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1894 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1895 "objectclass": "user",
1896 "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1897 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1900 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1901 "objectclass": "user",
1902 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1904 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1906 attrs=["sAMAccountType", "userAccountControl"])
1907 self.assertTrue(len(res1) == 1)
1908 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1909 ATYPE_NORMAL_ACCOUNT)
1910 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
1911 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1914 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1915 "objectclass": "user",
1916 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_LOCKOUT | UF_PASSWORD_EXPIRED)})
1918 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1920 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
1921 self.assertTrue(len(res1) == 1)
1922 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1923 ATYPE_NORMAL_ACCOUNT)
1924 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
1925 self.assertFalse("lockoutTime" in res1[0])
1926 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
1927 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1931 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1932 "objectclass": "user",
1933 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1935 except LdbError as e59:
1937 self.assertEquals(num, ERR_OTHER)
1938 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1942 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1943 "objectclass": "user",
1944 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1946 except LdbError as e60:
1948 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1949 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1953 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1954 "objectclass": "user",
1955 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1956 except LdbError as e61:
1958 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1959 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1963 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1964 "objectclass": "user",
1965 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)})
1966 except LdbError as e62:
1968 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1969 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1973 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1974 "objectclass": "user",
1975 "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1977 except LdbError as e63:
1979 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1980 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1985 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1986 "objectclass": "user"})
1988 # After creation we should have a normal account
1989 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1991 attrs=["sAMAccountType", "userAccountControl"])
1992 self.assertTrue(len(res1) == 1)
1993 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1994 ATYPE_NORMAL_ACCOUNT)
1995 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
1997 # As user you can only switch from a normal account to a workstation
1998 # trust account and back.
1999 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2001 # With SYSTEM rights you can switch to a interdomain trust account.
2006 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2007 m["userAccountControl"] = MessageElement("0",
2008 FLAG_MOD_REPLACE, "userAccountControl")
2010 except LdbError as e64:
2012 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2016 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2017 m["userAccountControl"] = MessageElement(
2018 str(UF_NORMAL_ACCOUNT),
2019 FLAG_MOD_REPLACE, "userAccountControl")
2021 except LdbError as e65:
2023 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2026 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2027 m["userAccountControl"] = MessageElement(
2028 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2029 FLAG_MOD_REPLACE, "userAccountControl")
2032 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2034 attrs=["sAMAccountType", "userAccountControl"])
2035 self.assertTrue(len(res1) == 1)
2036 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2037 ATYPE_NORMAL_ACCOUNT)
2038 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2041 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2042 m["userAccountControl"] = MessageElement(
2043 str(UF_ACCOUNTDISABLE),
2044 FLAG_MOD_REPLACE, "userAccountControl")
2047 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2049 attrs=["sAMAccountType", "userAccountControl"])
2050 self.assertTrue(len(res1) == 1)
2051 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2052 ATYPE_NORMAL_ACCOUNT)
2053 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2054 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2057 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2058 m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
2059 m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
2063 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2064 m["userAccountControl"] = MessageElement(
2065 str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
2066 FLAG_MOD_REPLACE, "userAccountControl")
2069 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2071 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2072 self.assertTrue(len(res1) == 1)
2073 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2074 ATYPE_NORMAL_ACCOUNT)
2075 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2076 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2077 self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
2078 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2082 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2083 m["userAccountControl"] = MessageElement(
2084 str(UF_TEMP_DUPLICATE_ACCOUNT),
2085 FLAG_MOD_REPLACE, "userAccountControl")
2088 except LdbError as e66:
2090 self.assertEquals(num, ERR_OTHER)
2094 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2095 m["userAccountControl"] = MessageElement(
2096 str(UF_SERVER_TRUST_ACCOUNT),
2097 FLAG_MOD_REPLACE, "userAccountControl")
2100 except LdbError as e67:
2102 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2105 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2106 m["userAccountControl"] = MessageElement(
2107 str(UF_WORKSTATION_TRUST_ACCOUNT),
2108 FLAG_MOD_REPLACE, "userAccountControl")
2113 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2114 m["userAccountControl"] = MessageElement(
2115 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT),
2116 FLAG_MOD_REPLACE, "userAccountControl")
2119 except LdbError as e68:
2121 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2123 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2124 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2125 self.assertTrue(len(res1) == 1)
2126 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2127 ATYPE_WORKSTATION_TRUST)
2130 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2131 m["userAccountControl"] = MessageElement(
2132 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2133 FLAG_MOD_REPLACE, "userAccountControl")
2136 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2137 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2138 self.assertTrue(len(res1) == 1)
2139 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2140 ATYPE_NORMAL_ACCOUNT)
2144 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2145 m["userAccountControl"] = MessageElement(
2146 str(UF_INTERDOMAIN_TRUST_ACCOUNT),
2147 FLAG_MOD_REPLACE, "userAccountControl")
2150 except LdbError as e69:
2152 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2154 # With a computer object
2158 # As computer you can set a normal account and a server trust account.
2159 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2161 # With SYSTEM rights you can set a interdomain trust account.
2164 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2165 "objectclass": "computer",
2166 "userAccountControl": "0"})
2168 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2170 attrs=["sAMAccountType", "userAccountControl"])
2171 self.assertTrue(len(res1) == 1)
2172 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2173 ATYPE_NORMAL_ACCOUNT)
2174 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2175 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0)
2176 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2179 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2180 "objectclass": "computer",
2181 "userAccountControl": str(UF_NORMAL_ACCOUNT)})
2182 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2185 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2186 "objectclass": "computer",
2187 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
2189 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2191 attrs=["sAMAccountType", "userAccountControl"])
2192 self.assertTrue(len(res1) == 1)
2193 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2194 ATYPE_NORMAL_ACCOUNT)
2195 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2196 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2199 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2200 "objectclass": "computer",
2201 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_LOCKOUT | UF_PASSWORD_EXPIRED)})
2203 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2205 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2206 self.assertTrue(len(res1) == 1)
2207 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2208 ATYPE_NORMAL_ACCOUNT)
2209 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2210 self.assertFalse("lockoutTime" in res1[0])
2211 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2212 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2216 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2217 "objectclass": "computer",
2218 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
2220 except LdbError as e70:
2222 self.assertEquals(num, ERR_OTHER)
2223 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2226 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2227 "objectclass": "computer",
2228 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
2230 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2231 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2232 self.assertTrue(len(res1) == 1)
2233 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2234 ATYPE_WORKSTATION_TRUST)
2235 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2239 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2240 "objectclass": "computer",
2241 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
2242 except LdbError as e71:
2244 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
2245 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2249 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2250 "objectclass": "computer",
2251 "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
2253 except LdbError as e72:
2255 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2256 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2261 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2262 "objectclass": "computer"})
2264 # After creation we should have a normal account
2265 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2267 attrs=["sAMAccountType", "userAccountControl"])
2268 self.assertTrue(len(res1) == 1)
2269 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2270 ATYPE_NORMAL_ACCOUNT)
2271 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2273 # As computer you can switch from a normal account to a workstation
2274 # or server trust account and back (also swapping between trust
2275 # accounts is allowed).
2276 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2278 # With SYSTEM rights you can switch to a interdomain trust account.
2283 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2284 m["userAccountControl"] = MessageElement("0",
2285 FLAG_MOD_REPLACE, "userAccountControl")
2287 except LdbError as e73:
2289 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2293 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2294 m["userAccountControl"] = MessageElement(
2295 str(UF_NORMAL_ACCOUNT),
2296 FLAG_MOD_REPLACE, "userAccountControl")
2298 except LdbError as e74:
2300 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2303 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2304 m["userAccountControl"] = MessageElement(
2305 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2306 FLAG_MOD_REPLACE, "userAccountControl")
2309 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2311 attrs=["sAMAccountType", "userAccountControl"])
2312 self.assertTrue(len(res1) == 1)
2313 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2314 ATYPE_NORMAL_ACCOUNT)
2315 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2318 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2319 m["userAccountControl"] = MessageElement(
2320 str(UF_ACCOUNTDISABLE),
2321 FLAG_MOD_REPLACE, "userAccountControl")
2324 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2326 attrs=["sAMAccountType", "userAccountControl"])
2327 self.assertTrue(len(res1) == 1)
2328 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2329 ATYPE_NORMAL_ACCOUNT)
2330 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2331 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2334 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2335 m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
2336 m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
2340 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2341 m["userAccountControl"] = MessageElement(
2342 str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
2343 FLAG_MOD_REPLACE, "userAccountControl")
2346 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2348 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2349 self.assertTrue(len(res1) == 1)
2350 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2351 ATYPE_NORMAL_ACCOUNT)
2352 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2353 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2354 self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
2355 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2359 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2360 m["userAccountControl"] = MessageElement(
2361 str(UF_TEMP_DUPLICATE_ACCOUNT),
2362 FLAG_MOD_REPLACE, "userAccountControl")
2365 except LdbError as e75:
2367 self.assertEquals(num, ERR_OTHER)
2370 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2371 m["userAccountControl"] = MessageElement(
2372 str(UF_SERVER_TRUST_ACCOUNT),
2373 FLAG_MOD_REPLACE, "userAccountControl")
2376 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2377 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2378 self.assertTrue(len(res1) == 1)
2379 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2380 ATYPE_WORKSTATION_TRUST)
2383 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2384 m["userAccountControl"] = MessageElement(
2385 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2386 FLAG_MOD_REPLACE, "userAccountControl")
2389 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2390 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2391 self.assertTrue(len(res1) == 1)
2392 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2393 ATYPE_NORMAL_ACCOUNT)
2396 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2397 m["userAccountControl"] = MessageElement(
2398 str(UF_WORKSTATION_TRUST_ACCOUNT),
2399 FLAG_MOD_REPLACE, "userAccountControl")
2402 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2403 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2404 self.assertTrue(len(res1) == 1)
2405 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2406 ATYPE_WORKSTATION_TRUST)
2409 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2410 m["userAccountControl"] = MessageElement(
2411 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2412 FLAG_MOD_REPLACE, "userAccountControl")
2415 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2416 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2417 self.assertTrue(len(res1) == 1)
2418 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2419 ATYPE_NORMAL_ACCOUNT)
2422 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2423 m["userAccountControl"] = MessageElement(
2424 str(UF_SERVER_TRUST_ACCOUNT),
2425 FLAG_MOD_REPLACE, "userAccountControl")
2428 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2429 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2430 self.assertTrue(len(res1) == 1)
2431 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2432 ATYPE_WORKSTATION_TRUST)
2435 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2436 m["userAccountControl"] = MessageElement(
2437 str(UF_WORKSTATION_TRUST_ACCOUNT),
2438 FLAG_MOD_REPLACE, "userAccountControl")
2441 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2442 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2443 self.assertTrue(len(res1) == 1)
2444 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2445 ATYPE_WORKSTATION_TRUST)
2449 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2450 m["userAccountControl"] = MessageElement(
2451 str(UF_INTERDOMAIN_TRUST_ACCOUNT),
2452 FLAG_MOD_REPLACE, "userAccountControl")
2455 except LdbError as e76:
2457 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2459 # "primaryGroupID" does not change if account type remains the same
2461 # For a user account
2464 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
2465 "objectclass": "user",
2466 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)})
2468 res1 = ldb.search("cn=ldaptestuser2,cn=users," + self.base_dn,
2470 attrs=["userAccountControl"])
2471 self.assertTrue(len(res1) == 1)
2472 self.assertEquals(int(res1[0]["userAccountControl"][0]),
2473 UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2476 m.dn = Dn(ldb, "<SID=" + ldb.get_domain_sid() + "-" + str(DOMAIN_RID_ADMINS) + ">")
2477 m["member"] = MessageElement(
2478 "cn=ldaptestuser2,cn=users," + self.base_dn, FLAG_MOD_ADD, "member")
2482 m.dn = Dn(ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2483 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_ADMINS),
2484 FLAG_MOD_REPLACE, "primaryGroupID")
2488 m.dn = Dn(ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2489 m["userAccountControl"] = MessageElement(
2490 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2491 FLAG_MOD_REPLACE, "userAccountControl")
2494 res1 = ldb.search("cn=ldaptestuser2,cn=users," + self.base_dn,
2496 attrs=["userAccountControl", "primaryGroupID"])
2497 self.assertTrue(len(res1) == 1)
2498 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2499 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_ADMINS)
2501 # For a workstation account
2503 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2505 attrs=["primaryGroupID"])
2506 self.assertTrue(len(res1) == 1)
2507 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS)
2510 m.dn = Dn(ldb, "<SID=" + ldb.get_domain_sid() + "-" + str(DOMAIN_RID_USERS) + ">")
2511 m["member"] = MessageElement(
2512 "cn=ldaptestcomputer,cn=computers," + self.base_dn, FLAG_MOD_ADD, "member")
2516 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2517 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS),
2518 FLAG_MOD_REPLACE, "primaryGroupID")
2522 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2523 m["userAccountControl"] = MessageElement(
2524 str(UF_WORKSTATION_TRUST_ACCOUNT),
2525 FLAG_MOD_REPLACE, "userAccountControl")
2528 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2530 attrs=["primaryGroupID"])
2531 self.assertTrue(len(res1) == 1)
2532 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS)
2534 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2535 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2536 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2538 def find_repl_meta_data(self, rpmd, attid):
2539 for i in range(0, rpmd.ctr.count):
2540 m = rpmd.ctr.array[i]
2541 if m.attid == attid:
2545 def test_smartcard_required1(self):
2546 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2547 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2549 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2552 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2553 "objectclass": "user",
2554 "userAccountControl": str(UF_NORMAL_ACCOUNT),
2555 "unicodePwd": "\"thatsAcomplPASS2\"".encode('utf-16-le')
2558 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2560 attrs=["sAMAccountType", "userAccountControl",
2561 "pwdLastSet", "msDS-KeyVersionNumber",
2562 "replPropertyMetaData"])
2563 self.assertTrue(len(res) == 1)
2564 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2565 ATYPE_NORMAL_ACCOUNT)
2566 self.assertEqual(int(res[0]["userAccountControl"][0]),
2568 self.assertNotEqual(int(res[0]["pwdLastSet"][0]), 0)
2569 lastset = int(res[0]["pwdLastSet"][0])
2570 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2571 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2572 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2573 res[0]["replPropertyMetaData"][0])
2574 lastsetmd = self.find_repl_meta_data(rpmd,
2575 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2576 self.assertIsNotNone(lastsetmd)
2577 self.assertEqual(lastsetmd.version, 1)
2578 nthashmd = self.find_repl_meta_data(rpmd,
2579 drsuapi.DRSUAPI_ATTID_unicodePwd)
2580 self.assertIsNotNone(nthashmd)
2581 self.assertEqual(nthashmd.version, 1)
2582 nthistmd = self.find_repl_meta_data(rpmd,
2583 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2584 self.assertIsNotNone(nthistmd)
2585 self.assertEqual(nthistmd.version, 1)
2586 lmhashmd = self.find_repl_meta_data(rpmd,
2587 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2588 self.assertIsNotNone(lmhashmd)
2589 self.assertEqual(lmhashmd.version, 1)
2590 lmhistmd = self.find_repl_meta_data(rpmd,
2591 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2592 self.assertIsNotNone(lmhistmd)
2593 self.assertEqual(lmhistmd.version, 1)
2594 spcbmd = self.find_repl_meta_data(rpmd,
2595 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2596 self.assertIsNotNone(spcbmd)
2597 self.assertEqual(spcbmd.version, 1)
2600 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2601 m["userAccountControl"] = MessageElement(
2602 str(UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED),
2603 FLAG_MOD_REPLACE, "userAccountControl")
2606 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2608 attrs=["sAMAccountType", "userAccountControl",
2609 "pwdLastSet", "msDS-KeyVersionNumber",
2610 "replPropertyMetaData"])
2611 self.assertTrue(len(res) == 1)
2612 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2613 ATYPE_NORMAL_ACCOUNT)
2614 self.assertEqual(int(res[0]["userAccountControl"][0]),
2615 UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED)
2616 self.assertEqual(int(res[0]["pwdLastSet"][0]), lastset)
2617 lastset1 = int(res[0]["pwdLastSet"][0])
2618 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2619 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2620 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2621 res[0]["replPropertyMetaData"][0])
2622 lastsetmd = self.find_repl_meta_data(rpmd,
2623 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2624 self.assertIsNotNone(lastsetmd)
2625 self.assertEqual(lastsetmd.version, 1)
2626 nthashmd = self.find_repl_meta_data(rpmd,
2627 drsuapi.DRSUAPI_ATTID_unicodePwd)
2628 self.assertIsNotNone(nthashmd)
2629 self.assertEqual(nthashmd.version, 2)
2630 nthistmd = self.find_repl_meta_data(rpmd,
2631 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2632 self.assertIsNotNone(nthistmd)
2633 self.assertEqual(nthistmd.version, 2)
2634 lmhashmd = self.find_repl_meta_data(rpmd,
2635 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2636 self.assertIsNotNone(lmhashmd)
2637 self.assertEqual(lmhashmd.version, 2)
2638 lmhistmd = self.find_repl_meta_data(rpmd,
2639 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2640 self.assertIsNotNone(lmhistmd)
2641 self.assertEqual(lmhistmd.version, 2)
2642 spcbmd = self.find_repl_meta_data(rpmd,
2643 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2644 self.assertIsNotNone(spcbmd)
2645 self.assertEqual(spcbmd.version, 2)
2647 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2649 def test_smartcard_required2(self):
2650 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2651 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2653 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2656 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2657 "objectclass": "user",
2658 "userAccountControl": str(UF_NORMAL_ACCOUNT|UF_ACCOUNTDISABLE),
2661 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2663 attrs=["sAMAccountType", "userAccountControl",
2664 "pwdLastSet", "msDS-KeyVersionNumber",
2665 "replPropertyMetaData"])
2666 self.assertTrue(len(res) == 1)
2667 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2668 ATYPE_NORMAL_ACCOUNT)
2669 self.assertEqual(int(res[0]["userAccountControl"][0]),
2670 UF_NORMAL_ACCOUNT|UF_ACCOUNTDISABLE)
2671 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2672 self.assertTrue("msDS-KeyVersionNumber" in res[0])
2673 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2674 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2675 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2676 res[0]["replPropertyMetaData"][0])
2677 lastsetmd = self.find_repl_meta_data(rpmd,
2678 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2679 self.assertIsNotNone(lastsetmd)
2680 self.assertEqual(lastsetmd.version, 1)
2681 nthashmd = self.find_repl_meta_data(rpmd,
2682 drsuapi.DRSUAPI_ATTID_unicodePwd)
2683 self.assertIsNotNone(nthashmd)
2684 self.assertEqual(nthashmd.version, 1)
2685 nthistmd = self.find_repl_meta_data(rpmd,
2686 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2687 self.assertIsNotNone(nthistmd)
2688 self.assertEqual(nthistmd.version, 1)
2689 lmhashmd = self.find_repl_meta_data(rpmd,
2690 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2691 self.assertIsNotNone(lmhashmd)
2692 self.assertEqual(lmhashmd.version, 1)
2693 lmhistmd = self.find_repl_meta_data(rpmd,
2694 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2695 self.assertIsNotNone(lmhistmd)
2696 self.assertEqual(lmhistmd.version, 1)
2697 spcbmd = self.find_repl_meta_data(rpmd,
2698 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2699 self.assertIsNone(spcbmd)
2702 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2703 m["userAccountControl"] = MessageElement(
2704 str(UF_NORMAL_ACCOUNT|UF_ACCOUNTDISABLE|UF_SMARTCARD_REQUIRED),
2705 FLAG_MOD_REPLACE, "userAccountControl")
2708 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2710 attrs=["sAMAccountType", "userAccountControl",
2711 "pwdLastSet", "msDS-KeyVersionNumber",
2712 "replPropertyMetaData"])
2713 self.assertTrue(len(res) == 1)
2714 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2715 ATYPE_NORMAL_ACCOUNT)
2716 self.assertEqual(int(res[0]["userAccountControl"][0]),
2717 UF_NORMAL_ACCOUNT|UF_ACCOUNTDISABLE|UF_SMARTCARD_REQUIRED)
2718 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2719 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2720 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2721 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2722 res[0]["replPropertyMetaData"][0])
2723 lastsetmd = self.find_repl_meta_data(rpmd,
2724 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2725 self.assertIsNotNone(lastsetmd)
2726 self.assertEqual(lastsetmd.version, 1)
2727 nthashmd = self.find_repl_meta_data(rpmd,
2728 drsuapi.DRSUAPI_ATTID_unicodePwd)
2729 self.assertIsNotNone(nthashmd)
2730 self.assertEqual(nthashmd.version, 2)
2731 nthistmd = self.find_repl_meta_data(rpmd,
2732 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2733 self.assertIsNotNone(nthistmd)
2734 self.assertEqual(nthistmd.version, 2)
2735 lmhashmd = self.find_repl_meta_data(rpmd,
2736 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2737 self.assertIsNotNone(lmhashmd)
2738 self.assertEqual(lmhashmd.version, 2)
2739 lmhistmd = self.find_repl_meta_data(rpmd,
2740 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2741 self.assertIsNotNone(lmhistmd)
2742 self.assertEqual(lmhistmd.version, 2)
2743 spcbmd = self.find_repl_meta_data(rpmd,
2744 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2745 self.assertIsNotNone(spcbmd)
2746 self.assertEqual(spcbmd.version, 1)
2749 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2750 m["userAccountControl"] = MessageElement(
2751 str(UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED),
2752 FLAG_MOD_REPLACE, "userAccountControl")
2755 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2757 attrs=["sAMAccountType", "userAccountControl",
2758 "pwdLastSet", "msDS-KeyVersionNumber",
2759 "replPropertyMetaData"])
2760 self.assertTrue(len(res) == 1)
2761 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2762 ATYPE_NORMAL_ACCOUNT)
2763 self.assertEqual(int(res[0]["userAccountControl"][0]),
2764 UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED)
2765 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2766 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2767 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2768 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2769 res[0]["replPropertyMetaData"][0])
2770 lastsetmd = self.find_repl_meta_data(rpmd,
2771 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2772 self.assertIsNotNone(lastsetmd)
2773 self.assertEqual(lastsetmd.version, 1)
2774 nthashmd = self.find_repl_meta_data(rpmd,
2775 drsuapi.DRSUAPI_ATTID_unicodePwd)
2776 self.assertIsNotNone(nthashmd)
2777 self.assertEqual(nthashmd.version, 2)
2778 nthistmd = self.find_repl_meta_data(rpmd,
2779 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2780 self.assertIsNotNone(nthistmd)
2781 self.assertEqual(nthistmd.version, 2)
2782 lmhashmd = self.find_repl_meta_data(rpmd,
2783 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2784 self.assertIsNotNone(lmhashmd)
2785 self.assertEqual(lmhashmd.version, 2)
2786 lmhistmd = self.find_repl_meta_data(rpmd,
2787 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2788 self.assertIsNotNone(lmhistmd)
2789 self.assertEqual(lmhistmd.version, 2)
2790 spcbmd = self.find_repl_meta_data(rpmd,
2791 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2792 self.assertIsNotNone(spcbmd)
2793 self.assertEqual(spcbmd.version, 1)
2795 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2797 def test_smartcard_required3(self):
2798 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2799 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2801 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2804 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2805 "objectclass": "user",
2806 "userAccountControl": str(UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED|UF_ACCOUNTDISABLE),
2809 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2811 attrs=["sAMAccountType", "userAccountControl",
2812 "pwdLastSet", "msDS-KeyVersionNumber",
2813 "replPropertyMetaData"])
2814 self.assertTrue(len(res) == 1)
2815 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2816 ATYPE_NORMAL_ACCOUNT)
2817 self.assertEqual(int(res[0]["userAccountControl"][0]),
2818 UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED|UF_ACCOUNTDISABLE)
2819 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2820 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2821 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2822 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2823 res[0]["replPropertyMetaData"][0])
2824 lastsetmd = self.find_repl_meta_data(rpmd,
2825 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2826 self.assertIsNotNone(lastsetmd)
2827 self.assertEqual(lastsetmd.version, 1)
2828 nthashmd = self.find_repl_meta_data(rpmd,
2829 drsuapi.DRSUAPI_ATTID_unicodePwd)
2830 self.assertIsNotNone(nthashmd)
2831 self.assertEqual(nthashmd.version, 1)
2832 nthistmd = self.find_repl_meta_data(rpmd,
2833 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2834 self.assertIsNotNone(nthistmd)
2835 self.assertEqual(nthistmd.version, 1)
2836 lmhashmd = self.find_repl_meta_data(rpmd,
2837 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2838 self.assertIsNotNone(lmhashmd)
2839 self.assertEqual(lmhashmd.version, 1)
2840 lmhistmd = self.find_repl_meta_data(rpmd,
2841 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2842 self.assertIsNotNone(lmhistmd)
2843 self.assertEqual(lmhistmd.version, 1)
2844 spcbmd = self.find_repl_meta_data(rpmd,
2845 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2846 self.assertIsNotNone(spcbmd)
2847 self.assertEqual(spcbmd.version, 1)
2850 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2851 m["userAccountControl"] = MessageElement(
2852 str(UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED),
2853 FLAG_MOD_REPLACE, "userAccountControl")
2856 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2858 attrs=["sAMAccountType", "userAccountControl",
2859 "pwdLastSet", "msDS-KeyVersionNumber",
2860 "replPropertyMetaData"])
2861 self.assertTrue(len(res) == 1)
2862 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2863 ATYPE_NORMAL_ACCOUNT)
2864 self.assertEqual(int(res[0]["userAccountControl"][0]),
2865 UF_NORMAL_ACCOUNT|UF_SMARTCARD_REQUIRED)
2866 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2867 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2868 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2869 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2870 res[0]["replPropertyMetaData"][0])
2871 lastsetmd = self.find_repl_meta_data(rpmd,
2872 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2873 self.assertIsNotNone(lastsetmd)
2874 self.assertEqual(lastsetmd.version, 1)
2875 nthashmd = self.find_repl_meta_data(rpmd,
2876 drsuapi.DRSUAPI_ATTID_unicodePwd)
2877 self.assertIsNotNone(nthashmd)
2878 self.assertEqual(nthashmd.version, 1)
2879 nthistmd = self.find_repl_meta_data(rpmd,
2880 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2881 self.assertIsNotNone(nthistmd)
2882 self.assertEqual(nthistmd.version, 1)
2883 lmhashmd = self.find_repl_meta_data(rpmd,
2884 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2885 self.assertIsNotNone(lmhashmd)
2886 self.assertEqual(lmhashmd.version, 1)
2887 lmhistmd = self.find_repl_meta_data(rpmd,
2888 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2889 self.assertIsNotNone(lmhistmd)
2890 self.assertEqual(lmhistmd.version, 1)
2891 spcbmd = self.find_repl_meta_data(rpmd,
2892 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2893 self.assertIsNotNone(spcbmd)
2894 self.assertEqual(spcbmd.version, 1)
2896 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2898 def test_isCriticalSystemObject(self):
2899 """Test the isCriticalSystemObject behaviour"""
2900 print("Testing isCriticalSystemObject behaviour\n")
2905 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2906 "objectclass": "computer"})
2908 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2910 attrs=["isCriticalSystemObject"])
2911 self.assertTrue(len(res1) == 1)
2912 self.assertTrue("isCriticalSystemObject" not in res1[0])
2914 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2917 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2918 "objectclass": "computer",
2919 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
2921 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2923 attrs=["isCriticalSystemObject"])
2924 self.assertTrue(len(res1) == 1)
2925 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "FALSE")
2927 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2930 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2931 "objectclass": "computer",
2932 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)})
2934 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2936 attrs=["isCriticalSystemObject"])
2937 self.assertTrue(len(res1) == 1)
2938 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2940 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2943 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2944 "objectclass": "computer",
2945 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
2947 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2949 attrs=["isCriticalSystemObject"])
2950 self.assertTrue(len(res1) == 1)
2951 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2953 # Modification tests
2956 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2957 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2958 FLAG_MOD_REPLACE, "userAccountControl")
2961 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2963 attrs=["isCriticalSystemObject"])
2964 self.assertTrue(len(res1) == 1)
2965 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2968 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2969 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT),
2970 FLAG_MOD_REPLACE, "userAccountControl")
2973 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2975 attrs=["isCriticalSystemObject"])
2976 self.assertTrue(len(res1) == 1)
2977 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "FALSE")
2980 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2981 m["userAccountControl"] = MessageElement(
2982 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT),
2983 FLAG_MOD_REPLACE, "userAccountControl")
2986 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2988 attrs=["isCriticalSystemObject"])
2989 self.assertTrue(len(res1) == 1)
2990 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2993 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2994 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2995 FLAG_MOD_REPLACE, "userAccountControl")
2998 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3000 attrs=["isCriticalSystemObject"])
3001 self.assertTrue(len(res1) == 1)
3002 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
3005 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3006 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT),
3007 FLAG_MOD_REPLACE, "userAccountControl")
3010 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3012 attrs=["isCriticalSystemObject"])
3013 self.assertTrue(len(res1) == 1)
3014 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
3017 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3018 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT),
3019 FLAG_MOD_REPLACE, "userAccountControl")
3022 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3024 attrs=["isCriticalSystemObject"])
3025 self.assertTrue(len(res1) == 1)
3026 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "FALSE")
3028 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3030 def test_service_principal_name_updates(self):
3031 """Test the servicePrincipalNames update behaviour"""
3032 print("Testing servicePrincipalNames update behaviour\n")
3035 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3036 "objectclass": "computer",
3037 "dNSHostName": "testname.testdom"})
3039 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3040 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3041 self.assertTrue(len(res) == 1)
3042 self.assertFalse("servicePrincipalName" in res[0])
3044 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3047 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3048 "objectclass": "computer",
3049 "servicePrincipalName": "HOST/testname.testdom"})
3051 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3052 scope=SCOPE_BASE, attrs=["dNSHostName"])
3053 self.assertTrue(len(res) == 1)
3054 self.assertFalse("dNSHostName" in res[0])
3056 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3059 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3060 "objectclass": "computer",
3061 "dNSHostName": "testname2.testdom",
3062 "servicePrincipalName": "HOST/testname.testdom"})
3064 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3065 scope=SCOPE_BASE, attrs=["dNSHostName"])
3066 self.assertTrue(len(res) == 1)
3067 self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
3069 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3070 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3071 self.assertTrue(len(res) == 1)
3072 self.assertEquals(res[0]["servicePrincipalName"][0],
3073 "HOST/testname.testdom")
3076 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3077 m["dNSHostName"] = MessageElement("testname.testdoM",
3078 FLAG_MOD_REPLACE, "dNSHostName")
3081 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3082 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3083 self.assertTrue(len(res) == 1)
3084 self.assertEquals(res[0]["servicePrincipalName"][0],
3085 "HOST/testname.testdom")
3088 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3089 m["dNSHostName"] = MessageElement("testname2.testdom2",
3090 FLAG_MOD_REPLACE, "dNSHostName")
3093 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3094 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3095 self.assertTrue(len(res) == 1)
3096 self.assertEquals(res[0]["servicePrincipalName"][0],
3097 "HOST/testname2.testdom2")
3100 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3101 m["dNSHostName"] = MessageElement([],
3102 FLAG_MOD_DELETE, "dNSHostName")
3105 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3106 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3107 self.assertTrue(len(res) == 1)
3108 self.assertEquals(res[0]["servicePrincipalName"][0],
3109 "HOST/testname2.testdom2")
3112 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3113 m["dNSHostName"] = MessageElement("testname.testdom3",
3114 FLAG_MOD_REPLACE, "dNSHostName")
3117 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3118 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3119 self.assertTrue(len(res) == 1)
3120 self.assertEquals(res[0]["servicePrincipalName"][0],
3121 "HOST/testname2.testdom2")
3124 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3125 m["dNSHostName"] = MessageElement("testname2.testdom2",
3126 FLAG_MOD_REPLACE, "dNSHostName")
3130 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3131 m["dNSHostName"] = MessageElement("testname3.testdom3",
3132 FLAG_MOD_REPLACE, "dNSHostName")
3133 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
3135 "servicePrincipalName")
3138 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3139 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3140 self.assertTrue(len(res) == 1)
3141 self.assertEquals(res[0]["servicePrincipalName"][0],
3142 "HOST/testname3.testdom3")
3145 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3146 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
3148 "servicePrincipalName")
3149 m["dNSHostName"] = MessageElement("testname4.testdom4",
3150 FLAG_MOD_REPLACE, "dNSHostName")
3153 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3154 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3155 self.assertTrue(len(res) == 1)
3156 self.assertEquals(res[0]["servicePrincipalName"][0],
3157 "HOST/testname2.testdom2")
3160 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3161 m["servicePrincipalName"] = MessageElement([],
3163 "servicePrincipalName")
3167 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3168 m["dNSHostName"] = MessageElement("testname2.testdom2",
3169 FLAG_MOD_REPLACE, "dNSHostName")
3172 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3173 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3174 self.assertTrue(len(res) == 1)
3175 self.assertFalse("servicePrincipalName" in res[0])
3177 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3180 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3181 "objectclass": "computer",
3182 "sAMAccountName": "testname$"})
3184 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3185 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3186 self.assertTrue(len(res) == 1)
3187 self.assertFalse("servicePrincipalName" in res[0])
3189 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3192 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3193 "objectclass": "computer",
3194 "servicePrincipalName": "HOST/testname"})
3196 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3197 scope=SCOPE_BASE, attrs=["sAMAccountName"])
3198 self.assertTrue(len(res) == 1)
3199 self.assertTrue("sAMAccountName" in res[0])
3201 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3204 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3205 "objectclass": "computer",
3206 "sAMAccountName": "testname$",
3207 "servicePrincipalName": "HOST/testname"})
3209 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3210 scope=SCOPE_BASE, attrs=["sAMAccountName"])
3211 self.assertTrue(len(res) == 1)
3212 self.assertEquals(res[0]["sAMAccountName"][0], "testname$")
3214 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3215 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3216 self.assertTrue(len(res) == 1)
3217 self.assertEquals(res[0]["servicePrincipalName"][0],
3221 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3222 m["sAMAccountName"] = MessageElement("testnamE$",
3223 FLAG_MOD_REPLACE, "sAMAccountName")
3226 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3227 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3228 self.assertTrue(len(res) == 1)
3229 self.assertEquals(res[0]["servicePrincipalName"][0],
3233 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3234 m["sAMAccountName"] = MessageElement("testname",
3235 FLAG_MOD_REPLACE, "sAMAccountName")
3238 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3239 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3240 self.assertTrue(len(res) == 1)
3241 self.assertEquals(res[0]["servicePrincipalName"][0],
3245 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3246 m["sAMAccountName"] = MessageElement("test$name$",
3247 FLAG_MOD_REPLACE, "sAMAccountName")
3250 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3251 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3252 self.assertTrue(len(res) == 1)
3253 self.assertEquals(res[0]["servicePrincipalName"][0],
3257 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3258 m["sAMAccountName"] = MessageElement("testname2",
3259 FLAG_MOD_REPLACE, "sAMAccountName")
3262 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3263 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3264 self.assertTrue(len(res) == 1)
3265 self.assertEquals(res[0]["servicePrincipalName"][0],
3269 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3270 m["sAMAccountName"] = MessageElement("testname3",
3271 FLAG_MOD_REPLACE, "sAMAccountName")
3272 m["servicePrincipalName"] = MessageElement("HOST/testname2",
3274 "servicePrincipalName")
3277 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3278 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3279 self.assertTrue(len(res) == 1)
3280 self.assertEquals(res[0]["servicePrincipalName"][0],
3284 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3285 m["servicePrincipalName"] = MessageElement("HOST/testname2",
3287 "servicePrincipalName")
3288 m["sAMAccountName"] = MessageElement("testname4",
3289 FLAG_MOD_REPLACE, "sAMAccountName")
3292 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3293 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3294 self.assertTrue(len(res) == 1)
3295 self.assertEquals(res[0]["servicePrincipalName"][0],
3299 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3300 m["servicePrincipalName"] = MessageElement([],
3302 "servicePrincipalName")
3306 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3307 m["sAMAccountName"] = MessageElement("testname2",
3308 FLAG_MOD_REPLACE, "sAMAccountName")
3311 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3312 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3313 self.assertTrue(len(res) == 1)
3314 self.assertFalse("servicePrincipalName" in res[0])
3316 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3319 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3320 "objectclass": "computer",
3321 "dNSHostName": "testname.testdom",
3322 "sAMAccountName": "testname$",
3323 "servicePrincipalName": [ "HOST/testname.testdom", "HOST/testname" ]
3327 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3328 m["dNSHostName"] = MessageElement("testname2.testdom",
3329 FLAG_MOD_REPLACE, "dNSHostName")
3330 m["sAMAccountName"] = MessageElement("testname2$",
3331 FLAG_MOD_REPLACE, "sAMAccountName")
3334 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3335 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3336 self.assertTrue(len(res) == 1)
3337 self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
3338 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3339 self.assertTrue(res[0]["servicePrincipalName"][0] == "HOST/testname2" or
3340 res[0]["servicePrincipalName"][1] == "HOST/testname2")
3341 self.assertTrue(res[0]["servicePrincipalName"][0] == "HOST/testname2.testdom" or
3342 res[0]["servicePrincipalName"][1] == "HOST/testname2.testdom")
3344 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3347 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3348 "objectclass": "computer",
3349 "dNSHostName": "testname.testdom",
3350 "sAMAccountName": "testname$",
3351 "servicePrincipalName": [ "HOST/testname.testdom", "HOST/testname" ]
3355 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3356 m["sAMAccountName"] = MessageElement("testname2$",
3357 FLAG_MOD_REPLACE, "sAMAccountName")
3358 m["dNSHostName"] = MessageElement("testname2.testdom",
3359 FLAG_MOD_REPLACE, "dNSHostName")
3362 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3363 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3364 self.assertTrue(len(res) == 1)
3365 self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
3366 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3367 self.assertTrue(len(res[0]["servicePrincipalName"]) == 2)
3368 self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
3369 self.assertTrue("HOST/testname2.testdom" in res[0]["servicePrincipalName"])
3372 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3373 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom",
3374 FLAG_MOD_ADD, "servicePrincipalName")
3378 except LdbError as e77:
3380 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3383 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3384 m["servicePrincipalName"] = MessageElement("HOST/testname3",
3385 FLAG_MOD_ADD, "servicePrincipalName")
3388 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3389 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3390 self.assertTrue(len(res) == 1)
3391 self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
3392 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3393 self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
3394 self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
3395 self.assertTrue("HOST/testname3" in res[0]["servicePrincipalName"])
3396 self.assertTrue("HOST/testname2.testdom" in res[0]["servicePrincipalName"])
3399 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3400 m["dNSHostName"] = MessageElement("testname3.testdom",
3401 FLAG_MOD_REPLACE, "dNSHostName")
3402 m["servicePrincipalName"] = MessageElement("HOST/testname3.testdom",
3403 FLAG_MOD_ADD, "servicePrincipalName")
3406 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3407 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3408 self.assertTrue(len(res) == 1)
3409 self.assertEquals(res[0]["dNSHostName"][0], "testname3.testdom")
3410 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3411 self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
3412 self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
3413 self.assertTrue("HOST/testname3" in res[0]["servicePrincipalName"])
3414 self.assertTrue("HOST/testname3.testdom" in res[0]["servicePrincipalName"])
3416 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3418 def test_sam_description_attribute(self):
3419 """Test SAM description attribute"""
3420 print("Test SAM description attribute")
3423 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3424 "objectclass": "group",
3425 "description": "desc1"
3428 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3429 scope=SCOPE_BASE, attrs=["description"])
3430 self.assertTrue(len(res) == 1)
3431 self.assertTrue("description" in res[0])
3432 self.assertTrue(len(res[0]["description"]) == 1)
3433 self.assertEquals(res[0]["description"][0], "desc1")
3435 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3438 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3439 "objectclass": "group",
3440 "description": ["desc1", "desc2"]})
3442 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3443 scope=SCOPE_BASE, attrs=["description"])
3444 self.assertTrue(len(res) == 1)
3445 self.assertTrue("description" in res[0])
3446 self.assertTrue(len(res[0]["description"]) == 2)
3447 self.assertTrue(res[0]["description"][0] == "desc1" or
3448 res[0]["description"][1] == "desc1")
3449 self.assertTrue(res[0]["description"][0] == "desc2" or
3450 res[0]["description"][1] == "desc2")
3453 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3454 m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
3459 except LdbError as e78:
3461 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3464 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3465 m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_DELETE,
3469 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3472 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3473 "objectclass": "group" })
3476 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3477 m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
3481 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3482 scope=SCOPE_BASE, attrs=["description"])
3483 self.assertTrue(len(res) == 1)
3484 self.assertTrue("description" in res[0])
3485 self.assertTrue(len(res[0]["description"]) == 1)
3486 self.assertEquals(res[0]["description"][0], "desc1")
3488 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3491 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3492 "objectclass": "group",
3493 "description": ["desc1", "desc2"]})
3496 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3497 m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
3501 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3502 scope=SCOPE_BASE, attrs=["description"])
3503 self.assertTrue(len(res) == 1)
3504 self.assertTrue("description" in res[0])
3505 self.assertTrue(len(res[0]["description"]) == 1)
3506 self.assertEquals(res[0]["description"][0], "desc1")
3509 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3510 m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
3515 except LdbError as e79:
3517 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3520 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3521 m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_DELETE,
3526 except LdbError as e80:
3528 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
3531 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3532 m["description"] = MessageElement("desc1", FLAG_MOD_DELETE,
3535 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3536 scope=SCOPE_BASE, attrs=["description"])
3537 self.assertTrue(len(res) == 1)
3538 self.assertFalse("description" in res[0])
3541 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3542 m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
3547 except LdbError as e81:
3549 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3552 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3553 m["description"] = MessageElement(["desc3", "desc4"], FLAG_MOD_ADD,
3558 except LdbError as e82:
3560 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3563 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3564 m["description"] = MessageElement("desc1", FLAG_MOD_ADD,
3568 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3569 scope=SCOPE_BASE, attrs=["description"])
3570 self.assertTrue(len(res) == 1)
3571 self.assertTrue("description" in res[0])
3572 self.assertTrue(len(res[0]["description"]) == 1)
3573 self.assertEquals(res[0]["description"][0], "desc1")
3576 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3577 m.add(MessageElement("desc1", FLAG_MOD_DELETE, "description"))
3578 m.add(MessageElement("desc2", FLAG_MOD_ADD, "description"))
3581 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3582 scope=SCOPE_BASE, attrs=["description"])
3583 self.assertTrue(len(res) == 1)
3584 self.assertTrue("description" in res[0])
3585 self.assertTrue(len(res[0]["description"]) == 1)
3586 self.assertEquals(res[0]["description"][0], "desc2")
3588 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3591 def test_fSMORoleOwner_attribute(self):
3592 """Test fSMORoleOwner attribute"""
3593 print("Test fSMORoleOwner attribute")
3595 ds_service_name = self.ldb.get_dsServiceName()
3597 # The "fSMORoleOwner" attribute can only be set to "nTDSDSA" entries,
3598 # invalid DNs return ERR_UNWILLING_TO_PERFORM
3602 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3603 "objectclass": "group",
3604 "fSMORoleOwner": self.base_dn})
3606 except LdbError as e83:
3608 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3612 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3613 "objectclass": "group",
3614 "fSMORoleOwner": [] })
3616 except LdbError as e84:
3618 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
3620 # We are able to set it to a valid "nTDSDSA" entry if the server is
3621 # capable of handling the role
3624 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3625 "objectclass": "group",
3626 "fSMORoleOwner": ds_service_name })
3628 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3631 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3632 "objectclass": "group" })
3635 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3636 m.add(MessageElement(self.base_dn, FLAG_MOD_REPLACE, "fSMORoleOwner"))
3640 except LdbError as e85:
3642 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3645 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3646 m.add(MessageElement([], FLAG_MOD_REPLACE, "fSMORoleOwner"))
3650 except LdbError as e86:
3652 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3654 # We are able to set it to a valid "nTDSDSA" entry if the server is
3655 # capable of handling the role
3658 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3659 m.add(MessageElement(ds_service_name, FLAG_MOD_REPLACE, "fSMORoleOwner"))
3662 # A clean-out works on plain entries, not master (schema, PDC...) DNs
3665 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3666 m.add(MessageElement([], FLAG_MOD_DELETE, "fSMORoleOwner"))
3669 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3671 def test_protected_sid_objects(self):
3672 """Test deletion of objects with RID < 1000"""
3673 # a list of some well-known sids
3674 # objects in Builtin are aready covered by objectclass
3676 ["CN=Domain Admins","CN=Users,"],
3677 ["CN=Schema Admins","CN=Users,"],
3678 ["CN=Enterprise Admins","CN=Users,"],
3679 ["CN=Administrator","CN=Users,"],
3680 ["CN=Domain Controllers","CN=Users,"],
3685 for pr_object in protected_list:
3687 self.ldb.delete(pr_object[0] + "," + pr_object[1] + self.base_dn)
3688 except LdbError as e7:
3690 self.assertEquals(num, ERR_OTHER)
3692 self.fail("Deleted " + pr_object[0])
3695 self.ldb.rename(pr_object[0] + "," + pr_object[1] + self.base_dn,
3696 pr_object[0] + "2," + pr_object[1] + self.base_dn)
3697 except LdbError as e8:
3699 self.fail("Could not rename " + pr_object[0])
3701 self.ldb.rename(pr_object[0] + "2," + pr_object[1] + self.base_dn,
3702 pr_object[0] + "," + pr_object[1] + self.base_dn)
3704 def test_new_user_default_attributes(self):
3705 """Test default attributes for new user objects"""
3706 print("Test default attributes for new User objects\n")
3708 user_name = "ldaptestuser"
3709 user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
3712 "objectclass": "user",
3713 "sAMAccountName": user_name})
3715 res = ldb.search(user_dn, scope=SCOPE_BASE)
3716 self.assertTrue(len(res) == 1)
3719 expected_attrs = {"primaryGroupID": MessageElement(["513"]),
3720 "logonCount": MessageElement(["0"]),
3721 "cn": MessageElement([user_name]),
3722 "countryCode": MessageElement(["0"]),
3723 "objectClass": MessageElement(["top","person","organizationalPerson","user"]),
3724 "instanceType": MessageElement(["4"]),
3725 "distinguishedName": MessageElement([user_dn]),
3726 "sAMAccountType": MessageElement(["805306368"]),
3727 "objectSid": "**SKIP**",
3728 "whenCreated": "**SKIP**",
3729 "uSNCreated": "**SKIP**",
3730 "badPasswordTime": MessageElement(["0"]),
3731 "dn": Dn(ldb, user_dn),
3732 "pwdLastSet": MessageElement(["0"]),
3733 "sAMAccountName": MessageElement([user_name]),
3734 "objectCategory": MessageElement(["CN=Person,%s" % ldb.get_schema_basedn().get_linearized()]),
3735 "objectGUID": "**SKIP**",
3736 "whenChanged": "**SKIP**",
3737 "badPwdCount": MessageElement(["0"]),
3738 "accountExpires": MessageElement(["9223372036854775807"]),
3739 "name": MessageElement([user_name]),
3740 "codePage": MessageElement(["0"]),
3741 "userAccountControl": MessageElement(["546"]),
3742 "lastLogon": MessageElement(["0"]),
3743 "uSNChanged": "**SKIP**",
3744 "lastLogoff": MessageElement(["0"])}
3745 # assert we have expected attribute names
3746 actual_names = set(user_obj.keys())
3747 # Samba does not use 'dSCorePropagationData', so skip it
3748 actual_names -= set(['dSCorePropagationData'])
3749 self.assertEqual(set(expected_attrs.keys()), actual_names, "Actual object does not have expected attributes")
3750 # check attribute values
3751 for name in expected_attrs.keys():
3752 actual_val = user_obj.get(name)
3753 self.assertFalse(actual_val is None, "No value for attribute '%s'" % name)
3754 expected_val = expected_attrs[name]
3755 if expected_val == "**SKIP**":
3756 # "**ANY**" values means "any"
3758 self.assertEqual(expected_val, actual_val,
3759 "Unexpected value[%r] for '%s' expected[%r]" %
3760 (actual_val, name, expected_val))
3762 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
3765 if not "://" in host:
3766 if os.path.isfile(host):
3767 host = "tdb://%s" % host
3769 host = "ldap://%s" % host
3771 ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp)
3773 TestProgram(module=__name__, opts=subunitopts)