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 samba.compat import get_string
20 from samba.compat import text_type
21 from ldb import SCOPE_BASE, LdbError
22 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
23 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
24 from ldb import ERR_OTHER, ERR_NO_SUCH_ATTRIBUTE
25 from ldb import ERR_OBJECT_CLASS_VIOLATION
26 from ldb import ERR_CONSTRAINT_VIOLATION
27 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
28 from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS
29 from ldb import ERR_INVALID_CREDENTIALS
30 from ldb import ERR_STRONG_AUTH_REQUIRED
31 from ldb import Message, MessageElement, Dn
32 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
33 from samba.samdb import SamDB
34 from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_ACCOUNTDISABLE,
35 UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
36 UF_PARTIAL_SECRETS_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT,
37 UF_INTERDOMAIN_TRUST_ACCOUNT, UF_SMARTCARD_REQUIRED,
38 UF_PASSWD_NOTREQD, UF_LOCKOUT, UF_PASSWORD_EXPIRED, ATYPE_NORMAL_ACCOUNT,
39 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
40 GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP,
41 GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP, GTYPE_DISTRIBUTION_GLOBAL_GROUP,
42 GTYPE_DISTRIBUTION_UNIVERSAL_GROUP,
43 ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_UNIVERSAL_GROUP,
44 ATYPE_SECURITY_LOCAL_GROUP, ATYPE_DISTRIBUTION_GLOBAL_GROUP,
45 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP, ATYPE_DISTRIBUTION_LOCAL_GROUP,
46 ATYPE_WORKSTATION_TRUST)
47 from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_ADMINS,
48 DOMAIN_RID_DOMAIN_MEMBERS, DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS)
50 from samba.ndr import ndr_unpack
51 from samba.dcerpc import drsblobs
52 from samba.dcerpc import drsuapi
53 from samba.dcerpc import security
54 from samba.tests import delete_force
55 from samba import gensec
56 from samba import werror
58 parser = optparse.OptionParser("sam.py [options] <host>")
59 sambaopts = options.SambaOptions(parser)
60 parser.add_option_group(sambaopts)
61 parser.add_option_group(options.VersionOptions(parser))
62 # use command line creds if available
63 credopts = options.CredentialsOptions(parser)
64 parser.add_option_group(credopts)
65 subunitopts = SubunitOptions(parser)
66 parser.add_option_group(subunitopts)
67 opts, args = parser.parse_args()
75 lp = sambaopts.get_loadparm()
76 creds = credopts.get_credentials(lp)
77 creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
80 class SamTests(samba.tests.TestCase):
83 super(SamTests, self).setUp()
85 self.base_dn = ldb.domain_dn()
87 print("baseDN: %s\n" % self.base_dn)
89 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
90 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
91 delete_force(self.ldb, "cn=ldaptest\,specialuser,cn=users," + self.base_dn)
92 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
93 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
94 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
96 def test_users_groups(self):
97 """This tests the SAM users and groups behaviour"""
98 print("Testing users and groups behaviour\n")
101 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
102 "objectclass": "group"})
105 "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
106 "objectclass": "group"})
108 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
109 scope=SCOPE_BASE, attrs=["objectSID"])
110 self.assertTrue(len(res1) == 1)
111 obj_sid = get_string(ldb.schema_format_value("objectSID",
112 res1[0]["objectSID"][0]))
113 group_rid_1 = security.dom_sid(obj_sid).split()[1]
115 res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
116 scope=SCOPE_BASE, attrs=["objectSID"])
117 self.assertTrue(len(res1) == 1)
118 obj_sid = get_string(ldb.schema_format_value("objectSID",
119 res1[0]["objectSID"][0]))
120 group_rid_2 = security.dom_sid(obj_sid).split()[1]
122 # Try to create a user with an invalid account name
125 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
126 "objectclass": "user",
127 "sAMAccountName": "administrator"})
129 except LdbError as e9:
131 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
132 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
134 # Try to create a user with an invalid account name
137 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
138 "objectclass": "user",
139 "sAMAccountName": []})
141 except LdbError as e10:
143 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
144 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
146 # Try to create a user with an invalid primary group
149 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
150 "objectclass": "user",
151 "primaryGroupID": "0"})
153 except LdbError as e11:
155 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
156 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
158 # Try to Create a user with a valid primary group
161 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
162 "objectclass": "user",
163 "primaryGroupID": str(group_rid_1)})
165 except LdbError as e12:
167 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
168 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
170 # Test to see how we should behave when the user account doesn't
173 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
174 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
179 except LdbError as e13:
181 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
183 # Test to see how we should behave when the account isn't a user
185 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
186 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
191 except LdbError as e14:
193 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
195 # Test default primary groups on add operations
198 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
199 "objectclass": "user"})
201 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
202 scope=SCOPE_BASE, attrs=["primaryGroupID"])
203 self.assertTrue(len(res1) == 1)
204 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS)
206 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
209 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
210 "objectclass": "user",
211 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
213 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
214 scope=SCOPE_BASE, attrs=["primaryGroupID"])
215 self.assertTrue(len(res1) == 1)
216 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS)
218 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
220 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
221 # since such accounts aren't directly creatable (ACCESS_DENIED)
224 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
225 "objectclass": "computer",
226 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT |
229 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
230 scope=SCOPE_BASE, attrs=["primaryGroupID"])
231 self.assertTrue(len(res1) == 1)
232 self.assertEquals(int(res1[0]["primaryGroupID"][0]),
233 DOMAIN_RID_DOMAIN_MEMBERS)
235 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
238 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
239 "objectclass": "computer",
240 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT |
243 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
244 scope=SCOPE_BASE, attrs=["primaryGroupID"])
245 self.assertTrue(len(res1) == 1)
246 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DCS)
248 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
250 # Read-only DC accounts are only creatable by
251 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
252 # we have a fallback in the assertion)
254 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
255 "objectclass": "computer",
256 "userAccountControl": str(UF_PARTIAL_SECRETS_ACCOUNT |
257 UF_WORKSTATION_TRUST_ACCOUNT |
260 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
261 scope=SCOPE_BASE, attrs=["primaryGroupID"])
262 self.assertTrue(len(res1) == 1)
263 self.assertTrue(int(res1[0]["primaryGroupID"][0]) == DOMAIN_RID_READONLY_DCS or
264 int(res1[0]["primaryGroupID"][0]) == DOMAIN_RID_DOMAIN_MEMBERS)
266 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
268 # Test default primary groups on modify operations
271 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
272 "objectclass": "user"})
275 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
276 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT |
279 "userAccountControl")
282 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
283 scope=SCOPE_BASE, attrs=["primaryGroupID"])
284 self.assertTrue(len(res1) == 1)
285 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS)
287 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
288 # since such accounts aren't directly creatable (ACCESS_DENIED)
290 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
293 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
294 "objectclass": "computer"})
296 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
297 scope=SCOPE_BASE, attrs=["primaryGroupID"])
298 self.assertTrue(len(res1) == 1)
299 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS)
302 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
303 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT |
306 "userAccountControl")
309 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
310 scope=SCOPE_BASE, attrs=["primaryGroupID"])
311 self.assertTrue(len(res1) == 1)
312 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS)
315 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
316 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT |
319 "userAccountControl")
322 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
323 scope=SCOPE_BASE, attrs=["primaryGroupID"])
324 self.assertTrue(len(res1) == 1)
325 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DCS)
327 # Read-only DC accounts are only creatable by
328 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
329 # we have a fallback in the assertion)
331 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
332 m["userAccountControl"] = MessageElement(str(UF_PARTIAL_SECRETS_ACCOUNT |
333 UF_WORKSTATION_TRUST_ACCOUNT |
336 "userAccountControl")
339 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
340 scope=SCOPE_BASE, attrs=["primaryGroupID"])
341 self.assertTrue(len(res1) == 1)
342 self.assertTrue(int(res1[0]["primaryGroupID"][0]) == DOMAIN_RID_READONLY_DCS or
343 int(res1[0]["primaryGroupID"][0]) == DOMAIN_RID_DOMAIN_MEMBERS)
345 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
347 # Recreate account for further tests
350 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
351 "objectclass": "user"})
353 # Try to set an invalid account name
355 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
356 m["sAMAccountName"] = MessageElement("administrator", FLAG_MOD_REPLACE,
361 except LdbError as e15:
363 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
365 # But to reset the actual "sAMAccountName" should still be possible
366 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
367 scope=SCOPE_BASE, attrs=["sAMAccountName"])
368 self.assertTrue(len(res1) == 1)
370 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
371 m["sAMAccountName"] = MessageElement(res1[0]["sAMAccountName"][0], FLAG_MOD_REPLACE,
375 # And another (free) name should be possible as well
377 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
378 m["sAMAccountName"] = MessageElement("xxx_ldaptestuser_xxx", FLAG_MOD_REPLACE,
382 # We should be able to reset our actual primary group
384 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
385 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS), FLAG_MOD_REPLACE,
389 # Try to add invalid primary group
391 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
392 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
397 except LdbError as e16:
399 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
401 # Try to make group 1 primary - should be denied since it is not yet
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")
410 except LdbError as e17:
412 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
414 # Make group 1 secondary
416 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
417 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
418 FLAG_MOD_REPLACE, "member")
421 # Make group 1 primary
423 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
424 m["primaryGroupID"] = MessageElement(str(group_rid_1),
425 FLAG_MOD_REPLACE, "primaryGroupID")
428 # Try to delete group 1 - should be denied
430 ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
432 except LdbError as e18:
434 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
436 # Try to add group 1 also as secondary - should be denied
438 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
439 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
440 FLAG_MOD_ADD, "member")
444 except LdbError as e19:
446 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
448 # Try to add invalid member to group 1 - should be denied
450 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
451 m["member"] = MessageElement(
452 "cn=ldaptestuser3,cn=users," + self.base_dn,
453 FLAG_MOD_ADD, "member")
457 except LdbError as e20:
459 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
461 # Make group 2 secondary
463 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
464 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
465 FLAG_MOD_ADD, "member")
470 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
471 m["primaryGroupID"] = MessageElement(str(group_rid_2),
472 FLAG_MOD_REPLACE, "primaryGroupID")
475 # Swap the groups (does not really make sense but does the same)
477 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
478 m["primaryGroupID"] = MessageElement(str(group_rid_1),
479 FLAG_MOD_REPLACE, "primaryGroupID")
480 m["primaryGroupID"] = MessageElement(str(group_rid_2),
481 FLAG_MOD_REPLACE, "primaryGroupID")
484 # Old primary group should contain a "member" attribute for the user,
485 # the new shouldn't contain anymore one
486 res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
487 scope=SCOPE_BASE, attrs=["member"])
488 self.assertTrue(len(res1) == 1)
489 self.assertTrue(len(res1[0]["member"]) == 1)
490 self.assertEquals(str(res1[0]["member"][0]).lower(),
491 ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
493 res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
494 scope=SCOPE_BASE, attrs=["member"])
495 self.assertTrue(len(res1) == 1)
496 self.assertFalse("member" in res1[0])
498 # Primary group member
500 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
501 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
502 FLAG_MOD_DELETE, "member")
506 except LdbError as e21:
508 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
510 # Delete invalid group member
512 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
513 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
514 FLAG_MOD_DELETE, "member")
518 except LdbError as e22:
520 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
522 # Also this should be denied
525 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
526 "objectclass": "user",
527 "primaryGroupID": "0"})
529 except LdbError as e23:
531 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
533 # Recreate user accounts
535 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
538 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
539 "objectclass": "user"})
542 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
543 "objectclass": "user"})
546 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
547 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
548 FLAG_MOD_ADD, "member")
553 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
554 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
555 FLAG_MOD_ADD, "member")
559 except LdbError as e24:
561 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
563 # Already added, but as <SID=...>
564 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
565 scope=SCOPE_BASE, attrs=["objectSid"])
566 self.assertTrue(len(res1) == 1)
567 sid_bin = res1[0]["objectSid"][0]
568 sid_str = ("<SID=" + get_string(ldb.schema_format_value("objectSid", sid_bin)) + ">").upper()
571 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
572 m["member"] = MessageElement(sid_str, FLAG_MOD_ADD, "member")
576 except LdbError as e25:
578 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
582 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
583 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
584 FLAG_MOD_REPLACE, "member")
588 except LdbError as e26:
590 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
594 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
595 m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
596 "cn=ldaptestuser1,cn=users," + self.base_dn],
597 FLAG_MOD_REPLACE, "member")
601 except LdbError as e27:
603 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
607 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
608 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
609 FLAG_MOD_REPLACE, "member")
610 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
611 FLAG_MOD_ADD, "member")
615 except LdbError as e28:
617 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
620 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
621 m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
622 "cn=ldaptestuser2,cn=users," + self.base_dn],
623 FLAG_MOD_REPLACE, "member")
626 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
627 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
628 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
629 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
631 # Make also a small test for accounts with special DNs ("," in this case)
633 "dn": "cn=ldaptest\,specialuser,cn=users," + self.base_dn,
634 "objectclass": "user"})
635 delete_force(self.ldb, "cn=ldaptest\,specialuser,cn=users," + self.base_dn)
637 def test_sam_attributes(self):
638 """Test the behaviour of special attributes of SAM objects"""
639 print("Testing the behaviour of special attributes of SAM objects\n")
642 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
643 "objectclass": "user"})
645 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
646 "objectclass": "group"})
649 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
650 m["groupType"] = MessageElement(str(GTYPE_SECURITY_GLOBAL_GROUP), FLAG_MOD_ADD,
655 except LdbError as e29:
657 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
659 # Delete protection tests
661 for attr in ["nTSecurityDescriptor", "objectSid", "sAMAccountType",
662 "sAMAccountName", "groupType"]:
665 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
666 m[attr] = MessageElement([], FLAG_MOD_REPLACE, attr)
670 except LdbError as e:
672 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
675 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
676 m[attr] = MessageElement([], FLAG_MOD_DELETE, attr)
680 except LdbError as e1:
682 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
685 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
686 m["primaryGroupID"] = MessageElement("513", FLAG_MOD_ADD,
691 except LdbError as e30:
693 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
696 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
697 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT |
700 "userAccountControl")
704 except LdbError as e31:
706 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
709 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
710 m["objectSid"] = MessageElement("xxxxxxxxxxxxxxxx", FLAG_MOD_ADD,
715 except LdbError as e32:
717 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
720 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
721 m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
726 except LdbError as e33:
728 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
731 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
732 m["sAMAccountName"] = MessageElement("test", FLAG_MOD_ADD,
737 except LdbError as e34:
739 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
741 # Delete protection tests
743 for attr in ["nTSecurityDescriptor", "objectSid", "sAMAccountType",
744 "sAMAccountName", "primaryGroupID", "userAccountControl",
745 "accountExpires", "badPasswordTime", "badPwdCount",
746 "codePage", "countryCode", "lastLogoff", "lastLogon",
747 "logonCount", "pwdLastSet"]:
750 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
751 m[attr] = MessageElement([], FLAG_MOD_REPLACE, attr)
755 except LdbError as e2:
757 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
760 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
761 m[attr] = MessageElement([], FLAG_MOD_DELETE, attr)
765 except LdbError as e3:
767 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
769 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
770 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
772 def test_primary_group_token_constructed(self):
773 """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
774 print("Testing primary group token behaviour and other constructed attributes\n")
778 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
779 "objectclass": "group",
780 "primaryGroupToken": "100"})
782 except LdbError as e35:
784 self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
785 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
788 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
789 "objectclass": "user"})
792 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
793 "objectclass": "group"})
795 # Testing for one invalid, and one valid operational attribute, but also the things they are built from
796 res1 = ldb.search(self.base_dn,
797 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
798 self.assertTrue(len(res1) == 1)
799 self.assertFalse("primaryGroupToken" in res1[0])
800 self.assertTrue("canonicalName" in res1[0])
801 self.assertTrue("objectClass" in res1[0])
802 self.assertTrue("objectSid" in res1[0])
804 res1 = ldb.search(self.base_dn,
805 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
806 self.assertTrue(len(res1) == 1)
807 self.assertFalse("primaryGroupToken" in res1[0])
808 self.assertFalse("objectSid" in res1[0])
809 self.assertFalse("objectClass" in res1[0])
810 self.assertTrue("canonicalName" in res1[0])
812 res1 = ldb.search("cn=users," + self.base_dn,
813 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
814 self.assertTrue(len(res1) == 1)
815 self.assertFalse("primaryGroupToken" in res1[0])
817 res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
818 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
819 self.assertTrue(len(res1) == 1)
820 self.assertFalse("primaryGroupToken" in res1[0])
822 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
824 self.assertTrue(len(res1) == 1)
825 self.assertFalse("primaryGroupToken" in res1[0])
827 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
828 scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
829 self.assertTrue(len(res1) == 1)
830 primary_group_token = int(res1[0]["primaryGroupToken"][0])
832 obj_sid = get_string(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0]))
833 rid = security.dom_sid(obj_sid).split()[1]
834 self.assertEquals(primary_group_token, rid)
837 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
838 m["primaryGroupToken"] = "100"
842 except LdbError as e36:
844 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
846 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
847 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
849 def test_tokenGroups(self):
850 """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
851 print("Testing tokenGroups behaviour\n")
853 # The domain object shouldn't contain any "tokenGroups" entry
854 res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
855 self.assertTrue(len(res) == 1)
856 self.assertFalse("tokenGroups" in res[0])
858 # The domain administrator should contain "tokenGroups" entries
859 # (the exact number depends on the domain/forest function level and the
860 # DC software versions)
861 res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
862 scope=SCOPE_BASE, attrs=["tokenGroups"])
863 self.assertTrue(len(res) == 1)
864 self.assertTrue("tokenGroups" in res[0])
867 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
868 "objectclass": "user"})
870 # This testuser should contain at least two "tokenGroups" entries
871 # (exactly two on an unmodified "Domain Users" and "Users" group)
872 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
873 scope=SCOPE_BASE, attrs=["tokenGroups"])
874 self.assertTrue(len(res) == 1)
875 self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
877 # one entry which we need to find should point to domains "Domain Users"
878 # group and another entry should point to the builtin "Users"group
879 domain_users_group_found = False
880 users_group_found = False
881 for sid in res[0]["tokenGroups"]:
882 obj_sid = get_string(ldb.schema_format_value("objectSID", sid))
883 rid = security.dom_sid(obj_sid).split()[1]
885 domain_users_group_found = True
887 users_group_found = True
889 self.assertTrue(domain_users_group_found)
890 self.assertTrue(users_group_found)
892 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
894 def test_groupType(self):
895 """Test the groupType behaviour"""
896 print("Testing groupType behaviour\n")
898 # You can never create or change to a
899 # "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP"
906 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
907 "objectclass": "group",
910 except LdbError as e37:
912 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
913 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
917 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
918 "objectclass": "group",
919 "groupType": str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP)})
921 except LdbError as e38:
923 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
924 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
927 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
928 "objectclass": "group",
929 "groupType": str(GTYPE_SECURITY_GLOBAL_GROUP)})
931 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
932 scope=SCOPE_BASE, attrs=["sAMAccountType"])
933 self.assertTrue(len(res1) == 1)
934 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
935 ATYPE_SECURITY_GLOBAL_GROUP)
936 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
939 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
940 "objectclass": "group",
941 "groupType": str(GTYPE_SECURITY_UNIVERSAL_GROUP)})
943 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
944 scope=SCOPE_BASE, attrs=["sAMAccountType"])
945 self.assertTrue(len(res1) == 1)
946 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
947 ATYPE_SECURITY_UNIVERSAL_GROUP)
948 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
951 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
952 "objectclass": "group",
953 "groupType": str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP)})
955 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
956 scope=SCOPE_BASE, attrs=["sAMAccountType"])
957 self.assertTrue(len(res1) == 1)
958 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
959 ATYPE_SECURITY_LOCAL_GROUP)
960 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
963 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
964 "objectclass": "group",
965 "groupType": str(GTYPE_DISTRIBUTION_GLOBAL_GROUP)})
967 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
968 scope=SCOPE_BASE, attrs=["sAMAccountType"])
969 self.assertTrue(len(res1) == 1)
970 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
971 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
972 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
975 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
976 "objectclass": "group",
977 "groupType": str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP)})
979 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
980 scope=SCOPE_BASE, attrs=["sAMAccountType"])
981 self.assertTrue(len(res1) == 1)
982 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
983 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
984 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
987 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
988 "objectclass": "group",
989 "groupType": str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)})
991 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
992 scope=SCOPE_BASE, attrs=["sAMAccountType"])
993 self.assertTrue(len(res1) == 1)
994 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
995 ATYPE_DISTRIBUTION_LOCAL_GROUP)
996 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1001 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1002 "objectclass": "group"})
1004 # We can change in this direction: global <-> universal <-> local
1005 # On each step also the group type itself (security/distribution) is
1008 # After creation we should have a "security global group"
1009 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1010 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1011 self.assertTrue(len(res1) == 1)
1012 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1013 ATYPE_SECURITY_GLOBAL_GROUP)
1018 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1019 m["groupType"] = MessageElement("0",
1020 FLAG_MOD_REPLACE, "groupType")
1023 except LdbError as e39:
1025 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1029 # Default is "global group"
1032 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1033 m["groupType"] = MessageElement(
1034 str(GTYPE_SECURITY_GLOBAL_GROUP),
1035 FLAG_MOD_REPLACE, "groupType")
1038 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1039 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1040 self.assertTrue(len(res1) == 1)
1041 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1042 ATYPE_SECURITY_GLOBAL_GROUP)
1044 # Change to "local" (shouldn't work)
1048 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1049 m["groupType"] = MessageElement(
1050 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1051 FLAG_MOD_REPLACE, "groupType")
1054 except LdbError as e40:
1056 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1058 # Change to "universal"
1061 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1062 m["groupType"] = MessageElement(
1063 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1064 FLAG_MOD_REPLACE, "groupType")
1067 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1068 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1069 self.assertTrue(len(res1) == 1)
1070 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1071 ATYPE_SECURITY_UNIVERSAL_GROUP)
1073 # Change back to "global"
1076 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1077 m["groupType"] = MessageElement(
1078 str(GTYPE_SECURITY_GLOBAL_GROUP),
1079 FLAG_MOD_REPLACE, "groupType")
1082 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1083 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1084 self.assertTrue(len(res1) == 1)
1085 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1086 ATYPE_SECURITY_GLOBAL_GROUP)
1088 # Change back to "universal"
1091 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1092 m["groupType"] = MessageElement(
1093 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1094 FLAG_MOD_REPLACE, "groupType")
1097 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1098 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1099 self.assertTrue(len(res1) == 1)
1100 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1101 ATYPE_SECURITY_UNIVERSAL_GROUP)
1106 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1107 m["groupType"] = MessageElement(
1108 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1109 FLAG_MOD_REPLACE, "groupType")
1112 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1113 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1114 self.assertTrue(len(res1) == 1)
1115 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1116 ATYPE_SECURITY_LOCAL_GROUP)
1118 # Change to "global" (shouldn't work)
1122 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1123 m["groupType"] = MessageElement(
1124 str(GTYPE_SECURITY_GLOBAL_GROUP),
1125 FLAG_MOD_REPLACE, "groupType")
1128 except LdbError as e41:
1130 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1132 # Change to "builtin local" (shouldn't work)
1136 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1137 m["groupType"] = MessageElement(
1138 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1139 FLAG_MOD_REPLACE, "groupType")
1142 except LdbError as e42:
1144 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1147 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1149 # Change back to "universal"
1152 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1153 m["groupType"] = MessageElement(
1154 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1155 FLAG_MOD_REPLACE, "groupType")
1158 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1159 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1160 self.assertTrue(len(res1) == 1)
1161 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1162 ATYPE_SECURITY_UNIVERSAL_GROUP)
1164 # Change to "builtin local" (shouldn't work)
1168 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1169 m["groupType"] = MessageElement(
1170 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1171 FLAG_MOD_REPLACE, "groupType")
1174 except LdbError as e43:
1176 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1178 # Change back to "global"
1181 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1182 m["groupType"] = MessageElement(
1183 str(GTYPE_SECURITY_GLOBAL_GROUP),
1184 FLAG_MOD_REPLACE, "groupType")
1187 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1188 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1189 self.assertTrue(len(res1) == 1)
1190 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1191 ATYPE_SECURITY_GLOBAL_GROUP)
1193 # Change to "builtin local" (shouldn't work)
1197 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1198 m["groupType"] = MessageElement(
1199 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1200 FLAG_MOD_REPLACE, "groupType")
1203 except LdbError as e44:
1205 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1207 # Distribution groups
1209 # Default is "global group"
1212 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1213 m["groupType"] = MessageElement(
1214 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1215 FLAG_MOD_REPLACE, "groupType")
1218 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1219 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1220 self.assertTrue(len(res1) == 1)
1221 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1222 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1224 # Change to local (shouldn't work)
1228 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1229 m["groupType"] = MessageElement(
1230 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1231 FLAG_MOD_REPLACE, "groupType")
1234 except LdbError as e45:
1236 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1238 # Change to "universal"
1241 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1242 m["groupType"] = MessageElement(
1243 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1244 FLAG_MOD_REPLACE, "groupType")
1247 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1248 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1249 self.assertTrue(len(res1) == 1)
1250 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1251 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1253 # Change back to "global"
1256 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1257 m["groupType"] = MessageElement(
1258 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1259 FLAG_MOD_REPLACE, "groupType")
1262 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1263 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1264 self.assertTrue(len(res1) == 1)
1265 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1266 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1268 # Change back to "universal"
1271 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1272 m["groupType"] = MessageElement(
1273 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1274 FLAG_MOD_REPLACE, "groupType")
1277 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1278 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1279 self.assertTrue(len(res1) == 1)
1280 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1281 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1286 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1287 m["groupType"] = MessageElement(
1288 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1289 FLAG_MOD_REPLACE, "groupType")
1292 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1293 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1294 self.assertTrue(len(res1) == 1)
1295 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1296 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1298 # Change to "global" (shouldn't work)
1302 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1303 m["groupType"] = MessageElement(
1304 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1305 FLAG_MOD_REPLACE, "groupType")
1308 except LdbError as e46:
1310 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1312 # Change back to "universal"
1314 # Try to add invalid member to group 1 - should be denied
1316 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1317 m["member"] = MessageElement(
1318 "cn=ldaptestuser3,cn=users," + self.base_dn,
1319 FLAG_MOD_ADD, "member")
1323 except LdbError as e47:
1325 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1327 # Make group 2 secondary
1329 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1330 m["groupType"] = MessageElement(
1331 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1332 FLAG_MOD_REPLACE, "groupType")
1335 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1336 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1337 self.assertTrue(len(res1) == 1)
1338 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1339 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1341 # Change back to "global"
1344 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1345 m["groupType"] = MessageElement(
1346 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1347 FLAG_MOD_REPLACE, "groupType")
1350 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1351 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1352 self.assertTrue(len(res1) == 1)
1353 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1354 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1356 # Both group types: this performs only random checks - all possibilities
1357 # would require too much code.
1359 # Default is "global group"
1362 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1363 m["groupType"] = MessageElement(
1364 str(GTYPE_SECURITY_GLOBAL_GROUP),
1365 FLAG_MOD_REPLACE, "groupType")
1368 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1369 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1370 self.assertTrue(len(res1) == 1)
1371 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1372 ATYPE_SECURITY_GLOBAL_GROUP)
1374 # Change to "local" (shouldn't work)
1378 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1379 m["groupType"] = MessageElement(
1380 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1381 FLAG_MOD_REPLACE, "groupType")
1384 except LdbError as e48:
1386 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1388 # Change to "universal"
1391 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1392 m["groupType"] = MessageElement(
1393 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1394 FLAG_MOD_REPLACE, "groupType")
1397 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1398 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1399 self.assertTrue(len(res1) == 1)
1400 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1401 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1403 # Change back to "global"
1406 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1407 m["groupType"] = MessageElement(
1408 str(GTYPE_SECURITY_GLOBAL_GROUP),
1409 FLAG_MOD_REPLACE, "groupType")
1412 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1413 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1414 self.assertTrue(len(res1) == 1)
1415 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1416 ATYPE_SECURITY_GLOBAL_GROUP)
1418 # Change back to "universal"
1421 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1422 m["groupType"] = MessageElement(
1423 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1424 FLAG_MOD_REPLACE, "groupType")
1427 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1428 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1429 self.assertTrue(len(res1) == 1)
1430 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1431 ATYPE_SECURITY_UNIVERSAL_GROUP)
1436 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1437 m["groupType"] = MessageElement(
1438 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1439 FLAG_MOD_REPLACE, "groupType")
1442 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1443 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1444 self.assertTrue(len(res1) == 1)
1445 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1446 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1448 # Change to "global" (shouldn't work)
1452 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1453 m["groupType"] = MessageElement(
1454 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1455 FLAG_MOD_REPLACE, "groupType")
1458 except LdbError as e49:
1460 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1462 # Change back to "universal"
1465 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1466 m["groupType"] = MessageElement(
1467 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1468 FLAG_MOD_REPLACE, "groupType")
1471 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1472 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1473 self.assertTrue(len(res1) == 1)
1474 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1475 ATYPE_SECURITY_UNIVERSAL_GROUP)
1477 # Change back to "global"
1480 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1481 m["groupType"] = MessageElement(
1482 str(GTYPE_SECURITY_GLOBAL_GROUP),
1483 FLAG_MOD_REPLACE, "groupType")
1486 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1487 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1488 self.assertTrue(len(res1) == 1)
1489 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1490 ATYPE_SECURITY_GLOBAL_GROUP)
1492 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1494 def test_pwdLastSet(self):
1495 """Test the pwdLastSet behaviour"""
1496 print("Testing pwdLastSet behaviour\n")
1499 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1500 "objectclass": "user",
1503 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1505 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1506 self.assertTrue(len(res1) == 1)
1507 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1508 ATYPE_NORMAL_ACCOUNT)
1509 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1510 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1511 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1512 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1515 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1516 "objectclass": "user",
1517 "pwdLastSet": "-1"})
1519 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1521 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1522 self.assertTrue(len(res1) == 1)
1523 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1524 ATYPE_NORMAL_ACCOUNT)
1525 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1526 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1527 self.assertNotEqual(int(res1[0]["pwdLastSet"][0]), 0)
1528 lastset = int(res1[0]["pwdLastSet"][0])
1529 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1533 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1534 "objectclass": "user",
1535 "pwdLastSet": str(1)})
1537 except LdbError as e50:
1538 (num, msg) = e50.args
1539 self.assertEquals(num, ERR_OTHER)
1540 self.assertTrue('00000057' in msg)
1544 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1545 "objectclass": "user",
1546 "pwdLastSet": str(lastset)})
1548 except LdbError as e51:
1549 (num, msg) = e51.args
1550 self.assertEquals(num, ERR_OTHER)
1551 self.assertTrue('00000057' in msg)
1554 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1555 "objectclass": "user"})
1557 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1559 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1560 self.assertTrue(len(res1) == 1)
1561 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1562 ATYPE_NORMAL_ACCOUNT)
1563 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1564 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1565 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1568 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1569 m["pls1"] = MessageElement(str(0),
1575 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1576 m["pls1"] = MessageElement(str(0),
1579 m["pls2"] = MessageElement(str(0),
1585 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1586 m["pls1"] = MessageElement(str(-1),
1590 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1592 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1593 self.assertTrue(len(res1) == 1)
1594 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1595 ATYPE_NORMAL_ACCOUNT)
1596 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1597 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1598 self.assertGreater(int(res1[0]["pwdLastSet"][0]), lastset)
1599 lastset = int(res1[0]["pwdLastSet"][0])
1603 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1604 m["pls1"] = MessageElement(str(0),
1607 m["pls2"] = MessageElement(str(0),
1612 except LdbError as e52:
1613 (num, msg) = e52.args
1614 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
1615 self.assertTrue('00002085' in msg)
1619 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1620 m["pls1"] = MessageElement(str(-1),
1623 m["pls2"] = MessageElement(str(0),
1628 except LdbError as e53:
1629 (num, msg) = e53.args
1630 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
1631 self.assertTrue('00002085' in msg)
1634 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1635 m["pls1"] = MessageElement(str(lastset),
1638 m["pls2"] = MessageElement(str(-1),
1643 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1645 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1646 self.assertTrue(len(res1) == 1)
1647 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1648 ATYPE_NORMAL_ACCOUNT)
1649 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1650 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1651 self.assertEqual(int(res1[0]["pwdLastSet"][0]), lastset)
1655 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1656 m["pls1"] = MessageElement(str(lastset),
1659 m["pls2"] = MessageElement(str(lastset),
1664 except LdbError as e54:
1665 (num, msg) = e54.args
1666 self.assertEquals(num, ERR_OTHER)
1667 self.assertTrue('00000057' in msg)
1670 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1671 m["pls1"] = MessageElement(str(lastset),
1674 m["pls2"] = MessageElement(str(0),
1678 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1680 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1681 self.assertTrue(len(res1) == 1)
1682 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1683 ATYPE_NORMAL_ACCOUNT)
1684 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1685 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1686 uac = int(res1[0]["userAccountControl"][0])
1687 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1690 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1691 m["uac1"] = MessageElement(str(uac |UF_PASSWORD_EXPIRED),
1693 "userAccountControl")
1695 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1697 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1698 self.assertTrue(len(res1) == 1)
1699 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1700 ATYPE_NORMAL_ACCOUNT)
1701 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1702 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1703 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1705 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1707 def test_ldap_bind_must_change_pwd(self):
1708 """Test the error messages for failing LDAP binds"""
1709 print("Test the error messages for failing LDAP binds\n")
1711 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1713 def format_error_msg(hresult_v, dsid_v, werror_v):
1715 # There are 4 lower case hex digits following 'v' at the end,
1716 # but different Windows Versions return different values:
1718 # Windows 2008R2 uses 'v1db1'
1719 # Windows 2012R2 uses 'v2580'
1721 return "%08X: LdapErr: DSID-%08X, comment: AcceptSecurityContext error, data %x, v" % (
1722 hresult_v, dsid_v, werror_v)
1724 HRES_SEC_E_LOGON_DENIED = 0x8009030C
1725 HRES_SEC_E_INVALID_TOKEN = 0x80090308
1727 sasl_bind_dsid = 0x0C0904DC
1728 simple_bind_dsid = 0x0C0903A9
1730 error_msg_sasl_wrong_pw = format_error_msg(
1731 HRES_SEC_E_LOGON_DENIED,
1733 werror.WERR_LOGON_FAILURE)
1734 error_msg_sasl_must_change = format_error_msg(
1735 HRES_SEC_E_LOGON_DENIED,
1737 werror.WERR_PASSWORD_MUST_CHANGE)
1738 error_msg_simple_wrong_pw = format_error_msg(
1739 HRES_SEC_E_INVALID_TOKEN,
1741 werror.WERR_LOGON_FAILURE)
1742 error_msg_simple_must_change = format_error_msg(
1743 HRES_SEC_E_INVALID_TOKEN,
1745 werror.WERR_PASSWORD_MUST_CHANGE)
1747 username = "ldaptestuser"
1748 password = "thatsAcomplPASS2"
1749 utf16pw = text_type('"' + password + '"').encode('utf-16-le')
1752 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1753 "objectclass": "user",
1754 "sAMAccountName": username,
1755 "userAccountControl": str(UF_NORMAL_ACCOUNT),
1756 "unicodePwd": utf16pw,
1759 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1761 attrs=["sAMAccountName", "sAMAccountType", "userAccountControl", "pwdLastSet"])
1762 self.assertTrue(len(res1) == 1)
1763 self.assertEqual(str(res1[0]["sAMAccountName"][0]), username)
1764 self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1765 self.assertEqual(int(res1[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT)
1766 self.assertNotEqual(int(res1[0]["pwdLastSet"][0]), 0)
1768 # Open a second LDB connection with the user credentials. Use the
1769 # command line credentials for information like the domain, the realm
1770 # and the workstation.
1771 sasl_creds = Credentials()
1772 sasl_creds.set_username(username)
1773 sasl_creds.set_password(password)
1774 sasl_creds.set_domain(creds.get_domain())
1775 sasl_creds.set_workstation(creds.get_workstation())
1776 sasl_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1777 sasl_creds.set_kerberos_state(DONT_USE_KERBEROS)
1779 sasl_wrong_creds = Credentials()
1780 sasl_wrong_creds.set_username(username)
1781 sasl_wrong_creds.set_password("wrong")
1782 sasl_wrong_creds.set_domain(creds.get_domain())
1783 sasl_wrong_creds.set_workstation(creds.get_workstation())
1784 sasl_wrong_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1785 sasl_wrong_creds.set_kerberos_state(DONT_USE_KERBEROS)
1787 simple_creds = Credentials()
1788 simple_creds.set_bind_dn("cn=ldaptestuser,cn=users," + self.base_dn)
1789 simple_creds.set_username(username)
1790 simple_creds.set_password(password)
1791 simple_creds.set_domain(creds.get_domain())
1792 simple_creds.set_workstation(creds.get_workstation())
1793 simple_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1794 simple_creds.set_kerberos_state(DONT_USE_KERBEROS)
1796 simple_wrong_creds = Credentials()
1797 simple_wrong_creds.set_bind_dn("cn=ldaptestuser,cn=users," + self.base_dn)
1798 simple_wrong_creds.set_username(username)
1799 simple_wrong_creds.set_password("wrong")
1800 simple_wrong_creds.set_domain(creds.get_domain())
1801 simple_wrong_creds.set_workstation(creds.get_workstation())
1802 simple_wrong_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1803 simple_wrong_creds.set_kerberos_state(DONT_USE_KERBEROS)
1805 sasl_ldb = SamDB(url=host, credentials=sasl_creds, lp=lp)
1806 self.assertIsNotNone(sasl_ldb)
1809 requires_strong_auth = False
1811 simple_ldb = SamDB(url=host, credentials=simple_creds, lp=lp)
1812 self.assertIsNotNone(simple_ldb)
1814 except LdbError as e55:
1815 (num, msg) = e55.args
1816 if num != ERR_STRONG_AUTH_REQUIRED:
1818 requires_strong_auth = True
1820 def assertLDAPErrorMsg(msg, expected_msg):
1821 self.assertTrue(expected_msg in msg,
1822 "msg[%s] does not contain expected[%s]" % (
1826 ldb_fail = SamDB(url=host, credentials=sasl_wrong_creds, lp=lp)
1828 except LdbError as e56:
1829 (num, msg) = e56.args
1830 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1831 self.assertTrue(error_msg_sasl_wrong_pw in msg)
1833 if not requires_strong_auth:
1835 ldb_fail = SamDB(url=host, credentials=simple_wrong_creds, lp=lp)
1837 except LdbError as e4:
1838 (num, msg) = e4.args
1839 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1840 assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw)
1843 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1844 m["pls1"] = MessageElement(str(0),
1849 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1850 scope=SCOPE_BASE, attrs=["pwdLastSet"])
1851 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1854 ldb_fail = SamDB(url=host, credentials=sasl_wrong_creds, lp=lp)
1856 except LdbError as e57:
1857 (num, msg) = e57.args
1858 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1859 assertLDAPErrorMsg(msg, error_msg_sasl_wrong_pw)
1862 ldb_fail = SamDB(url=host, credentials=sasl_creds, lp=lp)
1864 except LdbError as e58:
1865 (num, msg) = e58.args
1866 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1867 assertLDAPErrorMsg(msg, error_msg_sasl_must_change)
1869 if not requires_strong_auth:
1871 ldb_fail = SamDB(url=host, credentials=simple_wrong_creds, lp=lp)
1873 except LdbError as e5:
1874 (num, msg) = e5.args
1875 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1876 assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw)
1879 ldb_fail = SamDB(url=host, credentials=simple_creds, lp=lp)
1881 except LdbError as e6:
1882 (num, msg) = e6.args
1883 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1884 assertLDAPErrorMsg(msg, error_msg_simple_must_change)
1886 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1888 def test_userAccountControl(self):
1889 """Test the userAccountControl behaviour"""
1890 print("Testing userAccountControl behaviour\n")
1892 # With a user object
1896 # As user you can only set a normal account.
1897 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1899 # With SYSTEM rights you can set a interdomain trust account.
1902 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1903 "objectclass": "user",
1904 "userAccountControl": "0"})
1906 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1908 attrs=["sAMAccountType", "userAccountControl"])
1909 self.assertTrue(len(res1) == 1)
1910 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1911 ATYPE_NORMAL_ACCOUNT)
1912 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
1913 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0)
1914 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1917 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1918 "objectclass": "user",
1919 "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1920 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1923 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1924 "objectclass": "user",
1925 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1927 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1929 attrs=["sAMAccountType", "userAccountControl"])
1930 self.assertTrue(len(res1) == 1)
1931 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1932 ATYPE_NORMAL_ACCOUNT)
1933 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
1934 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1937 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1938 "objectclass": "user",
1939 "userAccountControl": str(UF_NORMAL_ACCOUNT |
1942 UF_PASSWORD_EXPIRED)})
1944 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1946 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
1947 self.assertTrue(len(res1) == 1)
1948 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1949 ATYPE_NORMAL_ACCOUNT)
1950 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
1951 self.assertFalse("lockoutTime" in res1[0])
1952 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
1953 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1957 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1958 "objectclass": "user",
1959 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1961 except LdbError as e59:
1963 self.assertEquals(num, ERR_OTHER)
1964 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1968 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1969 "objectclass": "user",
1970 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1972 except LdbError as e60:
1974 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1975 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1979 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1980 "objectclass": "user",
1981 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1982 except LdbError as e61:
1984 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1985 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1989 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1990 "objectclass": "user",
1991 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)})
1992 except LdbError as e62:
1994 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1995 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1999 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2000 "objectclass": "user",
2001 "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
2003 except LdbError as e63:
2005 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2006 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2011 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2012 "objectclass": "user"})
2014 # After creation we should have a normal account
2015 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2017 attrs=["sAMAccountType", "userAccountControl"])
2018 self.assertTrue(len(res1) == 1)
2019 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2020 ATYPE_NORMAL_ACCOUNT)
2021 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2023 # As user you can only switch from a normal account to a workstation
2024 # trust account and back.
2025 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2027 # With SYSTEM rights you can switch to a interdomain trust account.
2032 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2033 m["userAccountControl"] = MessageElement("0",
2034 FLAG_MOD_REPLACE, "userAccountControl")
2036 except LdbError as e64:
2038 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2042 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2043 m["userAccountControl"] = MessageElement(
2044 str(UF_NORMAL_ACCOUNT),
2045 FLAG_MOD_REPLACE, "userAccountControl")
2047 except LdbError as e65:
2049 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2052 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2053 m["userAccountControl"] = MessageElement(
2054 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2055 FLAG_MOD_REPLACE, "userAccountControl")
2058 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2060 attrs=["sAMAccountType", "userAccountControl"])
2061 self.assertTrue(len(res1) == 1)
2062 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2063 ATYPE_NORMAL_ACCOUNT)
2064 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2067 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2068 m["userAccountControl"] = MessageElement(
2069 str(UF_ACCOUNTDISABLE),
2070 FLAG_MOD_REPLACE, "userAccountControl")
2073 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2075 attrs=["sAMAccountType", "userAccountControl"])
2076 self.assertTrue(len(res1) == 1)
2077 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2078 ATYPE_NORMAL_ACCOUNT)
2079 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2080 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2083 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2084 m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
2085 m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
2089 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2090 m["userAccountControl"] = MessageElement(
2091 str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
2092 FLAG_MOD_REPLACE, "userAccountControl")
2095 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2097 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2098 self.assertTrue(len(res1) == 1)
2099 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2100 ATYPE_NORMAL_ACCOUNT)
2101 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2102 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2103 self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
2104 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2108 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2109 m["userAccountControl"] = MessageElement(
2110 str(UF_TEMP_DUPLICATE_ACCOUNT),
2111 FLAG_MOD_REPLACE, "userAccountControl")
2114 except LdbError as e66:
2116 self.assertEquals(num, ERR_OTHER)
2120 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2121 m["userAccountControl"] = MessageElement(
2122 str(UF_SERVER_TRUST_ACCOUNT),
2123 FLAG_MOD_REPLACE, "userAccountControl")
2126 except LdbError as e67:
2128 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2131 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2132 m["userAccountControl"] = MessageElement(
2133 str(UF_WORKSTATION_TRUST_ACCOUNT),
2134 FLAG_MOD_REPLACE, "userAccountControl")
2139 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2140 m["userAccountControl"] = MessageElement(
2141 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT),
2142 FLAG_MOD_REPLACE, "userAccountControl")
2145 except LdbError as e68:
2147 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2149 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2150 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2151 self.assertTrue(len(res1) == 1)
2152 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2153 ATYPE_WORKSTATION_TRUST)
2156 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2157 m["userAccountControl"] = MessageElement(
2158 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2159 FLAG_MOD_REPLACE, "userAccountControl")
2162 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2163 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2164 self.assertTrue(len(res1) == 1)
2165 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2166 ATYPE_NORMAL_ACCOUNT)
2170 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2171 m["userAccountControl"] = MessageElement(
2172 str(UF_INTERDOMAIN_TRUST_ACCOUNT),
2173 FLAG_MOD_REPLACE, "userAccountControl")
2176 except LdbError as e69:
2178 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2180 # With a computer object
2184 # As computer you can set a normal account and a server trust account.
2185 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2187 # With SYSTEM rights you can set a interdomain trust account.
2190 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2191 "objectclass": "computer",
2192 "userAccountControl": "0"})
2194 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2196 attrs=["sAMAccountType", "userAccountControl"])
2197 self.assertTrue(len(res1) == 1)
2198 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2199 ATYPE_NORMAL_ACCOUNT)
2200 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2201 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0)
2202 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2205 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2206 "objectclass": "computer",
2207 "userAccountControl": str(UF_NORMAL_ACCOUNT)})
2208 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2211 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2212 "objectclass": "computer",
2213 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
2215 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2217 attrs=["sAMAccountType", "userAccountControl"])
2218 self.assertTrue(len(res1) == 1)
2219 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2220 ATYPE_NORMAL_ACCOUNT)
2221 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2222 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2225 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2226 "objectclass": "computer",
2227 "userAccountControl": str(UF_NORMAL_ACCOUNT |
2230 UF_PASSWORD_EXPIRED)})
2232 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2234 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2235 self.assertTrue(len(res1) == 1)
2236 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2237 ATYPE_NORMAL_ACCOUNT)
2238 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2239 self.assertFalse("lockoutTime" in res1[0])
2240 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2241 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2245 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2246 "objectclass": "computer",
2247 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
2249 except LdbError as e70:
2251 self.assertEquals(num, ERR_OTHER)
2252 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2255 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2256 "objectclass": "computer",
2257 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
2259 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2260 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2261 self.assertTrue(len(res1) == 1)
2262 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2263 ATYPE_WORKSTATION_TRUST)
2264 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2268 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2269 "objectclass": "computer",
2270 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
2271 except LdbError as e71:
2273 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
2274 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2278 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2279 "objectclass": "computer",
2280 "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
2282 except LdbError as e72:
2284 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2285 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2290 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2291 "objectclass": "computer"})
2293 # After creation we should have a normal account
2294 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2296 attrs=["sAMAccountType", "userAccountControl"])
2297 self.assertTrue(len(res1) == 1)
2298 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2299 ATYPE_NORMAL_ACCOUNT)
2300 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2302 # As computer you can switch from a normal account to a workstation
2303 # or server trust account and back (also swapping between trust
2304 # accounts is allowed).
2305 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2307 # With SYSTEM rights you can switch to a interdomain trust account.
2312 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2313 m["userAccountControl"] = MessageElement("0",
2314 FLAG_MOD_REPLACE, "userAccountControl")
2316 except LdbError as e73:
2318 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2322 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2323 m["userAccountControl"] = MessageElement(
2324 str(UF_NORMAL_ACCOUNT),
2325 FLAG_MOD_REPLACE, "userAccountControl")
2327 except LdbError as e74:
2329 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2332 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2333 m["userAccountControl"] = MessageElement(
2334 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2335 FLAG_MOD_REPLACE, "userAccountControl")
2338 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2340 attrs=["sAMAccountType", "userAccountControl"])
2341 self.assertTrue(len(res1) == 1)
2342 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2343 ATYPE_NORMAL_ACCOUNT)
2344 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2347 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2348 m["userAccountControl"] = MessageElement(
2349 str(UF_ACCOUNTDISABLE),
2350 FLAG_MOD_REPLACE, "userAccountControl")
2353 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2355 attrs=["sAMAccountType", "userAccountControl"])
2356 self.assertTrue(len(res1) == 1)
2357 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2358 ATYPE_NORMAL_ACCOUNT)
2359 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2360 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2363 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2364 m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
2365 m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
2369 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2370 m["userAccountControl"] = MessageElement(
2371 str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
2372 FLAG_MOD_REPLACE, "userAccountControl")
2375 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2377 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2378 self.assertTrue(len(res1) == 1)
2379 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2380 ATYPE_NORMAL_ACCOUNT)
2381 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2382 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2383 self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
2384 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2388 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2389 m["userAccountControl"] = MessageElement(
2390 str(UF_TEMP_DUPLICATE_ACCOUNT),
2391 FLAG_MOD_REPLACE, "userAccountControl")
2394 except LdbError as e75:
2396 self.assertEquals(num, ERR_OTHER)
2399 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2400 m["userAccountControl"] = MessageElement(
2401 str(UF_SERVER_TRUST_ACCOUNT),
2402 FLAG_MOD_REPLACE, "userAccountControl")
2405 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2406 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2407 self.assertTrue(len(res1) == 1)
2408 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2409 ATYPE_WORKSTATION_TRUST)
2412 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2413 m["userAccountControl"] = MessageElement(
2414 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2415 FLAG_MOD_REPLACE, "userAccountControl")
2418 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2419 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2420 self.assertTrue(len(res1) == 1)
2421 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2422 ATYPE_NORMAL_ACCOUNT)
2425 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2426 m["userAccountControl"] = MessageElement(
2427 str(UF_WORKSTATION_TRUST_ACCOUNT),
2428 FLAG_MOD_REPLACE, "userAccountControl")
2431 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2432 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2433 self.assertTrue(len(res1) == 1)
2434 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2435 ATYPE_WORKSTATION_TRUST)
2438 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2439 m["userAccountControl"] = MessageElement(
2440 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2441 FLAG_MOD_REPLACE, "userAccountControl")
2444 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2445 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2446 self.assertTrue(len(res1) == 1)
2447 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2448 ATYPE_NORMAL_ACCOUNT)
2451 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2452 m["userAccountControl"] = MessageElement(
2453 str(UF_SERVER_TRUST_ACCOUNT),
2454 FLAG_MOD_REPLACE, "userAccountControl")
2457 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2458 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2459 self.assertTrue(len(res1) == 1)
2460 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2461 ATYPE_WORKSTATION_TRUST)
2464 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2465 m["userAccountControl"] = MessageElement(
2466 str(UF_WORKSTATION_TRUST_ACCOUNT),
2467 FLAG_MOD_REPLACE, "userAccountControl")
2470 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2471 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2472 self.assertTrue(len(res1) == 1)
2473 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2474 ATYPE_WORKSTATION_TRUST)
2478 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2479 m["userAccountControl"] = MessageElement(
2480 str(UF_INTERDOMAIN_TRUST_ACCOUNT),
2481 FLAG_MOD_REPLACE, "userAccountControl")
2484 except LdbError as e76:
2486 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2488 # "primaryGroupID" does not change if account type remains the same
2490 # For a user account
2493 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
2494 "objectclass": "user",
2495 "userAccountControl": str(UF_NORMAL_ACCOUNT |
2497 UF_ACCOUNTDISABLE)})
2499 res1 = ldb.search("cn=ldaptestuser2,cn=users," + self.base_dn,
2501 attrs=["userAccountControl"])
2502 self.assertTrue(len(res1) == 1)
2503 self.assertEquals(int(res1[0]["userAccountControl"][0]),
2504 UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2507 m.dn = Dn(ldb, "<SID=" + ldb.get_domain_sid() + "-" + str(DOMAIN_RID_ADMINS) + ">")
2508 m["member"] = MessageElement(
2509 "cn=ldaptestuser2,cn=users," + self.base_dn, FLAG_MOD_ADD, "member")
2513 m.dn = Dn(ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2514 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_ADMINS),
2515 FLAG_MOD_REPLACE, "primaryGroupID")
2519 m.dn = Dn(ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2520 m["userAccountControl"] = MessageElement(
2521 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2522 FLAG_MOD_REPLACE, "userAccountControl")
2525 res1 = ldb.search("cn=ldaptestuser2,cn=users," + self.base_dn,
2527 attrs=["userAccountControl", "primaryGroupID"])
2528 self.assertTrue(len(res1) == 1)
2529 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2530 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_ADMINS)
2532 # For a workstation account
2534 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2536 attrs=["primaryGroupID"])
2537 self.assertTrue(len(res1) == 1)
2538 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS)
2541 m.dn = Dn(ldb, "<SID=" + ldb.get_domain_sid() + "-" + str(DOMAIN_RID_USERS) + ">")
2542 m["member"] = MessageElement(
2543 "cn=ldaptestcomputer,cn=computers," + self.base_dn, FLAG_MOD_ADD, "member")
2547 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2548 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS),
2549 FLAG_MOD_REPLACE, "primaryGroupID")
2553 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2554 m["userAccountControl"] = MessageElement(
2555 str(UF_WORKSTATION_TRUST_ACCOUNT),
2556 FLAG_MOD_REPLACE, "userAccountControl")
2559 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2561 attrs=["primaryGroupID"])
2562 self.assertTrue(len(res1) == 1)
2563 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS)
2565 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2566 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2567 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2569 def find_repl_meta_data(self, rpmd, attid):
2570 for i in range(0, rpmd.ctr.count):
2571 m = rpmd.ctr.array[i]
2572 if m.attid == attid:
2576 def test_smartcard_required1(self):
2577 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2578 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2580 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2583 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2584 "objectclass": "user",
2585 "userAccountControl": str(UF_NORMAL_ACCOUNT),
2586 "unicodePwd": "\"thatsAcomplPASS2\"".encode('utf-16-le')
2589 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2591 attrs=["sAMAccountType", "userAccountControl",
2592 "pwdLastSet", "msDS-KeyVersionNumber",
2593 "replPropertyMetaData"])
2594 self.assertTrue(len(res) == 1)
2595 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2596 ATYPE_NORMAL_ACCOUNT)
2597 self.assertEqual(int(res[0]["userAccountControl"][0]),
2599 self.assertNotEqual(int(res[0]["pwdLastSet"][0]), 0)
2600 lastset = int(res[0]["pwdLastSet"][0])
2601 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2602 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2603 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2604 res[0]["replPropertyMetaData"][0])
2605 lastsetmd = self.find_repl_meta_data(rpmd,
2606 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2607 self.assertIsNotNone(lastsetmd)
2608 self.assertEqual(lastsetmd.version, 1)
2609 nthashmd = self.find_repl_meta_data(rpmd,
2610 drsuapi.DRSUAPI_ATTID_unicodePwd)
2611 self.assertIsNotNone(nthashmd)
2612 self.assertEqual(nthashmd.version, 1)
2613 nthistmd = self.find_repl_meta_data(rpmd,
2614 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2615 self.assertIsNotNone(nthistmd)
2616 self.assertEqual(nthistmd.version, 1)
2617 lmhashmd = self.find_repl_meta_data(rpmd,
2618 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2619 self.assertIsNotNone(lmhashmd)
2620 self.assertEqual(lmhashmd.version, 1)
2621 lmhistmd = self.find_repl_meta_data(rpmd,
2622 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2623 self.assertIsNotNone(lmhistmd)
2624 self.assertEqual(lmhistmd.version, 1)
2625 spcbmd = self.find_repl_meta_data(rpmd,
2626 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2627 self.assertIsNotNone(spcbmd)
2628 self.assertEqual(spcbmd.version, 1)
2631 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2632 m["userAccountControl"] = MessageElement(
2633 str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED),
2634 FLAG_MOD_REPLACE, "userAccountControl")
2637 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2639 attrs=["sAMAccountType", "userAccountControl",
2640 "pwdLastSet", "msDS-KeyVersionNumber",
2641 "replPropertyMetaData"])
2642 self.assertTrue(len(res) == 1)
2643 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2644 ATYPE_NORMAL_ACCOUNT)
2645 self.assertEqual(int(res[0]["userAccountControl"][0]),
2646 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED)
2647 self.assertEqual(int(res[0]["pwdLastSet"][0]), lastset)
2648 lastset1 = int(res[0]["pwdLastSet"][0])
2649 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2650 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2651 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2652 res[0]["replPropertyMetaData"][0])
2653 lastsetmd = self.find_repl_meta_data(rpmd,
2654 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2655 self.assertIsNotNone(lastsetmd)
2656 self.assertEqual(lastsetmd.version, 1)
2657 nthashmd = self.find_repl_meta_data(rpmd,
2658 drsuapi.DRSUAPI_ATTID_unicodePwd)
2659 self.assertIsNotNone(nthashmd)
2660 self.assertEqual(nthashmd.version, 2)
2661 nthistmd = self.find_repl_meta_data(rpmd,
2662 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2663 self.assertIsNotNone(nthistmd)
2664 self.assertEqual(nthistmd.version, 2)
2665 lmhashmd = self.find_repl_meta_data(rpmd,
2666 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2667 self.assertIsNotNone(lmhashmd)
2668 self.assertEqual(lmhashmd.version, 2)
2669 lmhistmd = self.find_repl_meta_data(rpmd,
2670 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2671 self.assertIsNotNone(lmhistmd)
2672 self.assertEqual(lmhistmd.version, 2)
2673 spcbmd = self.find_repl_meta_data(rpmd,
2674 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2675 self.assertIsNotNone(spcbmd)
2676 self.assertEqual(spcbmd.version, 2)
2678 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2680 def test_smartcard_required2(self):
2681 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2682 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2684 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2687 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2688 "objectclass": "user",
2689 "userAccountControl": str(UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE),
2692 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2694 attrs=["sAMAccountType", "userAccountControl",
2695 "pwdLastSet", "msDS-KeyVersionNumber",
2696 "replPropertyMetaData"])
2697 self.assertTrue(len(res) == 1)
2698 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2699 ATYPE_NORMAL_ACCOUNT)
2700 self.assertEqual(int(res[0]["userAccountControl"][0]),
2701 UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE)
2702 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2703 self.assertTrue("msDS-KeyVersionNumber" in res[0])
2704 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2705 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2706 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2707 res[0]["replPropertyMetaData"][0])
2708 lastsetmd = self.find_repl_meta_data(rpmd,
2709 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2710 self.assertIsNotNone(lastsetmd)
2711 self.assertEqual(lastsetmd.version, 1)
2712 nthashmd = self.find_repl_meta_data(rpmd,
2713 drsuapi.DRSUAPI_ATTID_unicodePwd)
2714 self.assertIsNotNone(nthashmd)
2715 self.assertEqual(nthashmd.version, 1)
2716 nthistmd = self.find_repl_meta_data(rpmd,
2717 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2718 self.assertIsNotNone(nthistmd)
2719 self.assertEqual(nthistmd.version, 1)
2720 lmhashmd = self.find_repl_meta_data(rpmd,
2721 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2722 self.assertIsNotNone(lmhashmd)
2723 self.assertEqual(lmhashmd.version, 1)
2724 lmhistmd = self.find_repl_meta_data(rpmd,
2725 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2726 self.assertIsNotNone(lmhistmd)
2727 self.assertEqual(lmhistmd.version, 1)
2728 spcbmd = self.find_repl_meta_data(rpmd,
2729 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2730 self.assertIsNone(spcbmd)
2733 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2734 m["userAccountControl"] = MessageElement(
2735 str(UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE |UF_SMARTCARD_REQUIRED),
2736 FLAG_MOD_REPLACE, "userAccountControl")
2739 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2741 attrs=["sAMAccountType", "userAccountControl",
2742 "pwdLastSet", "msDS-KeyVersionNumber",
2743 "replPropertyMetaData"])
2744 self.assertTrue(len(res) == 1)
2745 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2746 ATYPE_NORMAL_ACCOUNT)
2747 self.assertEqual(int(res[0]["userAccountControl"][0]),
2748 UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE |UF_SMARTCARD_REQUIRED)
2749 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2750 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2751 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2752 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2753 res[0]["replPropertyMetaData"][0])
2754 lastsetmd = self.find_repl_meta_data(rpmd,
2755 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2756 self.assertIsNotNone(lastsetmd)
2757 self.assertEqual(lastsetmd.version, 1)
2758 nthashmd = self.find_repl_meta_data(rpmd,
2759 drsuapi.DRSUAPI_ATTID_unicodePwd)
2760 self.assertIsNotNone(nthashmd)
2761 self.assertEqual(nthashmd.version, 2)
2762 nthistmd = self.find_repl_meta_data(rpmd,
2763 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2764 self.assertIsNotNone(nthistmd)
2765 self.assertEqual(nthistmd.version, 2)
2766 lmhashmd = self.find_repl_meta_data(rpmd,
2767 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2768 self.assertIsNotNone(lmhashmd)
2769 self.assertEqual(lmhashmd.version, 2)
2770 lmhistmd = self.find_repl_meta_data(rpmd,
2771 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2772 self.assertIsNotNone(lmhistmd)
2773 self.assertEqual(lmhistmd.version, 2)
2774 spcbmd = self.find_repl_meta_data(rpmd,
2775 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2776 self.assertIsNotNone(spcbmd)
2777 self.assertEqual(spcbmd.version, 1)
2780 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2781 m["userAccountControl"] = MessageElement(
2782 str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED),
2783 FLAG_MOD_REPLACE, "userAccountControl")
2786 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2788 attrs=["sAMAccountType", "userAccountControl",
2789 "pwdLastSet", "msDS-KeyVersionNumber",
2790 "replPropertyMetaData"])
2791 self.assertTrue(len(res) == 1)
2792 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2793 ATYPE_NORMAL_ACCOUNT)
2794 self.assertEqual(int(res[0]["userAccountControl"][0]),
2795 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED)
2796 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2797 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2798 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2799 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2800 res[0]["replPropertyMetaData"][0])
2801 lastsetmd = self.find_repl_meta_data(rpmd,
2802 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2803 self.assertIsNotNone(lastsetmd)
2804 self.assertEqual(lastsetmd.version, 1)
2805 nthashmd = self.find_repl_meta_data(rpmd,
2806 drsuapi.DRSUAPI_ATTID_unicodePwd)
2807 self.assertIsNotNone(nthashmd)
2808 self.assertEqual(nthashmd.version, 2)
2809 nthistmd = self.find_repl_meta_data(rpmd,
2810 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2811 self.assertIsNotNone(nthistmd)
2812 self.assertEqual(nthistmd.version, 2)
2813 lmhashmd = self.find_repl_meta_data(rpmd,
2814 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2815 self.assertIsNotNone(lmhashmd)
2816 self.assertEqual(lmhashmd.version, 2)
2817 lmhistmd = self.find_repl_meta_data(rpmd,
2818 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2819 self.assertIsNotNone(lmhistmd)
2820 self.assertEqual(lmhistmd.version, 2)
2821 spcbmd = self.find_repl_meta_data(rpmd,
2822 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2823 self.assertIsNotNone(spcbmd)
2824 self.assertEqual(spcbmd.version, 1)
2826 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2828 def test_smartcard_required3(self):
2829 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2830 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2832 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2835 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2836 "objectclass": "user",
2837 "userAccountControl": str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED |UF_ACCOUNTDISABLE),
2840 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2842 attrs=["sAMAccountType", "userAccountControl",
2843 "pwdLastSet", "msDS-KeyVersionNumber",
2844 "replPropertyMetaData"])
2845 self.assertTrue(len(res) == 1)
2846 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2847 ATYPE_NORMAL_ACCOUNT)
2848 self.assertEqual(int(res[0]["userAccountControl"][0]),
2849 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED |UF_ACCOUNTDISABLE)
2850 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2851 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2852 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2853 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2854 res[0]["replPropertyMetaData"][0])
2855 lastsetmd = self.find_repl_meta_data(rpmd,
2856 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2857 self.assertIsNotNone(lastsetmd)
2858 self.assertEqual(lastsetmd.version, 1)
2859 nthashmd = self.find_repl_meta_data(rpmd,
2860 drsuapi.DRSUAPI_ATTID_unicodePwd)
2861 self.assertIsNotNone(nthashmd)
2862 self.assertEqual(nthashmd.version, 1)
2863 nthistmd = self.find_repl_meta_data(rpmd,
2864 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2865 self.assertIsNotNone(nthistmd)
2866 self.assertEqual(nthistmd.version, 1)
2867 lmhashmd = self.find_repl_meta_data(rpmd,
2868 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2869 self.assertIsNotNone(lmhashmd)
2870 self.assertEqual(lmhashmd.version, 1)
2871 lmhistmd = self.find_repl_meta_data(rpmd,
2872 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2873 self.assertIsNotNone(lmhistmd)
2874 self.assertEqual(lmhistmd.version, 1)
2875 spcbmd = self.find_repl_meta_data(rpmd,
2876 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2877 self.assertIsNotNone(spcbmd)
2878 self.assertEqual(spcbmd.version, 1)
2881 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2882 m["userAccountControl"] = MessageElement(
2883 str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED),
2884 FLAG_MOD_REPLACE, "userAccountControl")
2887 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2889 attrs=["sAMAccountType", "userAccountControl",
2890 "pwdLastSet", "msDS-KeyVersionNumber",
2891 "replPropertyMetaData"])
2892 self.assertTrue(len(res) == 1)
2893 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2894 ATYPE_NORMAL_ACCOUNT)
2895 self.assertEqual(int(res[0]["userAccountControl"][0]),
2896 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED)
2897 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2898 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2899 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2900 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2901 res[0]["replPropertyMetaData"][0])
2902 lastsetmd = self.find_repl_meta_data(rpmd,
2903 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2904 self.assertIsNotNone(lastsetmd)
2905 self.assertEqual(lastsetmd.version, 1)
2906 nthashmd = self.find_repl_meta_data(rpmd,
2907 drsuapi.DRSUAPI_ATTID_unicodePwd)
2908 self.assertIsNotNone(nthashmd)
2909 self.assertEqual(nthashmd.version, 1)
2910 nthistmd = self.find_repl_meta_data(rpmd,
2911 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2912 self.assertIsNotNone(nthistmd)
2913 self.assertEqual(nthistmd.version, 1)
2914 lmhashmd = self.find_repl_meta_data(rpmd,
2915 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2916 self.assertIsNotNone(lmhashmd)
2917 self.assertEqual(lmhashmd.version, 1)
2918 lmhistmd = self.find_repl_meta_data(rpmd,
2919 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2920 self.assertIsNotNone(lmhistmd)
2921 self.assertEqual(lmhistmd.version, 1)
2922 spcbmd = self.find_repl_meta_data(rpmd,
2923 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2924 self.assertIsNotNone(spcbmd)
2925 self.assertEqual(spcbmd.version, 1)
2927 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2929 def test_isCriticalSystemObject(self):
2930 """Test the isCriticalSystemObject behaviour"""
2931 print("Testing isCriticalSystemObject behaviour\n")
2936 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2937 "objectclass": "computer"})
2939 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2941 attrs=["isCriticalSystemObject"])
2942 self.assertTrue(len(res1) == 1)
2943 self.assertTrue("isCriticalSystemObject" not in res1[0])
2945 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2948 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2949 "objectclass": "computer",
2950 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
2952 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2954 attrs=["isCriticalSystemObject"])
2955 self.assertTrue(len(res1) == 1)
2956 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "FALSE")
2958 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2961 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2962 "objectclass": "computer",
2963 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)})
2965 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2967 attrs=["isCriticalSystemObject"])
2968 self.assertTrue(len(res1) == 1)
2969 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE")
2971 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2974 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2975 "objectclass": "computer",
2976 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
2978 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2980 attrs=["isCriticalSystemObject"])
2981 self.assertTrue(len(res1) == 1)
2982 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE")
2984 # Modification tests
2987 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2988 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2989 FLAG_MOD_REPLACE, "userAccountControl")
2992 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2994 attrs=["isCriticalSystemObject"])
2995 self.assertTrue(len(res1) == 1)
2996 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE")
2999 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3000 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT),
3001 FLAG_MOD_REPLACE, "userAccountControl")
3004 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3006 attrs=["isCriticalSystemObject"])
3007 self.assertTrue(len(res1) == 1)
3008 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "FALSE")
3011 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3012 m["userAccountControl"] = MessageElement(
3013 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT),
3014 FLAG_MOD_REPLACE, "userAccountControl")
3017 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3019 attrs=["isCriticalSystemObject"])
3020 self.assertTrue(len(res1) == 1)
3021 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE")
3024 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3025 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
3026 FLAG_MOD_REPLACE, "userAccountControl")
3029 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3031 attrs=["isCriticalSystemObject"])
3032 self.assertTrue(len(res1) == 1)
3033 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE")
3036 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3037 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT),
3038 FLAG_MOD_REPLACE, "userAccountControl")
3041 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3043 attrs=["isCriticalSystemObject"])
3044 self.assertTrue(len(res1) == 1)
3045 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "TRUE")
3048 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3049 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT),
3050 FLAG_MOD_REPLACE, "userAccountControl")
3053 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3055 attrs=["isCriticalSystemObject"])
3056 self.assertTrue(len(res1) == 1)
3057 self.assertEquals(str(res1[0]["isCriticalSystemObject"][0]), "FALSE")
3059 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3061 def test_service_principal_name_updates(self):
3062 """Test the servicePrincipalNames update behaviour"""
3063 print("Testing servicePrincipalNames update behaviour\n")
3066 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3067 "objectclass": "computer",
3068 "dNSHostName": "testname.testdom"})
3070 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3071 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3072 self.assertTrue(len(res) == 1)
3073 self.assertFalse("servicePrincipalName" in res[0])
3075 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3078 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3079 "objectclass": "computer",
3080 "servicePrincipalName": "HOST/testname.testdom"})
3082 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3083 scope=SCOPE_BASE, attrs=["dNSHostName"])
3084 self.assertTrue(len(res) == 1)
3085 self.assertFalse("dNSHostName" in res[0])
3087 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3090 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3091 "objectclass": "computer",
3092 "dNSHostName": "testname2.testdom",
3093 "servicePrincipalName": "HOST/testname.testdom"})
3095 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3096 scope=SCOPE_BASE, attrs=["dNSHostName"])
3097 self.assertTrue(len(res) == 1)
3098 self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom")
3100 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3101 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3102 self.assertTrue(len(res) == 1)
3103 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3104 "HOST/testname.testdom")
3107 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3108 m["dNSHostName"] = MessageElement("testname.testdoM",
3109 FLAG_MOD_REPLACE, "dNSHostName")
3112 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3113 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3114 self.assertTrue(len(res) == 1)
3115 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3116 "HOST/testname.testdom")
3119 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3120 m["dNSHostName"] = MessageElement("testname2.testdom2",
3121 FLAG_MOD_REPLACE, "dNSHostName")
3124 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3125 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3126 self.assertTrue(len(res) == 1)
3127 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3128 "HOST/testname2.testdom2")
3131 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3132 m["dNSHostName"] = MessageElement([],
3133 FLAG_MOD_DELETE, "dNSHostName")
3136 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3137 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3138 self.assertTrue(len(res) == 1)
3139 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3140 "HOST/testname2.testdom2")
3143 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3144 m["dNSHostName"] = MessageElement("testname.testdom3",
3145 FLAG_MOD_REPLACE, "dNSHostName")
3148 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3149 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3150 self.assertTrue(len(res) == 1)
3151 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3152 "HOST/testname2.testdom2")
3155 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3156 m["dNSHostName"] = MessageElement("testname2.testdom2",
3157 FLAG_MOD_REPLACE, "dNSHostName")
3161 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3162 m["dNSHostName"] = MessageElement("testname3.testdom3",
3163 FLAG_MOD_REPLACE, "dNSHostName")
3164 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
3166 "servicePrincipalName")
3169 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3170 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3171 self.assertTrue(len(res) == 1)
3172 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3173 "HOST/testname3.testdom3")
3176 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3177 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
3179 "servicePrincipalName")
3180 m["dNSHostName"] = MessageElement("testname4.testdom4",
3181 FLAG_MOD_REPLACE, "dNSHostName")
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.assertEquals(str(res[0]["servicePrincipalName"][0]),
3188 "HOST/testname2.testdom2")
3191 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3192 m["servicePrincipalName"] = MessageElement([],
3194 "servicePrincipalName")
3198 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3199 m["dNSHostName"] = MessageElement("testname2.testdom2",
3200 FLAG_MOD_REPLACE, "dNSHostName")
3203 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3204 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3205 self.assertTrue(len(res) == 1)
3206 self.assertFalse("servicePrincipalName" in res[0])
3208 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3211 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3212 "objectclass": "computer",
3213 "sAMAccountName": "testname$"})
3215 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3216 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3217 self.assertTrue(len(res) == 1)
3218 self.assertFalse("servicePrincipalName" in res[0])
3220 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3223 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3224 "objectclass": "computer",
3225 "servicePrincipalName": "HOST/testname"})
3227 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3228 scope=SCOPE_BASE, attrs=["sAMAccountName"])
3229 self.assertTrue(len(res) == 1)
3230 self.assertTrue("sAMAccountName" in res[0])
3232 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3235 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3236 "objectclass": "computer",
3237 "sAMAccountName": "testname$",
3238 "servicePrincipalName": "HOST/testname"})
3240 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3241 scope=SCOPE_BASE, attrs=["sAMAccountName"])
3242 self.assertTrue(len(res) == 1)
3243 self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname$")
3245 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3246 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3247 self.assertTrue(len(res) == 1)
3248 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3252 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3253 m["sAMAccountName"] = MessageElement("testnamE$",
3254 FLAG_MOD_REPLACE, "sAMAccountName")
3257 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3258 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3259 self.assertTrue(len(res) == 1)
3260 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3264 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3265 m["sAMAccountName"] = MessageElement("testname",
3266 FLAG_MOD_REPLACE, "sAMAccountName")
3269 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3270 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3271 self.assertTrue(len(res) == 1)
3272 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3276 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3277 m["sAMAccountName"] = MessageElement("test$name$",
3278 FLAG_MOD_REPLACE, "sAMAccountName")
3281 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3282 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3283 self.assertTrue(len(res) == 1)
3284 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3288 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3289 m["sAMAccountName"] = MessageElement("testname2",
3290 FLAG_MOD_REPLACE, "sAMAccountName")
3293 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3294 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3295 self.assertTrue(len(res) == 1)
3296 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3300 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3301 m["sAMAccountName"] = MessageElement("testname3",
3302 FLAG_MOD_REPLACE, "sAMAccountName")
3303 m["servicePrincipalName"] = MessageElement("HOST/testname2",
3305 "servicePrincipalName")
3308 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3309 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3310 self.assertTrue(len(res) == 1)
3311 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3315 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3316 m["servicePrincipalName"] = MessageElement("HOST/testname2",
3318 "servicePrincipalName")
3319 m["sAMAccountName"] = MessageElement("testname4",
3320 FLAG_MOD_REPLACE, "sAMAccountName")
3323 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3324 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3325 self.assertTrue(len(res) == 1)
3326 self.assertEquals(str(res[0]["servicePrincipalName"][0]),
3330 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3331 m["servicePrincipalName"] = MessageElement([],
3333 "servicePrincipalName")
3337 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3338 m["sAMAccountName"] = MessageElement("testname2",
3339 FLAG_MOD_REPLACE, "sAMAccountName")
3342 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3343 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3344 self.assertTrue(len(res) == 1)
3345 self.assertFalse("servicePrincipalName" in res[0])
3347 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3350 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3351 "objectclass": "computer",
3352 "dNSHostName": "testname.testdom",
3353 "sAMAccountName": "testname$",
3354 "servicePrincipalName": ["HOST/testname.testdom", "HOST/testname"]
3358 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3359 m["dNSHostName"] = MessageElement("testname2.testdom",
3360 FLAG_MOD_REPLACE, "dNSHostName")
3361 m["sAMAccountName"] = MessageElement("testname2$",
3362 FLAG_MOD_REPLACE, "sAMAccountName")
3365 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3366 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3367 self.assertTrue(len(res) == 1)
3368 self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom")
3369 self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$")
3370 self.assertTrue(str(res[0]["servicePrincipalName"][0]) == "HOST/testname2" or
3371 str(res[0]["servicePrincipalName"][1]) == "HOST/testname2")
3372 self.assertTrue(str(res[0]["servicePrincipalName"][0]) == "HOST/testname2.testdom" or
3373 str(res[0]["servicePrincipalName"][1]) == "HOST/testname2.testdom")
3375 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3378 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3379 "objectclass": "computer",
3380 "dNSHostName": "testname.testdom",
3381 "sAMAccountName": "testname$",
3382 "servicePrincipalName": ["HOST/testname.testdom", "HOST/testname"]
3386 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3387 m["sAMAccountName"] = MessageElement("testname2$",
3388 FLAG_MOD_REPLACE, "sAMAccountName")
3389 m["dNSHostName"] = MessageElement("testname2.testdom",
3390 FLAG_MOD_REPLACE, "dNSHostName")
3393 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3394 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3395 self.assertTrue(len(res) == 1)
3396 self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom")
3397 self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$")
3398 self.assertTrue(len(res[0]["servicePrincipalName"]) == 2)
3399 self.assertTrue("HOST/testname2" in [str(x) for x in res[0]["servicePrincipalName"]])
3400 self.assertTrue("HOST/testname2.testdom" in [str(x) for x in res[0]["servicePrincipalName"]])
3403 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3404 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom",
3405 FLAG_MOD_ADD, "servicePrincipalName")
3409 except LdbError as e77:
3411 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3414 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3415 m["servicePrincipalName"] = MessageElement("HOST/testname3",
3416 FLAG_MOD_ADD, "servicePrincipalName")
3419 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3420 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3421 self.assertTrue(len(res) == 1)
3422 self.assertEquals(str(res[0]["dNSHostName"][0]), "testname2.testdom")
3423 self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$")
3424 self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
3425 self.assertTrue("HOST/testname2" in [str(x) for x in res[0]["servicePrincipalName"]])
3426 self.assertTrue("HOST/testname3" in [str(x) for x in res[0]["servicePrincipalName"]])
3427 self.assertTrue("HOST/testname2.testdom" in [str(x) for x in res[0]["servicePrincipalName"]])
3430 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3431 m["dNSHostName"] = MessageElement("testname3.testdom",
3432 FLAG_MOD_REPLACE, "dNSHostName")
3433 m["servicePrincipalName"] = MessageElement("HOST/testname3.testdom",
3434 FLAG_MOD_ADD, "servicePrincipalName")
3437 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3438 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3439 self.assertTrue(len(res) == 1)
3440 self.assertEquals(str(res[0]["dNSHostName"][0]), "testname3.testdom")
3441 self.assertEquals(str(res[0]["sAMAccountName"][0]), "testname2$")
3442 self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
3443 self.assertTrue("HOST/testname2" in [str(x) for x in res[0]["servicePrincipalName"]])
3444 self.assertTrue("HOST/testname3" in [str(x) for x in res[0]["servicePrincipalName"]])
3445 self.assertTrue("HOST/testname3.testdom" in [str(x) for x in res[0]["servicePrincipalName"]])
3447 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3449 def test_sam_description_attribute(self):
3450 """Test SAM description attribute"""
3451 print("Test SAM description attribute")
3454 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3455 "objectclass": "group",
3456 "description": "desc1"
3459 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3460 scope=SCOPE_BASE, attrs=["description"])
3461 self.assertTrue(len(res) == 1)
3462 self.assertTrue("description" in res[0])
3463 self.assertTrue(len(res[0]["description"]) == 1)
3464 self.assertEquals(str(res[0]["description"][0]), "desc1")
3466 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3469 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3470 "objectclass": "group",
3471 "description": ["desc1", "desc2"]})
3473 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3474 scope=SCOPE_BASE, attrs=["description"])
3475 self.assertTrue(len(res) == 1)
3476 self.assertTrue("description" in res[0])
3477 self.assertTrue(len(res[0]["description"]) == 2)
3478 self.assertTrue(str(res[0]["description"][0]) == "desc1" or
3479 str(res[0]["description"][1]) == "desc1")
3480 self.assertTrue(str(res[0]["description"][0]) == "desc2" or
3481 str(res[0]["description"][1]) == "desc2")
3484 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3485 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_REPLACE,
3490 except LdbError as e78:
3492 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3495 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3496 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_DELETE,
3500 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3503 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3504 "objectclass": "group"})
3507 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3508 m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
3512 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3513 scope=SCOPE_BASE, attrs=["description"])
3514 self.assertTrue(len(res) == 1)
3515 self.assertTrue("description" in res[0])
3516 self.assertTrue(len(res[0]["description"]) == 1)
3517 self.assertEquals(str(res[0]["description"][0]), "desc1")
3519 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3522 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3523 "objectclass": "group",
3524 "description": ["desc1", "desc2"]})
3527 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3528 m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
3532 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3533 scope=SCOPE_BASE, attrs=["description"])
3534 self.assertTrue(len(res) == 1)
3535 self.assertTrue("description" in res[0])
3536 self.assertTrue(len(res[0]["description"]) == 1)
3537 self.assertEquals(str(res[0]["description"][0]), "desc1")
3540 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3541 m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
3546 except LdbError as e79:
3548 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3551 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3552 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_DELETE,
3557 except LdbError as e80:
3559 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
3562 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3563 m["description"] = MessageElement("desc1", FLAG_MOD_DELETE,
3566 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3567 scope=SCOPE_BASE, attrs=["description"])
3568 self.assertTrue(len(res) == 1)
3569 self.assertFalse("description" in res[0])
3572 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3573 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_REPLACE,
3578 except LdbError as e81:
3580 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3583 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3584 m["description"] = MessageElement(["desc3", "desc4"], FLAG_MOD_ADD,
3589 except LdbError as e82:
3591 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3594 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3595 m["description"] = MessageElement("desc1", FLAG_MOD_ADD,
3599 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3600 scope=SCOPE_BASE, attrs=["description"])
3601 self.assertTrue(len(res) == 1)
3602 self.assertTrue("description" in res[0])
3603 self.assertTrue(len(res[0]["description"]) == 1)
3604 self.assertEquals(str(res[0]["description"][0]), "desc1")
3607 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3608 m.add(MessageElement("desc1", FLAG_MOD_DELETE, "description"))
3609 m.add(MessageElement("desc2", FLAG_MOD_ADD, "description"))
3612 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3613 scope=SCOPE_BASE, attrs=["description"])
3614 self.assertTrue(len(res) == 1)
3615 self.assertTrue("description" in res[0])
3616 self.assertTrue(len(res[0]["description"]) == 1)
3617 self.assertEquals(str(res[0]["description"][0]), "desc2")
3619 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3621 def test_fSMORoleOwner_attribute(self):
3622 """Test fSMORoleOwner attribute"""
3623 print("Test fSMORoleOwner attribute")
3625 ds_service_name = self.ldb.get_dsServiceName()
3627 # The "fSMORoleOwner" attribute can only be set to "nTDSDSA" entries,
3628 # invalid DNs return ERR_UNWILLING_TO_PERFORM
3632 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3633 "objectclass": "group",
3634 "fSMORoleOwner": self.base_dn})
3636 except LdbError as e83:
3638 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3642 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3643 "objectclass": "group",
3644 "fSMORoleOwner": []})
3646 except LdbError as e84:
3648 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
3650 # We are able to set it to a valid "nTDSDSA" entry if the server is
3651 # capable of handling the role
3654 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3655 "objectclass": "group",
3656 "fSMORoleOwner": ds_service_name})
3658 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3661 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3662 "objectclass": "group"})
3665 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3666 m.add(MessageElement(self.base_dn, FLAG_MOD_REPLACE, "fSMORoleOwner"))
3670 except LdbError as e85:
3672 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3675 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3676 m.add(MessageElement([], FLAG_MOD_REPLACE, "fSMORoleOwner"))
3680 except LdbError as e86:
3682 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3684 # We are able to set it to a valid "nTDSDSA" entry if the server is
3685 # capable of handling the role
3688 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3689 m.add(MessageElement(ds_service_name, FLAG_MOD_REPLACE, "fSMORoleOwner"))
3692 # A clean-out works on plain entries, not master (schema, PDC...) DNs
3695 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3696 m.add(MessageElement([], FLAG_MOD_DELETE, "fSMORoleOwner"))
3699 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3701 def test_protected_sid_objects(self):
3702 """Test deletion of objects with RID < 1000"""
3703 # a list of some well-known sids
3704 # objects in Builtin are aready covered by objectclass
3706 ["CN=Domain Admins", "CN=Users,"],
3707 ["CN=Schema Admins", "CN=Users,"],
3708 ["CN=Enterprise Admins", "CN=Users,"],
3709 ["CN=Administrator", "CN=Users,"],
3710 ["CN=Domain Controllers", "CN=Users,"],
3713 for pr_object in protected_list:
3715 self.ldb.delete(pr_object[0] + "," + pr_object[1] + self.base_dn)
3716 except LdbError as e7:
3718 self.assertEquals(num, ERR_OTHER)
3720 self.fail("Deleted " + pr_object[0])
3723 self.ldb.rename(pr_object[0] + "," + pr_object[1] + self.base_dn,
3724 pr_object[0] + "2," + pr_object[1] + self.base_dn)
3725 except LdbError as e8:
3727 self.fail("Could not rename " + pr_object[0])
3729 self.ldb.rename(pr_object[0] + "2," + pr_object[1] + self.base_dn,
3730 pr_object[0] + "," + pr_object[1] + self.base_dn)
3732 def test_new_user_default_attributes(self):
3733 """Test default attributes for new user objects"""
3734 print("Test default attributes for new User objects\n")
3736 user_name = "ldaptestuser"
3737 user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
3740 "objectclass": "user",
3741 "sAMAccountName": user_name})
3743 res = ldb.search(user_dn, scope=SCOPE_BASE)
3744 self.assertTrue(len(res) == 1)
3747 expected_attrs = {"primaryGroupID": MessageElement(["513"]),
3748 "logonCount": MessageElement(["0"]),
3749 "cn": MessageElement([user_name]),
3750 "countryCode": MessageElement(["0"]),
3751 "objectClass": MessageElement(["top", "person", "organizationalPerson", "user"]),
3752 "instanceType": MessageElement(["4"]),
3753 "distinguishedName": MessageElement([user_dn]),
3754 "sAMAccountType": MessageElement(["805306368"]),
3755 "objectSid": "**SKIP**",
3756 "whenCreated": "**SKIP**",
3757 "uSNCreated": "**SKIP**",
3758 "badPasswordTime": MessageElement(["0"]),
3759 "dn": Dn(ldb, user_dn),
3760 "pwdLastSet": MessageElement(["0"]),
3761 "sAMAccountName": MessageElement([user_name]),
3762 "objectCategory": MessageElement(["CN=Person,%s" % ldb.get_schema_basedn().get_linearized()]),
3763 "objectGUID": "**SKIP**",
3764 "whenChanged": "**SKIP**",
3765 "badPwdCount": MessageElement(["0"]),
3766 "accountExpires": MessageElement(["9223372036854775807"]),
3767 "name": MessageElement([user_name]),
3768 "codePage": MessageElement(["0"]),
3769 "userAccountControl": MessageElement(["546"]),
3770 "lastLogon": MessageElement(["0"]),
3771 "uSNChanged": "**SKIP**",
3772 "lastLogoff": MessageElement(["0"])}
3773 # assert we have expected attribute names
3774 actual_names = set(user_obj.keys())
3775 # Samba does not use 'dSCorePropagationData', so skip it
3776 actual_names -= set(['dSCorePropagationData'])
3777 self.assertEqual(set(expected_attrs.keys()), actual_names, "Actual object does not have expected attributes")
3778 # check attribute values
3779 for name in expected_attrs.keys():
3780 actual_val = user_obj.get(name)
3781 self.assertFalse(actual_val is None, "No value for attribute '%s'" % name)
3782 expected_val = expected_attrs[name]
3783 if expected_val == "**SKIP**":
3784 # "**ANY**" values means "any"
3786 self.assertEqual(expected_val, actual_val,
3787 "Unexpected value[%r] for '%s' expected[%r]" %
3788 (actual_val, name, expected_val))
3790 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
3793 if "://" not in host:
3794 if os.path.isfile(host):
3795 host = "tdb://%s" % host
3797 host = "ldap://%s" % host
3799 ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp)
3801 TestProgram(module=__name__, opts=subunitopts)