2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
5 from __future__ import print_function
11 sys.path.insert(0, "bin/python")
13 from samba.tests.subunitrun import SubunitOptions, TestProgram
15 import samba.getopt as options
17 from samba.credentials import Credentials, DONT_USE_KERBEROS
18 from samba.auth import system_session
19 from ldb import SCOPE_BASE, LdbError
20 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
21 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
22 from ldb import ERR_OTHER, ERR_NO_SUCH_ATTRIBUTE
23 from ldb import ERR_OBJECT_CLASS_VIOLATION
24 from ldb import ERR_CONSTRAINT_VIOLATION
25 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
26 from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS
27 from ldb import ERR_INVALID_CREDENTIALS
28 from ldb import ERR_STRONG_AUTH_REQUIRED
29 from ldb import Message, MessageElement, Dn
30 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
31 from samba.samdb import SamDB
32 from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_ACCOUNTDISABLE,
33 UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
34 UF_PARTIAL_SECRETS_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT,
35 UF_INTERDOMAIN_TRUST_ACCOUNT, UF_SMARTCARD_REQUIRED,
36 UF_PASSWD_NOTREQD, UF_LOCKOUT, UF_PASSWORD_EXPIRED, ATYPE_NORMAL_ACCOUNT,
37 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
38 GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP,
39 GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP, GTYPE_DISTRIBUTION_GLOBAL_GROUP,
40 GTYPE_DISTRIBUTION_UNIVERSAL_GROUP,
41 ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_UNIVERSAL_GROUP,
42 ATYPE_SECURITY_LOCAL_GROUP, ATYPE_DISTRIBUTION_GLOBAL_GROUP,
43 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP, ATYPE_DISTRIBUTION_LOCAL_GROUP,
44 ATYPE_WORKSTATION_TRUST)
45 from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_ADMINS,
46 DOMAIN_RID_DOMAIN_MEMBERS, DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS)
48 from samba.ndr import ndr_unpack
49 from samba.dcerpc import drsblobs
50 from samba.dcerpc import drsuapi
51 from samba.dcerpc import security
52 from samba.tests import delete_force
53 from samba import gensec
54 from samba import werror
56 parser = optparse.OptionParser("sam.py [options] <host>")
57 sambaopts = options.SambaOptions(parser)
58 parser.add_option_group(sambaopts)
59 parser.add_option_group(options.VersionOptions(parser))
60 # use command line creds if available
61 credopts = options.CredentialsOptions(parser)
62 parser.add_option_group(credopts)
63 subunitopts = SubunitOptions(parser)
64 parser.add_option_group(subunitopts)
65 opts, args = parser.parse_args()
73 lp = sambaopts.get_loadparm()
74 creds = credopts.get_credentials(lp)
75 creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
78 class SamTests(samba.tests.TestCase):
81 super(SamTests, self).setUp()
83 self.base_dn = ldb.domain_dn()
85 print("baseDN: %s\n" % self.base_dn)
87 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
88 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
89 delete_force(self.ldb, "cn=ldaptest\,specialuser,cn=users," + self.base_dn)
90 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
91 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
92 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
94 def test_users_groups(self):
95 """This tests the SAM users and groups behaviour"""
96 print("Testing users and groups behaviour\n")
99 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
100 "objectclass": "group"})
103 "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
104 "objectclass": "group"})
106 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
107 scope=SCOPE_BASE, attrs=["objectSID"])
108 self.assertTrue(len(res1) == 1)
109 group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
110 res1[0]["objectSID"][0])).split()[1]
112 res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
113 scope=SCOPE_BASE, attrs=["objectSID"])
114 self.assertTrue(len(res1) == 1)
115 group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
116 res1[0]["objectSID"][0])).split()[1]
118 # Try to create a user with an invalid account name
121 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
122 "objectclass": "user",
123 "sAMAccountName": "administrator"})
125 except LdbError as e9:
127 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
128 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
130 # Try to create a user with an invalid account name
133 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
134 "objectclass": "user",
135 "sAMAccountName": []})
137 except LdbError as e10:
139 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
140 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
142 # Try to create a user with an invalid primary group
145 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
146 "objectclass": "user",
147 "primaryGroupID": "0"})
149 except LdbError as e11:
151 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
152 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
154 # Try to Create a user with a valid primary group
157 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
158 "objectclass": "user",
159 "primaryGroupID": str(group_rid_1)})
161 except LdbError as e12:
163 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
164 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
166 # Test to see how we should behave when the user account doesn't
169 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
170 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
175 except LdbError as e13:
177 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
179 # Test to see how we should behave when the account isn't a user
181 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
182 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
187 except LdbError as e14:
189 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
191 # Test default primary groups on add operations
194 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
195 "objectclass": "user"})
197 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
198 scope=SCOPE_BASE, attrs=["primaryGroupID"])
199 self.assertTrue(len(res1) == 1)
200 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
202 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
205 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
206 "objectclass": "user",
207 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
209 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
210 scope=SCOPE_BASE, attrs=["primaryGroupID"])
211 self.assertTrue(len(res1) == 1)
212 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
214 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
216 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
217 # since such accounts aren't directly creatable (ACCESS_DENIED)
220 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
221 "objectclass": "computer",
222 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD)})
224 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
225 scope=SCOPE_BASE, attrs=["primaryGroupID"])
226 self.assertTrue(len(res1) == 1)
227 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
229 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
232 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
233 "objectclass": "computer",
234 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD)})
236 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
237 scope=SCOPE_BASE, attrs=["primaryGroupID"])
238 self.assertTrue(len(res1) == 1)
239 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
241 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
243 # Read-only DC accounts are only creatable by
244 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
245 # we have a fallback in the assertion)
247 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
248 "objectclass": "computer",
249 "userAccountControl": str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD)})
251 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
252 scope=SCOPE_BASE, attrs=["primaryGroupID"])
253 self.assertTrue(len(res1) == 1)
254 self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
255 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
257 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
259 # Test default primary groups on modify operations
262 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
263 "objectclass": "user"})
266 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
267 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
268 "userAccountControl")
271 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
272 scope=SCOPE_BASE, attrs=["primaryGroupID"])
273 self.assertTrue(len(res1) == 1)
274 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
276 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
277 # since such accounts aren't directly creatable (ACCESS_DENIED)
279 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
282 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
283 "objectclass": "computer"})
285 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
286 scope=SCOPE_BASE, attrs=["primaryGroupID"])
287 self.assertTrue(len(res1) == 1)
288 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
291 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
292 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
293 "userAccountControl")
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(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
302 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
303 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
304 "userAccountControl")
307 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
308 scope=SCOPE_BASE, attrs=["primaryGroupID"])
309 self.assertTrue(len(res1) == 1)
310 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
312 # Read-only DC accounts are only creatable by
313 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
314 # we have a fallback in the assertion)
316 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
317 m["userAccountControl"] = MessageElement(str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
318 "userAccountControl")
321 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
322 scope=SCOPE_BASE, attrs=["primaryGroupID"])
323 self.assertTrue(len(res1) == 1)
324 self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
325 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
327 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
329 # Recreate account for further tests
332 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
333 "objectclass": "user"})
335 # Try to set an invalid account name
337 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
338 m["sAMAccountName"] = MessageElement("administrator", FLAG_MOD_REPLACE,
343 except LdbError as e15:
345 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
347 # But to reset the actual "sAMAccountName" should still be possible
348 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
349 scope=SCOPE_BASE, attrs=["sAMAccountName"])
350 self.assertTrue(len(res1) == 1)
352 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
353 m["sAMAccountName"] = MessageElement(res1[0]["sAMAccountName"][0], FLAG_MOD_REPLACE,
357 # And another (free) name should be possible as well
359 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
360 m["sAMAccountName"] = MessageElement("xxx_ldaptestuser_xxx", FLAG_MOD_REPLACE,
364 # We should be able to reset our actual primary group
366 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
367 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS), FLAG_MOD_REPLACE,
371 # Try to add invalid primary group
373 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
374 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
379 except LdbError as e16:
381 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
383 # Try to make group 1 primary - should be denied since it is not yet
386 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
387 m["primaryGroupID"] = MessageElement(str(group_rid_1),
388 FLAG_MOD_REPLACE, "primaryGroupID")
392 except LdbError as e17:
394 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
396 # Make group 1 secondary
398 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
399 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
400 FLAG_MOD_REPLACE, "member")
403 # Make group 1 primary
405 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
406 m["primaryGroupID"] = MessageElement(str(group_rid_1),
407 FLAG_MOD_REPLACE, "primaryGroupID")
410 # Try to delete group 1 - should be denied
412 ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
414 except LdbError as e18:
416 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
418 # Try to add group 1 also as secondary - should be denied
420 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
421 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
422 FLAG_MOD_ADD, "member")
426 except LdbError as e19:
428 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
430 # Try to add invalid member to group 1 - should be denied
432 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
433 m["member"] = MessageElement(
434 "cn=ldaptestuser3,cn=users," + self.base_dn,
435 FLAG_MOD_ADD, "member")
439 except LdbError as e20:
441 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
443 # Make group 2 secondary
445 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
446 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
447 FLAG_MOD_ADD, "member")
452 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
453 m["primaryGroupID"] = MessageElement(str(group_rid_2),
454 FLAG_MOD_REPLACE, "primaryGroupID")
457 # Swap the groups (does not really make sense but does the same)
459 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
460 m["primaryGroupID"] = MessageElement(str(group_rid_1),
461 FLAG_MOD_REPLACE, "primaryGroupID")
462 m["primaryGroupID"] = MessageElement(str(group_rid_2),
463 FLAG_MOD_REPLACE, "primaryGroupID")
466 # Old primary group should contain a "member" attribute for the user,
467 # the new shouldn't contain anymore one
468 res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
469 scope=SCOPE_BASE, attrs=["member"])
470 self.assertTrue(len(res1) == 1)
471 self.assertTrue(len(res1[0]["member"]) == 1)
472 self.assertEquals(res1[0]["member"][0].lower(),
473 ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
475 res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
476 scope=SCOPE_BASE, attrs=["member"])
477 self.assertTrue(len(res1) == 1)
478 self.assertFalse("member" in res1[0])
480 # Primary group member
482 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
483 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
484 FLAG_MOD_DELETE, "member")
488 except LdbError as e21:
490 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
492 # Delete invalid group member
494 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
495 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
496 FLAG_MOD_DELETE, "member")
500 except LdbError as e22:
502 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
504 # Also this should be denied
507 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
508 "objectclass": "user",
509 "primaryGroupID": "0"})
511 except LdbError as e23:
513 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
515 # Recreate user accounts
517 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
520 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
521 "objectclass": "user"})
524 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
525 "objectclass": "user"})
528 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
529 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
530 FLAG_MOD_ADD, "member")
535 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
536 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
537 FLAG_MOD_ADD, "member")
541 except LdbError as e24:
543 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
545 # Already added, but as <SID=...>
546 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
547 scope=SCOPE_BASE, attrs=["objectSid"])
548 self.assertTrue(len(res1) == 1)
549 sid_bin = res1[0]["objectSid"][0]
550 sid_str = ("<SID=" + ldb.schema_format_value("objectSid", sid_bin) + ">").upper()
553 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
554 m["member"] = MessageElement(sid_str, FLAG_MOD_ADD, "member")
558 except LdbError as e25:
560 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
564 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
565 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
566 FLAG_MOD_REPLACE, "member")
570 except LdbError as e26:
572 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
576 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
577 m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
578 "cn=ldaptestuser1,cn=users," + self.base_dn],
579 FLAG_MOD_REPLACE, "member")
583 except LdbError as e27:
585 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
589 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
590 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
591 FLAG_MOD_REPLACE, "member")
592 m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
593 FLAG_MOD_ADD, "member")
597 except LdbError as e28:
599 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
602 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
603 m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
604 "cn=ldaptestuser2,cn=users," + self.base_dn],
605 FLAG_MOD_REPLACE, "member")
608 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
609 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
610 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
611 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
613 # Make also a small test for accounts with special DNs ("," in this case)
615 "dn": "cn=ldaptest\,specialuser,cn=users," + self.base_dn,
616 "objectclass": "user"})
617 delete_force(self.ldb, "cn=ldaptest\,specialuser,cn=users," + self.base_dn)
619 def test_sam_attributes(self):
620 """Test the behaviour of special attributes of SAM objects"""
621 print("Testing the behaviour of special attributes of SAM objects\n")
624 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
625 "objectclass": "user"})
627 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
628 "objectclass": "group"})
631 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
632 m["groupType"] = MessageElement(str(GTYPE_SECURITY_GLOBAL_GROUP), FLAG_MOD_ADD,
637 except LdbError as e29:
639 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
641 # Delete protection tests
643 for attr in ["nTSecurityDescriptor", "objectSid", "sAMAccountType",
644 "sAMAccountName", "groupType"]:
647 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
648 m[attr] = MessageElement([], FLAG_MOD_REPLACE, attr)
652 except LdbError as e:
654 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
657 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
658 m[attr] = MessageElement([], FLAG_MOD_DELETE, attr)
662 except LdbError as e1:
664 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
667 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
668 m["primaryGroupID"] = MessageElement("513", FLAG_MOD_ADD,
673 except LdbError as e30:
675 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
678 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
679 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_ADD,
680 "userAccountControl")
684 except LdbError as e31:
686 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
689 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
690 m["objectSid"] = MessageElement("xxxxxxxxxxxxxxxx", FLAG_MOD_ADD,
695 except LdbError as e32:
697 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
700 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
701 m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
706 except LdbError as e33:
708 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
711 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
712 m["sAMAccountName"] = MessageElement("test", FLAG_MOD_ADD,
717 except LdbError as e34:
719 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
721 # Delete protection tests
723 for attr in ["nTSecurityDescriptor", "objectSid", "sAMAccountType",
724 "sAMAccountName", "primaryGroupID", "userAccountControl",
725 "accountExpires", "badPasswordTime", "badPwdCount",
726 "codePage", "countryCode", "lastLogoff", "lastLogon",
727 "logonCount", "pwdLastSet"]:
730 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
731 m[attr] = MessageElement([], FLAG_MOD_REPLACE, attr)
735 except LdbError as e2:
737 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
740 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
741 m[attr] = MessageElement([], FLAG_MOD_DELETE, attr)
745 except LdbError as e3:
747 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
749 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
750 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
752 def test_primary_group_token_constructed(self):
753 """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
754 print("Testing primary group token behaviour and other constructed attributes\n")
758 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
759 "objectclass": "group",
760 "primaryGroupToken": "100"})
762 except LdbError as e35:
764 self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
765 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
768 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
769 "objectclass": "user"})
772 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
773 "objectclass": "group"})
775 # Testing for one invalid, and one valid operational attribute, but also the things they are built from
776 res1 = ldb.search(self.base_dn,
777 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
778 self.assertTrue(len(res1) == 1)
779 self.assertFalse("primaryGroupToken" in res1[0])
780 self.assertTrue("canonicalName" in res1[0])
781 self.assertTrue("objectClass" in res1[0])
782 self.assertTrue("objectSid" in res1[0])
784 res1 = ldb.search(self.base_dn,
785 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
786 self.assertTrue(len(res1) == 1)
787 self.assertFalse("primaryGroupToken" in res1[0])
788 self.assertFalse("objectSid" in res1[0])
789 self.assertFalse("objectClass" in res1[0])
790 self.assertTrue("canonicalName" in res1[0])
792 res1 = ldb.search("cn=users," + self.base_dn,
793 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
794 self.assertTrue(len(res1) == 1)
795 self.assertFalse("primaryGroupToken" in res1[0])
797 res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
798 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
799 self.assertTrue(len(res1) == 1)
800 self.assertFalse("primaryGroupToken" in res1[0])
802 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
804 self.assertTrue(len(res1) == 1)
805 self.assertFalse("primaryGroupToken" in res1[0])
807 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
808 scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
809 self.assertTrue(len(res1) == 1)
810 primary_group_token = int(res1[0]["primaryGroupToken"][0])
812 rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
813 self.assertEquals(primary_group_token, rid)
816 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
817 m["primaryGroupToken"] = "100"
821 except LdbError as e36:
823 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
825 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
826 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
828 def test_tokenGroups(self):
829 """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
830 print("Testing tokenGroups behaviour\n")
832 # The domain object shouldn't contain any "tokenGroups" entry
833 res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
834 self.assertTrue(len(res) == 1)
835 self.assertFalse("tokenGroups" in res[0])
837 # The domain administrator should contain "tokenGroups" entries
838 # (the exact number depends on the domain/forest function level and the
839 # DC software versions)
840 res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
841 scope=SCOPE_BASE, attrs=["tokenGroups"])
842 self.assertTrue(len(res) == 1)
843 self.assertTrue("tokenGroups" in res[0])
846 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
847 "objectclass": "user"})
849 # This testuser should contain at least two "tokenGroups" entries
850 # (exactly two on an unmodified "Domain Users" and "Users" group)
851 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
852 scope=SCOPE_BASE, attrs=["tokenGroups"])
853 self.assertTrue(len(res) == 1)
854 self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
856 # one entry which we need to find should point to domains "Domain Users"
857 # group and another entry should point to the builtin "Users"group
858 domain_users_group_found = False
859 users_group_found = False
860 for sid in res[0]["tokenGroups"]:
861 rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
863 domain_users_group_found = True
865 users_group_found = True
867 self.assertTrue(domain_users_group_found)
868 self.assertTrue(users_group_found)
870 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
872 def test_groupType(self):
873 """Test the groupType behaviour"""
874 print("Testing groupType behaviour\n")
876 # You can never create or change to a
877 # "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP"
884 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
885 "objectclass": "group",
888 except LdbError as e37:
890 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
891 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
895 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
896 "objectclass": "group",
897 "groupType": str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP)})
899 except LdbError as e38:
901 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
902 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
905 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
906 "objectclass": "group",
907 "groupType": str(GTYPE_SECURITY_GLOBAL_GROUP)})
909 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
910 scope=SCOPE_BASE, attrs=["sAMAccountType"])
911 self.assertTrue(len(res1) == 1)
912 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
913 ATYPE_SECURITY_GLOBAL_GROUP)
914 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_UNIVERSAL_GROUP)})
921 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
922 scope=SCOPE_BASE, attrs=["sAMAccountType"])
923 self.assertTrue(len(res1) == 1)
924 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
925 ATYPE_SECURITY_UNIVERSAL_GROUP)
926 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
929 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
930 "objectclass": "group",
931 "groupType": str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP)})
933 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
934 scope=SCOPE_BASE, attrs=["sAMAccountType"])
935 self.assertTrue(len(res1) == 1)
936 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
937 ATYPE_SECURITY_LOCAL_GROUP)
938 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
941 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
942 "objectclass": "group",
943 "groupType": str(GTYPE_DISTRIBUTION_GLOBAL_GROUP)})
945 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
946 scope=SCOPE_BASE, attrs=["sAMAccountType"])
947 self.assertTrue(len(res1) == 1)
948 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
949 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
950 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
953 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
954 "objectclass": "group",
955 "groupType": str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP)})
957 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
958 scope=SCOPE_BASE, attrs=["sAMAccountType"])
959 self.assertTrue(len(res1) == 1)
960 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
961 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
962 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
965 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
966 "objectclass": "group",
967 "groupType": str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)})
969 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
970 scope=SCOPE_BASE, attrs=["sAMAccountType"])
971 self.assertTrue(len(res1) == 1)
972 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
973 ATYPE_DISTRIBUTION_LOCAL_GROUP)
974 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
979 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
980 "objectclass": "group"})
982 # We can change in this direction: global <-> universal <-> local
983 # On each step also the group type itself (security/distribution) is
986 # After creation we should have a "security global group"
987 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
988 scope=SCOPE_BASE, attrs=["sAMAccountType"])
989 self.assertTrue(len(res1) == 1)
990 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
991 ATYPE_SECURITY_GLOBAL_GROUP)
996 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
997 m["groupType"] = MessageElement("0",
998 FLAG_MOD_REPLACE, "groupType")
1001 except LdbError as e39:
1003 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1007 # Default is "global group"
1010 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1011 m["groupType"] = MessageElement(
1012 str(GTYPE_SECURITY_GLOBAL_GROUP),
1013 FLAG_MOD_REPLACE, "groupType")
1016 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1017 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1018 self.assertTrue(len(res1) == 1)
1019 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1020 ATYPE_SECURITY_GLOBAL_GROUP)
1022 # Change to "local" (shouldn't work)
1026 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1027 m["groupType"] = MessageElement(
1028 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1029 FLAG_MOD_REPLACE, "groupType")
1032 except LdbError as e40:
1034 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1036 # Change to "universal"
1039 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1040 m["groupType"] = MessageElement(
1041 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1042 FLAG_MOD_REPLACE, "groupType")
1045 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1046 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1047 self.assertTrue(len(res1) == 1)
1048 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1049 ATYPE_SECURITY_UNIVERSAL_GROUP)
1051 # Change back to "global"
1054 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1055 m["groupType"] = MessageElement(
1056 str(GTYPE_SECURITY_GLOBAL_GROUP),
1057 FLAG_MOD_REPLACE, "groupType")
1060 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1061 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1062 self.assertTrue(len(res1) == 1)
1063 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1064 ATYPE_SECURITY_GLOBAL_GROUP)
1066 # Change back to "universal"
1069 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1070 m["groupType"] = MessageElement(
1071 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1072 FLAG_MOD_REPLACE, "groupType")
1075 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1076 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1077 self.assertTrue(len(res1) == 1)
1078 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1079 ATYPE_SECURITY_UNIVERSAL_GROUP)
1084 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1085 m["groupType"] = MessageElement(
1086 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
1087 FLAG_MOD_REPLACE, "groupType")
1090 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1091 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1092 self.assertTrue(len(res1) == 1)
1093 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1094 ATYPE_SECURITY_LOCAL_GROUP)
1096 # Change to "global" (shouldn't work)
1100 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1101 m["groupType"] = MessageElement(
1102 str(GTYPE_SECURITY_GLOBAL_GROUP),
1103 FLAG_MOD_REPLACE, "groupType")
1106 except LdbError as e41:
1108 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1110 # Change to "builtin local" (shouldn't work)
1114 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1115 m["groupType"] = MessageElement(
1116 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1117 FLAG_MOD_REPLACE, "groupType")
1120 except LdbError as e42:
1122 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1125 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1127 # Change back to "universal"
1130 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1131 m["groupType"] = MessageElement(
1132 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1133 FLAG_MOD_REPLACE, "groupType")
1136 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1137 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1138 self.assertTrue(len(res1) == 1)
1139 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1140 ATYPE_SECURITY_UNIVERSAL_GROUP)
1142 # Change to "builtin local" (shouldn't work)
1146 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1147 m["groupType"] = MessageElement(
1148 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1149 FLAG_MOD_REPLACE, "groupType")
1152 except LdbError as e43:
1154 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1156 # Change back to "global"
1159 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1160 m["groupType"] = MessageElement(
1161 str(GTYPE_SECURITY_GLOBAL_GROUP),
1162 FLAG_MOD_REPLACE, "groupType")
1165 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1166 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1167 self.assertTrue(len(res1) == 1)
1168 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1169 ATYPE_SECURITY_GLOBAL_GROUP)
1171 # Change to "builtin local" (shouldn't work)
1175 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1176 m["groupType"] = MessageElement(
1177 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
1178 FLAG_MOD_REPLACE, "groupType")
1181 except LdbError as e44:
1183 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1185 # Distribution groups
1187 # Default is "global group"
1190 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1191 m["groupType"] = MessageElement(
1192 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1193 FLAG_MOD_REPLACE, "groupType")
1196 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1197 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1198 self.assertTrue(len(res1) == 1)
1199 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1200 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1202 # Change to local (shouldn't work)
1206 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1207 m["groupType"] = MessageElement(
1208 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1209 FLAG_MOD_REPLACE, "groupType")
1212 except LdbError as e45:
1214 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1216 # Change to "universal"
1219 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1220 m["groupType"] = MessageElement(
1221 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1222 FLAG_MOD_REPLACE, "groupType")
1225 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1226 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1227 self.assertTrue(len(res1) == 1)
1228 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1229 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1231 # Change back to "global"
1234 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1235 m["groupType"] = MessageElement(
1236 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1237 FLAG_MOD_REPLACE, "groupType")
1240 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1241 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1242 self.assertTrue(len(res1) == 1)
1243 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1244 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1246 # Change back to "universal"
1249 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1250 m["groupType"] = MessageElement(
1251 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1252 FLAG_MOD_REPLACE, "groupType")
1255 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1256 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1257 self.assertTrue(len(res1) == 1)
1258 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1259 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1264 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1265 m["groupType"] = MessageElement(
1266 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1267 FLAG_MOD_REPLACE, "groupType")
1270 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1271 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1272 self.assertTrue(len(res1) == 1)
1273 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1274 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1276 # Change to "global" (shouldn't work)
1280 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1281 m["groupType"] = MessageElement(
1282 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1283 FLAG_MOD_REPLACE, "groupType")
1286 except LdbError as e46:
1288 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1290 # Change back to "universal"
1292 # Try to add invalid member to group 1 - should be denied
1294 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1295 m["member"] = MessageElement(
1296 "cn=ldaptestuser3,cn=users," + self.base_dn,
1297 FLAG_MOD_ADD, "member")
1301 except LdbError as e47:
1303 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1305 # Make group 2 secondary
1307 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1308 m["groupType"] = MessageElement(
1309 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1310 FLAG_MOD_REPLACE, "groupType")
1313 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1314 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1315 self.assertTrue(len(res1) == 1)
1316 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1317 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1319 # Change back to "global"
1322 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1323 m["groupType"] = MessageElement(
1324 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1325 FLAG_MOD_REPLACE, "groupType")
1328 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1329 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1330 self.assertTrue(len(res1) == 1)
1331 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1332 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1334 # Both group types: this performs only random checks - all possibilities
1335 # would require too much code.
1337 # Default is "global group"
1340 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1341 m["groupType"] = MessageElement(
1342 str(GTYPE_SECURITY_GLOBAL_GROUP),
1343 FLAG_MOD_REPLACE, "groupType")
1346 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1347 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1348 self.assertTrue(len(res1) == 1)
1349 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1350 ATYPE_SECURITY_GLOBAL_GROUP)
1352 # Change to "local" (shouldn't work)
1356 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1357 m["groupType"] = MessageElement(
1358 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1359 FLAG_MOD_REPLACE, "groupType")
1362 except LdbError as e48:
1364 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1366 # Change to "universal"
1369 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1370 m["groupType"] = MessageElement(
1371 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1372 FLAG_MOD_REPLACE, "groupType")
1375 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1376 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1377 self.assertTrue(len(res1) == 1)
1378 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1379 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1381 # Change back to "global"
1384 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1385 m["groupType"] = MessageElement(
1386 str(GTYPE_SECURITY_GLOBAL_GROUP),
1387 FLAG_MOD_REPLACE, "groupType")
1390 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1391 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1392 self.assertTrue(len(res1) == 1)
1393 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1394 ATYPE_SECURITY_GLOBAL_GROUP)
1396 # Change back to "universal"
1399 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1400 m["groupType"] = MessageElement(
1401 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1402 FLAG_MOD_REPLACE, "groupType")
1405 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1406 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1407 self.assertTrue(len(res1) == 1)
1408 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1409 ATYPE_SECURITY_UNIVERSAL_GROUP)
1414 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1415 m["groupType"] = MessageElement(
1416 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1417 FLAG_MOD_REPLACE, "groupType")
1420 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1421 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1422 self.assertTrue(len(res1) == 1)
1423 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1424 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1426 # Change to "global" (shouldn't work)
1430 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1431 m["groupType"] = MessageElement(
1432 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1433 FLAG_MOD_REPLACE, "groupType")
1436 except LdbError as e49:
1438 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1440 # Change back to "universal"
1443 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1444 m["groupType"] = MessageElement(
1445 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1446 FLAG_MOD_REPLACE, "groupType")
1449 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1450 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1451 self.assertTrue(len(res1) == 1)
1452 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1453 ATYPE_SECURITY_UNIVERSAL_GROUP)
1455 # Change back to "global"
1458 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1459 m["groupType"] = MessageElement(
1460 str(GTYPE_SECURITY_GLOBAL_GROUP),
1461 FLAG_MOD_REPLACE, "groupType")
1464 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1465 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1466 self.assertTrue(len(res1) == 1)
1467 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1468 ATYPE_SECURITY_GLOBAL_GROUP)
1470 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1472 def test_pwdLastSet(self):
1473 """Test the pwdLastSet behaviour"""
1474 print("Testing pwdLastSet behaviour\n")
1477 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1478 "objectclass": "user",
1481 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1483 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1484 self.assertTrue(len(res1) == 1)
1485 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1486 ATYPE_NORMAL_ACCOUNT)
1487 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1488 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1489 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1490 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1493 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1494 "objectclass": "user",
1495 "pwdLastSet": "-1"})
1497 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1499 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1500 self.assertTrue(len(res1) == 1)
1501 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1502 ATYPE_NORMAL_ACCOUNT)
1503 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1504 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1505 self.assertNotEqual(int(res1[0]["pwdLastSet"][0]), 0)
1506 lastset = int(res1[0]["pwdLastSet"][0])
1507 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1511 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1512 "objectclass": "user",
1513 "pwdLastSet": str(1)})
1515 except LdbError as e50:
1516 (num, msg) = e50.args
1517 self.assertEquals(num, ERR_OTHER)
1518 self.assertTrue('00000057' in msg)
1522 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1523 "objectclass": "user",
1524 "pwdLastSet": str(lastset)})
1526 except LdbError as e51:
1527 (num, msg) = e51.args
1528 self.assertEquals(num, ERR_OTHER)
1529 self.assertTrue('00000057' in msg)
1532 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1533 "objectclass": "user"})
1535 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1537 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1538 self.assertTrue(len(res1) == 1)
1539 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1540 ATYPE_NORMAL_ACCOUNT)
1541 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1542 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1543 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1546 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1547 m["pls1"] = MessageElement(str(0),
1553 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1554 m["pls1"] = MessageElement(str(0),
1557 m["pls2"] = MessageElement(str(0),
1563 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1564 m["pls1"] = MessageElement(str(-1),
1568 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1570 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1571 self.assertTrue(len(res1) == 1)
1572 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1573 ATYPE_NORMAL_ACCOUNT)
1574 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1575 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1576 self.assertGreater(int(res1[0]["pwdLastSet"][0]), lastset)
1577 lastset = int(res1[0]["pwdLastSet"][0])
1581 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1582 m["pls1"] = MessageElement(str(0),
1585 m["pls2"] = MessageElement(str(0),
1590 except LdbError as e52:
1591 (num, msg) = e52.args
1592 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
1593 self.assertTrue('00002085' in msg)
1597 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1598 m["pls1"] = MessageElement(str(-1),
1601 m["pls2"] = MessageElement(str(0),
1606 except LdbError as e53:
1607 (num, msg) = e53.args
1608 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
1609 self.assertTrue('00002085' in msg)
1612 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1613 m["pls1"] = MessageElement(str(lastset),
1616 m["pls2"] = MessageElement(str(-1),
1621 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1623 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1624 self.assertTrue(len(res1) == 1)
1625 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1626 ATYPE_NORMAL_ACCOUNT)
1627 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1628 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1629 self.assertEqual(int(res1[0]["pwdLastSet"][0]), lastset)
1633 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1634 m["pls1"] = MessageElement(str(lastset),
1637 m["pls2"] = MessageElement(str(lastset),
1642 except LdbError as e54:
1643 (num, msg) = e54.args
1644 self.assertEquals(num, ERR_OTHER)
1645 self.assertTrue('00000057' in msg)
1648 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1649 m["pls1"] = MessageElement(str(lastset),
1652 m["pls2"] = MessageElement(str(0),
1656 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1658 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1659 self.assertTrue(len(res1) == 1)
1660 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1661 ATYPE_NORMAL_ACCOUNT)
1662 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1663 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1664 uac = int(res1[0]["userAccountControl"][0])
1665 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1668 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1669 m["uac1"] = MessageElement(str(uac |UF_PASSWORD_EXPIRED),
1671 "userAccountControl")
1673 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1675 attrs=["sAMAccountType", "userAccountControl", "pwdLastSet"])
1676 self.assertTrue(len(res1) == 1)
1677 self.assertEqual(int(res1[0]["sAMAccountType"][0]),
1678 ATYPE_NORMAL_ACCOUNT)
1679 self.assertEqual(int(res1[0]["userAccountControl"][0]),
1680 UF_NORMAL_ACCOUNT | UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD)
1681 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1683 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1685 def test_ldap_bind_must_change_pwd(self):
1686 """Test the error messages for failing LDAP binds"""
1687 print("Test the error messages for failing LDAP binds\n")
1689 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1691 def format_error_msg(hresult_v, dsid_v, werror_v):
1693 # There are 4 lower case hex digits following 'v' at the end,
1694 # but different Windows Versions return different values:
1696 # Windows 2008R2 uses 'v1db1'
1697 # Windows 2012R2 uses 'v2580'
1699 return "%08X: LdapErr: DSID-%08X, comment: AcceptSecurityContext error, data %x, v" % (
1700 hresult_v, dsid_v, werror_v)
1702 HRES_SEC_E_LOGON_DENIED = 0x8009030C
1703 HRES_SEC_E_INVALID_TOKEN = 0x80090308
1705 sasl_bind_dsid = 0x0C0904DC
1706 simple_bind_dsid = 0x0C0903A9
1708 error_msg_sasl_wrong_pw = format_error_msg(
1709 HRES_SEC_E_LOGON_DENIED,
1711 werror.WERR_LOGON_FAILURE)
1712 error_msg_sasl_must_change = format_error_msg(
1713 HRES_SEC_E_LOGON_DENIED,
1715 werror.WERR_PASSWORD_MUST_CHANGE)
1716 error_msg_simple_wrong_pw = format_error_msg(
1717 HRES_SEC_E_INVALID_TOKEN,
1719 werror.WERR_LOGON_FAILURE)
1720 error_msg_simple_must_change = format_error_msg(
1721 HRES_SEC_E_INVALID_TOKEN,
1723 werror.WERR_PASSWORD_MUST_CHANGE)
1725 username = "ldaptestuser"
1726 password = "thatsAcomplPASS2"
1727 utf16pw = unicode('"' + password.encode('utf-8') + '"', 'utf-8').encode('utf-16-le')
1730 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1731 "objectclass": "user",
1732 "sAMAccountName": username,
1733 "userAccountControl": str(UF_NORMAL_ACCOUNT),
1734 "unicodePwd": utf16pw,
1737 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1739 attrs=["sAMAccountName", "sAMAccountType", "userAccountControl", "pwdLastSet"])
1740 self.assertTrue(len(res1) == 1)
1741 self.assertEqual(res1[0]["sAMAccountName"][0], username)
1742 self.assertEqual(int(res1[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1743 self.assertEqual(int(res1[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT)
1744 self.assertNotEqual(int(res1[0]["pwdLastSet"][0]), 0)
1746 # Open a second LDB connection with the user credentials. Use the
1747 # command line credentials for informations like the domain, the realm
1748 # and the workstation.
1749 sasl_creds = Credentials()
1750 sasl_creds.set_username(username)
1751 sasl_creds.set_password(password)
1752 sasl_creds.set_domain(creds.get_domain())
1753 sasl_creds.set_workstation(creds.get_workstation())
1754 sasl_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1755 sasl_creds.set_kerberos_state(DONT_USE_KERBEROS)
1757 sasl_wrong_creds = Credentials()
1758 sasl_wrong_creds.set_username(username)
1759 sasl_wrong_creds.set_password("wrong")
1760 sasl_wrong_creds.set_domain(creds.get_domain())
1761 sasl_wrong_creds.set_workstation(creds.get_workstation())
1762 sasl_wrong_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1763 sasl_wrong_creds.set_kerberos_state(DONT_USE_KERBEROS)
1765 simple_creds = Credentials()
1766 simple_creds.set_bind_dn("cn=ldaptestuser,cn=users," + self.base_dn)
1767 simple_creds.set_username(username)
1768 simple_creds.set_password(password)
1769 simple_creds.set_domain(creds.get_domain())
1770 simple_creds.set_workstation(creds.get_workstation())
1771 simple_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1772 simple_creds.set_kerberos_state(DONT_USE_KERBEROS)
1774 simple_wrong_creds = Credentials()
1775 simple_wrong_creds.set_bind_dn("cn=ldaptestuser,cn=users," + self.base_dn)
1776 simple_wrong_creds.set_username(username)
1777 simple_wrong_creds.set_password("wrong")
1778 simple_wrong_creds.set_domain(creds.get_domain())
1779 simple_wrong_creds.set_workstation(creds.get_workstation())
1780 simple_wrong_creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
1781 simple_wrong_creds.set_kerberos_state(DONT_USE_KERBEROS)
1783 sasl_ldb = SamDB(url=host, credentials=sasl_creds, lp=lp)
1784 self.assertIsNotNone(sasl_ldb)
1787 requires_strong_auth = False
1789 simple_ldb = SamDB(url=host, credentials=simple_creds, lp=lp)
1790 self.assertIsNotNone(simple_ldb)
1792 except LdbError as e55:
1793 (num, msg) = e55.args
1794 if num != ERR_STRONG_AUTH_REQUIRED:
1796 requires_strong_auth = True
1798 def assertLDAPErrorMsg(msg, expected_msg):
1799 self.assertTrue(expected_msg in msg,
1800 "msg[%s] does not contain expected[%s]" % (
1804 ldb_fail = SamDB(url=host, credentials=sasl_wrong_creds, lp=lp)
1806 except LdbError as e56:
1807 (num, msg) = e56.args
1808 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1809 self.assertTrue(error_msg_sasl_wrong_pw in msg)
1811 if not requires_strong_auth:
1813 ldb_fail = SamDB(url=host, credentials=simple_wrong_creds, lp=lp)
1815 except LdbError as e4:
1816 (num, msg) = e4.args
1817 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1818 assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw)
1821 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1822 m["pls1"] = MessageElement(str(0),
1827 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1828 scope=SCOPE_BASE, attrs=["pwdLastSet"])
1829 self.assertEqual(int(res1[0]["pwdLastSet"][0]), 0)
1832 ldb_fail = SamDB(url=host, credentials=sasl_wrong_creds, lp=lp)
1834 except LdbError as e57:
1835 (num, msg) = e57.args
1836 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1837 assertLDAPErrorMsg(msg, error_msg_sasl_wrong_pw)
1840 ldb_fail = SamDB(url=host, credentials=sasl_creds, lp=lp)
1842 except LdbError as e58:
1843 (num, msg) = e58.args
1844 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1845 assertLDAPErrorMsg(msg, error_msg_sasl_must_change)
1847 if not requires_strong_auth:
1849 ldb_fail = SamDB(url=host, credentials=simple_wrong_creds, lp=lp)
1851 except LdbError as e5:
1852 (num, msg) = e5.args
1853 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1854 assertLDAPErrorMsg(msg, error_msg_simple_wrong_pw)
1857 ldb_fail = SamDB(url=host, credentials=simple_creds, lp=lp)
1859 except LdbError as e6:
1860 (num, msg) = e6.args
1861 self.assertEquals(num, ERR_INVALID_CREDENTIALS)
1862 assertLDAPErrorMsg(msg, error_msg_simple_must_change)
1864 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1866 def test_userAccountControl(self):
1867 """Test the userAccountControl behaviour"""
1868 print("Testing userAccountControl behaviour\n")
1870 # With a user object
1874 # As user you can only set a normal account.
1875 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1877 # With SYSTEM rights you can set a interdomain trust account.
1880 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1881 "objectclass": "user",
1882 "userAccountControl": "0"})
1884 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1886 attrs=["sAMAccountType", "userAccountControl"])
1887 self.assertTrue(len(res1) == 1)
1888 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1889 ATYPE_NORMAL_ACCOUNT)
1890 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
1891 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0)
1892 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1895 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1896 "objectclass": "user",
1897 "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1898 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1901 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1902 "objectclass": "user",
1903 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1905 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1907 attrs=["sAMAccountType", "userAccountControl"])
1908 self.assertTrue(len(res1) == 1)
1909 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1910 ATYPE_NORMAL_ACCOUNT)
1911 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
1912 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1915 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1916 "objectclass": "user",
1917 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_LOCKOUT | UF_PASSWORD_EXPIRED)})
1919 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1921 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
1922 self.assertTrue(len(res1) == 1)
1923 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1924 ATYPE_NORMAL_ACCOUNT)
1925 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
1926 self.assertFalse("lockoutTime" in res1[0])
1927 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
1928 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1932 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1933 "objectclass": "user",
1934 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1936 except LdbError as e59:
1938 self.assertEquals(num, ERR_OTHER)
1939 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1943 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1944 "objectclass": "user",
1945 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1947 except LdbError as e60:
1949 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1950 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1954 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1955 "objectclass": "user",
1956 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1957 except LdbError as e61:
1959 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1960 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1964 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1965 "objectclass": "user",
1966 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)})
1967 except LdbError as e62:
1969 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1970 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1974 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1975 "objectclass": "user",
1976 "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1978 except LdbError as e63:
1980 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1981 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1986 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1987 "objectclass": "user"})
1989 # After creation we should have a normal account
1990 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1992 attrs=["sAMAccountType", "userAccountControl"])
1993 self.assertTrue(len(res1) == 1)
1994 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1995 ATYPE_NORMAL_ACCOUNT)
1996 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
1998 # As user you can only switch from a normal account to a workstation
1999 # trust account and back.
2000 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2002 # With SYSTEM rights you can switch to a interdomain trust account.
2007 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2008 m["userAccountControl"] = MessageElement("0",
2009 FLAG_MOD_REPLACE, "userAccountControl")
2011 except LdbError as e64:
2013 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2017 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2018 m["userAccountControl"] = MessageElement(
2019 str(UF_NORMAL_ACCOUNT),
2020 FLAG_MOD_REPLACE, "userAccountControl")
2022 except LdbError as e65:
2024 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2027 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2028 m["userAccountControl"] = MessageElement(
2029 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2030 FLAG_MOD_REPLACE, "userAccountControl")
2033 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2035 attrs=["sAMAccountType", "userAccountControl"])
2036 self.assertTrue(len(res1) == 1)
2037 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2038 ATYPE_NORMAL_ACCOUNT)
2039 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2042 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2043 m["userAccountControl"] = MessageElement(
2044 str(UF_ACCOUNTDISABLE),
2045 FLAG_MOD_REPLACE, "userAccountControl")
2048 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2050 attrs=["sAMAccountType", "userAccountControl"])
2051 self.assertTrue(len(res1) == 1)
2052 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2053 ATYPE_NORMAL_ACCOUNT)
2054 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2055 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2058 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2059 m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
2060 m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
2064 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2065 m["userAccountControl"] = MessageElement(
2066 str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
2067 FLAG_MOD_REPLACE, "userAccountControl")
2070 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2072 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2073 self.assertTrue(len(res1) == 1)
2074 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2075 ATYPE_NORMAL_ACCOUNT)
2076 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2077 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2078 self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
2079 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2083 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2084 m["userAccountControl"] = MessageElement(
2085 str(UF_TEMP_DUPLICATE_ACCOUNT),
2086 FLAG_MOD_REPLACE, "userAccountControl")
2089 except LdbError as e66:
2091 self.assertEquals(num, ERR_OTHER)
2095 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2096 m["userAccountControl"] = MessageElement(
2097 str(UF_SERVER_TRUST_ACCOUNT),
2098 FLAG_MOD_REPLACE, "userAccountControl")
2101 except LdbError as e67:
2103 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2106 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2107 m["userAccountControl"] = MessageElement(
2108 str(UF_WORKSTATION_TRUST_ACCOUNT),
2109 FLAG_MOD_REPLACE, "userAccountControl")
2114 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2115 m["userAccountControl"] = MessageElement(
2116 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT),
2117 FLAG_MOD_REPLACE, "userAccountControl")
2120 except LdbError as e68:
2122 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2124 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2125 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2126 self.assertTrue(len(res1) == 1)
2127 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2128 ATYPE_WORKSTATION_TRUST)
2131 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2132 m["userAccountControl"] = MessageElement(
2133 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2134 FLAG_MOD_REPLACE, "userAccountControl")
2137 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2138 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2139 self.assertTrue(len(res1) == 1)
2140 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2141 ATYPE_NORMAL_ACCOUNT)
2145 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2146 m["userAccountControl"] = MessageElement(
2147 str(UF_INTERDOMAIN_TRUST_ACCOUNT),
2148 FLAG_MOD_REPLACE, "userAccountControl")
2151 except LdbError as e69:
2153 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2155 # With a computer object
2159 # As computer you can set a normal account and a server trust account.
2160 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2162 # With SYSTEM rights you can set a interdomain trust account.
2165 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2166 "objectclass": "computer",
2167 "userAccountControl": "0"})
2169 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2171 attrs=["sAMAccountType", "userAccountControl"])
2172 self.assertTrue(len(res1) == 1)
2173 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2174 ATYPE_NORMAL_ACCOUNT)
2175 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2176 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0)
2177 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2180 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2181 "objectclass": "computer",
2182 "userAccountControl": str(UF_NORMAL_ACCOUNT)})
2183 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2186 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2187 "objectclass": "computer",
2188 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
2190 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2192 attrs=["sAMAccountType", "userAccountControl"])
2193 self.assertTrue(len(res1) == 1)
2194 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2195 ATYPE_NORMAL_ACCOUNT)
2196 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2197 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2200 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2201 "objectclass": "computer",
2202 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_LOCKOUT | UF_PASSWORD_EXPIRED)})
2204 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2206 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2207 self.assertTrue(len(res1) == 1)
2208 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2209 ATYPE_NORMAL_ACCOUNT)
2210 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2211 self.assertFalse("lockoutTime" in res1[0])
2212 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2213 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2217 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2218 "objectclass": "computer",
2219 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
2221 except LdbError as e70:
2223 self.assertEquals(num, ERR_OTHER)
2224 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2227 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2228 "objectclass": "computer",
2229 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
2231 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2232 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2233 self.assertTrue(len(res1) == 1)
2234 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2235 ATYPE_WORKSTATION_TRUST)
2236 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2240 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2241 "objectclass": "computer",
2242 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
2243 except LdbError as e71:
2245 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
2246 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2250 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2251 "objectclass": "computer",
2252 "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
2254 except LdbError as e72:
2256 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2257 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2262 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2263 "objectclass": "computer"})
2265 # After creation we should have a normal account
2266 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2268 attrs=["sAMAccountType", "userAccountControl"])
2269 self.assertTrue(len(res1) == 1)
2270 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2271 ATYPE_NORMAL_ACCOUNT)
2272 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2274 # As computer you can switch from a normal account to a workstation
2275 # or server trust account and back (also swapping between trust
2276 # accounts is allowed).
2277 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
2279 # With SYSTEM rights you can switch to a interdomain trust account.
2284 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2285 m["userAccountControl"] = MessageElement("0",
2286 FLAG_MOD_REPLACE, "userAccountControl")
2288 except LdbError as e73:
2290 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2294 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2295 m["userAccountControl"] = MessageElement(
2296 str(UF_NORMAL_ACCOUNT),
2297 FLAG_MOD_REPLACE, "userAccountControl")
2299 except LdbError as e74:
2301 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2304 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2305 m["userAccountControl"] = MessageElement(
2306 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2307 FLAG_MOD_REPLACE, "userAccountControl")
2310 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2312 attrs=["sAMAccountType", "userAccountControl"])
2313 self.assertTrue(len(res1) == 1)
2314 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2315 ATYPE_NORMAL_ACCOUNT)
2316 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2319 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2320 m["userAccountControl"] = MessageElement(
2321 str(UF_ACCOUNTDISABLE),
2322 FLAG_MOD_REPLACE, "userAccountControl")
2325 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2327 attrs=["sAMAccountType", "userAccountControl"])
2328 self.assertTrue(len(res1) == 1)
2329 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2330 ATYPE_NORMAL_ACCOUNT)
2331 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2332 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
2335 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2336 m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
2337 m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
2341 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2342 m["userAccountControl"] = MessageElement(
2343 str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
2344 FLAG_MOD_REPLACE, "userAccountControl")
2347 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2349 attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
2350 self.assertTrue(len(res1) == 1)
2351 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2352 ATYPE_NORMAL_ACCOUNT)
2353 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
2354 self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
2355 self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
2356 self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
2360 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2361 m["userAccountControl"] = MessageElement(
2362 str(UF_TEMP_DUPLICATE_ACCOUNT),
2363 FLAG_MOD_REPLACE, "userAccountControl")
2366 except LdbError as e75:
2368 self.assertEquals(num, ERR_OTHER)
2371 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2372 m["userAccountControl"] = MessageElement(
2373 str(UF_SERVER_TRUST_ACCOUNT),
2374 FLAG_MOD_REPLACE, "userAccountControl")
2377 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2378 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2379 self.assertTrue(len(res1) == 1)
2380 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2381 ATYPE_WORKSTATION_TRUST)
2384 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2385 m["userAccountControl"] = MessageElement(
2386 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2387 FLAG_MOD_REPLACE, "userAccountControl")
2390 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2391 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2392 self.assertTrue(len(res1) == 1)
2393 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2394 ATYPE_NORMAL_ACCOUNT)
2397 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2398 m["userAccountControl"] = MessageElement(
2399 str(UF_WORKSTATION_TRUST_ACCOUNT),
2400 FLAG_MOD_REPLACE, "userAccountControl")
2403 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2404 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2405 self.assertTrue(len(res1) == 1)
2406 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2407 ATYPE_WORKSTATION_TRUST)
2410 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2411 m["userAccountControl"] = MessageElement(
2412 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2413 FLAG_MOD_REPLACE, "userAccountControl")
2416 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2417 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2418 self.assertTrue(len(res1) == 1)
2419 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2420 ATYPE_NORMAL_ACCOUNT)
2423 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2424 m["userAccountControl"] = MessageElement(
2425 str(UF_SERVER_TRUST_ACCOUNT),
2426 FLAG_MOD_REPLACE, "userAccountControl")
2429 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2430 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2431 self.assertTrue(len(res1) == 1)
2432 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2433 ATYPE_WORKSTATION_TRUST)
2436 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2437 m["userAccountControl"] = MessageElement(
2438 str(UF_WORKSTATION_TRUST_ACCOUNT),
2439 FLAG_MOD_REPLACE, "userAccountControl")
2442 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2443 scope=SCOPE_BASE, attrs=["sAMAccountType"])
2444 self.assertTrue(len(res1) == 1)
2445 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
2446 ATYPE_WORKSTATION_TRUST)
2450 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2451 m["userAccountControl"] = MessageElement(
2452 str(UF_INTERDOMAIN_TRUST_ACCOUNT),
2453 FLAG_MOD_REPLACE, "userAccountControl")
2456 except LdbError as e76:
2458 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2460 # "primaryGroupID" does not change if account type remains the same
2462 # For a user account
2465 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
2466 "objectclass": "user",
2467 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)})
2469 res1 = ldb.search("cn=ldaptestuser2,cn=users," + self.base_dn,
2471 attrs=["userAccountControl"])
2472 self.assertTrue(len(res1) == 1)
2473 self.assertEquals(int(res1[0]["userAccountControl"][0]),
2474 UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2477 m.dn = Dn(ldb, "<SID=" + ldb.get_domain_sid() + "-" + str(DOMAIN_RID_ADMINS) + ">")
2478 m["member"] = MessageElement(
2479 "cn=ldaptestuser2,cn=users," + self.base_dn, FLAG_MOD_ADD, "member")
2483 m.dn = Dn(ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2484 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_ADMINS),
2485 FLAG_MOD_REPLACE, "primaryGroupID")
2489 m.dn = Dn(ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2490 m["userAccountControl"] = MessageElement(
2491 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2492 FLAG_MOD_REPLACE, "userAccountControl")
2495 res1 = ldb.search("cn=ldaptestuser2,cn=users," + self.base_dn,
2497 attrs=["userAccountControl", "primaryGroupID"])
2498 self.assertTrue(len(res1) == 1)
2499 self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
2500 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_ADMINS)
2502 # For a workstation account
2504 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2506 attrs=["primaryGroupID"])
2507 self.assertTrue(len(res1) == 1)
2508 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS)
2511 m.dn = Dn(ldb, "<SID=" + ldb.get_domain_sid() + "-" + str(DOMAIN_RID_USERS) + ">")
2512 m["member"] = MessageElement(
2513 "cn=ldaptestcomputer,cn=computers," + self.base_dn, FLAG_MOD_ADD, "member")
2517 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2518 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS),
2519 FLAG_MOD_REPLACE, "primaryGroupID")
2523 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2524 m["userAccountControl"] = MessageElement(
2525 str(UF_WORKSTATION_TRUST_ACCOUNT),
2526 FLAG_MOD_REPLACE, "userAccountControl")
2529 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2531 attrs=["primaryGroupID"])
2532 self.assertTrue(len(res1) == 1)
2533 self.assertEquals(int(res1[0]["primaryGroupID"][0]), DOMAIN_RID_USERS)
2535 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2536 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2537 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2539 def find_repl_meta_data(self, rpmd, attid):
2540 for i in range(0, rpmd.ctr.count):
2541 m = rpmd.ctr.array[i]
2542 if m.attid == attid:
2546 def test_smartcard_required1(self):
2547 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2548 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2550 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2553 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2554 "objectclass": "user",
2555 "userAccountControl": str(UF_NORMAL_ACCOUNT),
2556 "unicodePwd": "\"thatsAcomplPASS2\"".encode('utf-16-le')
2559 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2561 attrs=["sAMAccountType", "userAccountControl",
2562 "pwdLastSet", "msDS-KeyVersionNumber",
2563 "replPropertyMetaData"])
2564 self.assertTrue(len(res) == 1)
2565 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2566 ATYPE_NORMAL_ACCOUNT)
2567 self.assertEqual(int(res[0]["userAccountControl"][0]),
2569 self.assertNotEqual(int(res[0]["pwdLastSet"][0]), 0)
2570 lastset = int(res[0]["pwdLastSet"][0])
2571 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2572 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2573 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2574 res[0]["replPropertyMetaData"][0])
2575 lastsetmd = self.find_repl_meta_data(rpmd,
2576 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2577 self.assertIsNotNone(lastsetmd)
2578 self.assertEqual(lastsetmd.version, 1)
2579 nthashmd = self.find_repl_meta_data(rpmd,
2580 drsuapi.DRSUAPI_ATTID_unicodePwd)
2581 self.assertIsNotNone(nthashmd)
2582 self.assertEqual(nthashmd.version, 1)
2583 nthistmd = self.find_repl_meta_data(rpmd,
2584 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2585 self.assertIsNotNone(nthistmd)
2586 self.assertEqual(nthistmd.version, 1)
2587 lmhashmd = self.find_repl_meta_data(rpmd,
2588 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2589 self.assertIsNotNone(lmhashmd)
2590 self.assertEqual(lmhashmd.version, 1)
2591 lmhistmd = self.find_repl_meta_data(rpmd,
2592 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2593 self.assertIsNotNone(lmhistmd)
2594 self.assertEqual(lmhistmd.version, 1)
2595 spcbmd = self.find_repl_meta_data(rpmd,
2596 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2597 self.assertIsNotNone(spcbmd)
2598 self.assertEqual(spcbmd.version, 1)
2601 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2602 m["userAccountControl"] = MessageElement(
2603 str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED),
2604 FLAG_MOD_REPLACE, "userAccountControl")
2607 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2609 attrs=["sAMAccountType", "userAccountControl",
2610 "pwdLastSet", "msDS-KeyVersionNumber",
2611 "replPropertyMetaData"])
2612 self.assertTrue(len(res) == 1)
2613 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2614 ATYPE_NORMAL_ACCOUNT)
2615 self.assertEqual(int(res[0]["userAccountControl"][0]),
2616 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED)
2617 self.assertEqual(int(res[0]["pwdLastSet"][0]), lastset)
2618 lastset1 = int(res[0]["pwdLastSet"][0])
2619 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2620 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2621 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2622 res[0]["replPropertyMetaData"][0])
2623 lastsetmd = self.find_repl_meta_data(rpmd,
2624 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2625 self.assertIsNotNone(lastsetmd)
2626 self.assertEqual(lastsetmd.version, 1)
2627 nthashmd = self.find_repl_meta_data(rpmd,
2628 drsuapi.DRSUAPI_ATTID_unicodePwd)
2629 self.assertIsNotNone(nthashmd)
2630 self.assertEqual(nthashmd.version, 2)
2631 nthistmd = self.find_repl_meta_data(rpmd,
2632 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2633 self.assertIsNotNone(nthistmd)
2634 self.assertEqual(nthistmd.version, 2)
2635 lmhashmd = self.find_repl_meta_data(rpmd,
2636 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2637 self.assertIsNotNone(lmhashmd)
2638 self.assertEqual(lmhashmd.version, 2)
2639 lmhistmd = self.find_repl_meta_data(rpmd,
2640 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2641 self.assertIsNotNone(lmhistmd)
2642 self.assertEqual(lmhistmd.version, 2)
2643 spcbmd = self.find_repl_meta_data(rpmd,
2644 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2645 self.assertIsNotNone(spcbmd)
2646 self.assertEqual(spcbmd.version, 2)
2648 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2650 def test_smartcard_required2(self):
2651 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2652 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2654 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2657 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2658 "objectclass": "user",
2659 "userAccountControl": str(UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE),
2662 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2664 attrs=["sAMAccountType", "userAccountControl",
2665 "pwdLastSet", "msDS-KeyVersionNumber",
2666 "replPropertyMetaData"])
2667 self.assertTrue(len(res) == 1)
2668 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2669 ATYPE_NORMAL_ACCOUNT)
2670 self.assertEqual(int(res[0]["userAccountControl"][0]),
2671 UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE)
2672 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2673 self.assertTrue("msDS-KeyVersionNumber" in res[0])
2674 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2675 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2676 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2677 res[0]["replPropertyMetaData"][0])
2678 lastsetmd = self.find_repl_meta_data(rpmd,
2679 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2680 self.assertIsNotNone(lastsetmd)
2681 self.assertEqual(lastsetmd.version, 1)
2682 nthashmd = self.find_repl_meta_data(rpmd,
2683 drsuapi.DRSUAPI_ATTID_unicodePwd)
2684 self.assertIsNotNone(nthashmd)
2685 self.assertEqual(nthashmd.version, 1)
2686 nthistmd = self.find_repl_meta_data(rpmd,
2687 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2688 self.assertIsNotNone(nthistmd)
2689 self.assertEqual(nthistmd.version, 1)
2690 lmhashmd = self.find_repl_meta_data(rpmd,
2691 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2692 self.assertIsNotNone(lmhashmd)
2693 self.assertEqual(lmhashmd.version, 1)
2694 lmhistmd = self.find_repl_meta_data(rpmd,
2695 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2696 self.assertIsNotNone(lmhistmd)
2697 self.assertEqual(lmhistmd.version, 1)
2698 spcbmd = self.find_repl_meta_data(rpmd,
2699 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2700 self.assertIsNone(spcbmd)
2703 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2704 m["userAccountControl"] = MessageElement(
2705 str(UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE |UF_SMARTCARD_REQUIRED),
2706 FLAG_MOD_REPLACE, "userAccountControl")
2709 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2711 attrs=["sAMAccountType", "userAccountControl",
2712 "pwdLastSet", "msDS-KeyVersionNumber",
2713 "replPropertyMetaData"])
2714 self.assertTrue(len(res) == 1)
2715 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2716 ATYPE_NORMAL_ACCOUNT)
2717 self.assertEqual(int(res[0]["userAccountControl"][0]),
2718 UF_NORMAL_ACCOUNT |UF_ACCOUNTDISABLE |UF_SMARTCARD_REQUIRED)
2719 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2720 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2721 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2722 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2723 res[0]["replPropertyMetaData"][0])
2724 lastsetmd = self.find_repl_meta_data(rpmd,
2725 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2726 self.assertIsNotNone(lastsetmd)
2727 self.assertEqual(lastsetmd.version, 1)
2728 nthashmd = self.find_repl_meta_data(rpmd,
2729 drsuapi.DRSUAPI_ATTID_unicodePwd)
2730 self.assertIsNotNone(nthashmd)
2731 self.assertEqual(nthashmd.version, 2)
2732 nthistmd = self.find_repl_meta_data(rpmd,
2733 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2734 self.assertIsNotNone(nthistmd)
2735 self.assertEqual(nthistmd.version, 2)
2736 lmhashmd = self.find_repl_meta_data(rpmd,
2737 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2738 self.assertIsNotNone(lmhashmd)
2739 self.assertEqual(lmhashmd.version, 2)
2740 lmhistmd = self.find_repl_meta_data(rpmd,
2741 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2742 self.assertIsNotNone(lmhistmd)
2743 self.assertEqual(lmhistmd.version, 2)
2744 spcbmd = self.find_repl_meta_data(rpmd,
2745 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2746 self.assertIsNotNone(spcbmd)
2747 self.assertEqual(spcbmd.version, 1)
2750 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2751 m["userAccountControl"] = MessageElement(
2752 str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED),
2753 FLAG_MOD_REPLACE, "userAccountControl")
2756 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2758 attrs=["sAMAccountType", "userAccountControl",
2759 "pwdLastSet", "msDS-KeyVersionNumber",
2760 "replPropertyMetaData"])
2761 self.assertTrue(len(res) == 1)
2762 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2763 ATYPE_NORMAL_ACCOUNT)
2764 self.assertEqual(int(res[0]["userAccountControl"][0]),
2765 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED)
2766 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2767 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 2)
2768 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2769 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2770 res[0]["replPropertyMetaData"][0])
2771 lastsetmd = self.find_repl_meta_data(rpmd,
2772 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2773 self.assertIsNotNone(lastsetmd)
2774 self.assertEqual(lastsetmd.version, 1)
2775 nthashmd = self.find_repl_meta_data(rpmd,
2776 drsuapi.DRSUAPI_ATTID_unicodePwd)
2777 self.assertIsNotNone(nthashmd)
2778 self.assertEqual(nthashmd.version, 2)
2779 nthistmd = self.find_repl_meta_data(rpmd,
2780 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2781 self.assertIsNotNone(nthistmd)
2782 self.assertEqual(nthistmd.version, 2)
2783 lmhashmd = self.find_repl_meta_data(rpmd,
2784 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2785 self.assertIsNotNone(lmhashmd)
2786 self.assertEqual(lmhashmd.version, 2)
2787 lmhistmd = self.find_repl_meta_data(rpmd,
2788 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2789 self.assertIsNotNone(lmhistmd)
2790 self.assertEqual(lmhistmd.version, 2)
2791 spcbmd = self.find_repl_meta_data(rpmd,
2792 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2793 self.assertIsNotNone(spcbmd)
2794 self.assertEqual(spcbmd.version, 1)
2796 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2798 def test_smartcard_required3(self):
2799 """Test the UF_SMARTCARD_REQUIRED behaviour"""
2800 print("Testing UF_SMARTCARD_REQUIRED behaviour\n")
2802 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2805 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
2806 "objectclass": "user",
2807 "userAccountControl": str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED |UF_ACCOUNTDISABLE),
2810 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2812 attrs=["sAMAccountType", "userAccountControl",
2813 "pwdLastSet", "msDS-KeyVersionNumber",
2814 "replPropertyMetaData"])
2815 self.assertTrue(len(res) == 1)
2816 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2817 ATYPE_NORMAL_ACCOUNT)
2818 self.assertEqual(int(res[0]["userAccountControl"][0]),
2819 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED |UF_ACCOUNTDISABLE)
2820 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2821 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2822 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2823 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2824 res[0]["replPropertyMetaData"][0])
2825 lastsetmd = self.find_repl_meta_data(rpmd,
2826 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2827 self.assertIsNotNone(lastsetmd)
2828 self.assertEqual(lastsetmd.version, 1)
2829 nthashmd = self.find_repl_meta_data(rpmd,
2830 drsuapi.DRSUAPI_ATTID_unicodePwd)
2831 self.assertIsNotNone(nthashmd)
2832 self.assertEqual(nthashmd.version, 1)
2833 nthistmd = self.find_repl_meta_data(rpmd,
2834 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2835 self.assertIsNotNone(nthistmd)
2836 self.assertEqual(nthistmd.version, 1)
2837 lmhashmd = self.find_repl_meta_data(rpmd,
2838 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2839 self.assertIsNotNone(lmhashmd)
2840 self.assertEqual(lmhashmd.version, 1)
2841 lmhistmd = self.find_repl_meta_data(rpmd,
2842 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2843 self.assertIsNotNone(lmhistmd)
2844 self.assertEqual(lmhistmd.version, 1)
2845 spcbmd = self.find_repl_meta_data(rpmd,
2846 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2847 self.assertIsNotNone(spcbmd)
2848 self.assertEqual(spcbmd.version, 1)
2851 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2852 m["userAccountControl"] = MessageElement(
2853 str(UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED),
2854 FLAG_MOD_REPLACE, "userAccountControl")
2857 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
2859 attrs=["sAMAccountType", "userAccountControl",
2860 "pwdLastSet", "msDS-KeyVersionNumber",
2861 "replPropertyMetaData"])
2862 self.assertTrue(len(res) == 1)
2863 self.assertEqual(int(res[0]["sAMAccountType"][0]),
2864 ATYPE_NORMAL_ACCOUNT)
2865 self.assertEqual(int(res[0]["userAccountControl"][0]),
2866 UF_NORMAL_ACCOUNT |UF_SMARTCARD_REQUIRED)
2867 self.assertEqual(int(res[0]["pwdLastSet"][0]), 0)
2868 self.assertEqual(int(res[0]["msDS-KeyVersionNumber"][0]), 1)
2869 self.assertTrue(len(res[0]["replPropertyMetaData"]) == 1)
2870 rpmd = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
2871 res[0]["replPropertyMetaData"][0])
2872 lastsetmd = self.find_repl_meta_data(rpmd,
2873 drsuapi.DRSUAPI_ATTID_pwdLastSet)
2874 self.assertIsNotNone(lastsetmd)
2875 self.assertEqual(lastsetmd.version, 1)
2876 nthashmd = self.find_repl_meta_data(rpmd,
2877 drsuapi.DRSUAPI_ATTID_unicodePwd)
2878 self.assertIsNotNone(nthashmd)
2879 self.assertEqual(nthashmd.version, 1)
2880 nthistmd = self.find_repl_meta_data(rpmd,
2881 drsuapi.DRSUAPI_ATTID_ntPwdHistory)
2882 self.assertIsNotNone(nthistmd)
2883 self.assertEqual(nthistmd.version, 1)
2884 lmhashmd = self.find_repl_meta_data(rpmd,
2885 drsuapi.DRSUAPI_ATTID_dBCSPwd)
2886 self.assertIsNotNone(lmhashmd)
2887 self.assertEqual(lmhashmd.version, 1)
2888 lmhistmd = self.find_repl_meta_data(rpmd,
2889 drsuapi.DRSUAPI_ATTID_lmPwdHistory)
2890 self.assertIsNotNone(lmhistmd)
2891 self.assertEqual(lmhistmd.version, 1)
2892 spcbmd = self.find_repl_meta_data(rpmd,
2893 drsuapi.DRSUAPI_ATTID_supplementalCredentials)
2894 self.assertIsNotNone(spcbmd)
2895 self.assertEqual(spcbmd.version, 1)
2897 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2899 def test_isCriticalSystemObject(self):
2900 """Test the isCriticalSystemObject behaviour"""
2901 print("Testing isCriticalSystemObject behaviour\n")
2906 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2907 "objectclass": "computer"})
2909 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2911 attrs=["isCriticalSystemObject"])
2912 self.assertTrue(len(res1) == 1)
2913 self.assertTrue("isCriticalSystemObject" not in res1[0])
2915 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2918 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2919 "objectclass": "computer",
2920 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
2922 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2924 attrs=["isCriticalSystemObject"])
2925 self.assertTrue(len(res1) == 1)
2926 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "FALSE")
2928 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2931 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2932 "objectclass": "computer",
2933 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)})
2935 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2937 attrs=["isCriticalSystemObject"])
2938 self.assertTrue(len(res1) == 1)
2939 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2941 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2944 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
2945 "objectclass": "computer",
2946 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
2948 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2950 attrs=["isCriticalSystemObject"])
2951 self.assertTrue(len(res1) == 1)
2952 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2954 # Modification tests
2957 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2958 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2959 FLAG_MOD_REPLACE, "userAccountControl")
2962 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2964 attrs=["isCriticalSystemObject"])
2965 self.assertTrue(len(res1) == 1)
2966 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2969 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2970 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT),
2971 FLAG_MOD_REPLACE, "userAccountControl")
2974 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2976 attrs=["isCriticalSystemObject"])
2977 self.assertTrue(len(res1) == 1)
2978 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "FALSE")
2981 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2982 m["userAccountControl"] = MessageElement(
2983 str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT),
2984 FLAG_MOD_REPLACE, "userAccountControl")
2987 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
2989 attrs=["isCriticalSystemObject"])
2990 self.assertTrue(len(res1) == 1)
2991 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
2994 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2995 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
2996 FLAG_MOD_REPLACE, "userAccountControl")
2999 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3001 attrs=["isCriticalSystemObject"])
3002 self.assertTrue(len(res1) == 1)
3003 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
3006 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3007 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT),
3008 FLAG_MOD_REPLACE, "userAccountControl")
3011 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3013 attrs=["isCriticalSystemObject"])
3014 self.assertTrue(len(res1) == 1)
3015 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "TRUE")
3018 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3019 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT),
3020 FLAG_MOD_REPLACE, "userAccountControl")
3023 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3025 attrs=["isCriticalSystemObject"])
3026 self.assertTrue(len(res1) == 1)
3027 self.assertEquals(res1[0]["isCriticalSystemObject"][0], "FALSE")
3029 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3031 def test_service_principal_name_updates(self):
3032 """Test the servicePrincipalNames update behaviour"""
3033 print("Testing servicePrincipalNames update behaviour\n")
3036 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3037 "objectclass": "computer",
3038 "dNSHostName": "testname.testdom"})
3040 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3041 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3042 self.assertTrue(len(res) == 1)
3043 self.assertFalse("servicePrincipalName" in res[0])
3045 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3048 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3049 "objectclass": "computer",
3050 "servicePrincipalName": "HOST/testname.testdom"})
3052 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3053 scope=SCOPE_BASE, attrs=["dNSHostName"])
3054 self.assertTrue(len(res) == 1)
3055 self.assertFalse("dNSHostName" in res[0])
3057 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3060 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3061 "objectclass": "computer",
3062 "dNSHostName": "testname2.testdom",
3063 "servicePrincipalName": "HOST/testname.testdom"})
3065 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3066 scope=SCOPE_BASE, attrs=["dNSHostName"])
3067 self.assertTrue(len(res) == 1)
3068 self.assertEquals(res[0]["dNSHostName"][0], "testname2.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.assertEquals(res[0]["servicePrincipalName"][0],
3074 "HOST/testname.testdom")
3077 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3078 m["dNSHostName"] = MessageElement("testname.testdoM",
3079 FLAG_MOD_REPLACE, "dNSHostName")
3082 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3083 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3084 self.assertTrue(len(res) == 1)
3085 self.assertEquals(res[0]["servicePrincipalName"][0],
3086 "HOST/testname.testdom")
3089 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3090 m["dNSHostName"] = MessageElement("testname2.testdom2",
3091 FLAG_MOD_REPLACE, "dNSHostName")
3094 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3095 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3096 self.assertTrue(len(res) == 1)
3097 self.assertEquals(res[0]["servicePrincipalName"][0],
3098 "HOST/testname2.testdom2")
3101 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3102 m["dNSHostName"] = MessageElement([],
3103 FLAG_MOD_DELETE, "dNSHostName")
3106 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3107 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3108 self.assertTrue(len(res) == 1)
3109 self.assertEquals(res[0]["servicePrincipalName"][0],
3110 "HOST/testname2.testdom2")
3113 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3114 m["dNSHostName"] = MessageElement("testname.testdom3",
3115 FLAG_MOD_REPLACE, "dNSHostName")
3118 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3119 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3120 self.assertTrue(len(res) == 1)
3121 self.assertEquals(res[0]["servicePrincipalName"][0],
3122 "HOST/testname2.testdom2")
3125 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3126 m["dNSHostName"] = MessageElement("testname2.testdom2",
3127 FLAG_MOD_REPLACE, "dNSHostName")
3131 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3132 m["dNSHostName"] = MessageElement("testname3.testdom3",
3133 FLAG_MOD_REPLACE, "dNSHostName")
3134 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
3136 "servicePrincipalName")
3139 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3140 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3141 self.assertTrue(len(res) == 1)
3142 self.assertEquals(res[0]["servicePrincipalName"][0],
3143 "HOST/testname3.testdom3")
3146 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3147 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom2",
3149 "servicePrincipalName")
3150 m["dNSHostName"] = MessageElement("testname4.testdom4",
3151 FLAG_MOD_REPLACE, "dNSHostName")
3154 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3155 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3156 self.assertTrue(len(res) == 1)
3157 self.assertEquals(res[0]["servicePrincipalName"][0],
3158 "HOST/testname2.testdom2")
3161 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3162 m["servicePrincipalName"] = MessageElement([],
3164 "servicePrincipalName")
3168 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3169 m["dNSHostName"] = MessageElement("testname2.testdom2",
3170 FLAG_MOD_REPLACE, "dNSHostName")
3173 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3174 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3175 self.assertTrue(len(res) == 1)
3176 self.assertFalse("servicePrincipalName" in res[0])
3178 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3181 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3182 "objectclass": "computer",
3183 "sAMAccountName": "testname$"})
3185 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3186 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3187 self.assertTrue(len(res) == 1)
3188 self.assertFalse("servicePrincipalName" in res[0])
3190 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3193 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3194 "objectclass": "computer",
3195 "servicePrincipalName": "HOST/testname"})
3197 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3198 scope=SCOPE_BASE, attrs=["sAMAccountName"])
3199 self.assertTrue(len(res) == 1)
3200 self.assertTrue("sAMAccountName" in res[0])
3202 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3205 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3206 "objectclass": "computer",
3207 "sAMAccountName": "testname$",
3208 "servicePrincipalName": "HOST/testname"})
3210 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3211 scope=SCOPE_BASE, attrs=["sAMAccountName"])
3212 self.assertTrue(len(res) == 1)
3213 self.assertEquals(res[0]["sAMAccountName"][0], "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.assertEquals(res[0]["servicePrincipalName"][0],
3222 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3223 m["sAMAccountName"] = MessageElement("testnamE$",
3224 FLAG_MOD_REPLACE, "sAMAccountName")
3227 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3228 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3229 self.assertTrue(len(res) == 1)
3230 self.assertEquals(res[0]["servicePrincipalName"][0],
3234 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3235 m["sAMAccountName"] = MessageElement("testname",
3236 FLAG_MOD_REPLACE, "sAMAccountName")
3239 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3240 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3241 self.assertTrue(len(res) == 1)
3242 self.assertEquals(res[0]["servicePrincipalName"][0],
3246 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3247 m["sAMAccountName"] = MessageElement("test$name$",
3248 FLAG_MOD_REPLACE, "sAMAccountName")
3251 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3252 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3253 self.assertTrue(len(res) == 1)
3254 self.assertEquals(res[0]["servicePrincipalName"][0],
3258 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3259 m["sAMAccountName"] = MessageElement("testname2",
3260 FLAG_MOD_REPLACE, "sAMAccountName")
3263 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3264 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3265 self.assertTrue(len(res) == 1)
3266 self.assertEquals(res[0]["servicePrincipalName"][0],
3270 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3271 m["sAMAccountName"] = MessageElement("testname3",
3272 FLAG_MOD_REPLACE, "sAMAccountName")
3273 m["servicePrincipalName"] = MessageElement("HOST/testname2",
3275 "servicePrincipalName")
3278 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3279 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3280 self.assertTrue(len(res) == 1)
3281 self.assertEquals(res[0]["servicePrincipalName"][0],
3285 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3286 m["servicePrincipalName"] = MessageElement("HOST/testname2",
3288 "servicePrincipalName")
3289 m["sAMAccountName"] = MessageElement("testname4",
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(res[0]["servicePrincipalName"][0],
3300 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3301 m["servicePrincipalName"] = MessageElement([],
3303 "servicePrincipalName")
3307 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3308 m["sAMAccountName"] = MessageElement("testname2",
3309 FLAG_MOD_REPLACE, "sAMAccountName")
3312 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3313 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
3314 self.assertTrue(len(res) == 1)
3315 self.assertFalse("servicePrincipalName" in res[0])
3317 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3320 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3321 "objectclass": "computer",
3322 "dNSHostName": "testname.testdom",
3323 "sAMAccountName": "testname$",
3324 "servicePrincipalName": ["HOST/testname.testdom", "HOST/testname"]
3328 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3329 m["dNSHostName"] = MessageElement("testname2.testdom",
3330 FLAG_MOD_REPLACE, "dNSHostName")
3331 m["sAMAccountName"] = MessageElement("testname2$",
3332 FLAG_MOD_REPLACE, "sAMAccountName")
3335 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3336 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3337 self.assertTrue(len(res) == 1)
3338 self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
3339 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3340 self.assertTrue(res[0]["servicePrincipalName"][0] == "HOST/testname2" or
3341 res[0]["servicePrincipalName"][1] == "HOST/testname2")
3342 self.assertTrue(res[0]["servicePrincipalName"][0] == "HOST/testname2.testdom" or
3343 res[0]["servicePrincipalName"][1] == "HOST/testname2.testdom")
3345 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3348 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
3349 "objectclass": "computer",
3350 "dNSHostName": "testname.testdom",
3351 "sAMAccountName": "testname$",
3352 "servicePrincipalName": ["HOST/testname.testdom", "HOST/testname"]
3356 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3357 m["sAMAccountName"] = MessageElement("testname2$",
3358 FLAG_MOD_REPLACE, "sAMAccountName")
3359 m["dNSHostName"] = MessageElement("testname2.testdom",
3360 FLAG_MOD_REPLACE, "dNSHostName")
3363 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3364 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3365 self.assertTrue(len(res) == 1)
3366 self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
3367 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3368 self.assertTrue(len(res[0]["servicePrincipalName"]) == 2)
3369 self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
3370 self.assertTrue("HOST/testname2.testdom" in res[0]["servicePrincipalName"])
3373 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3374 m["servicePrincipalName"] = MessageElement("HOST/testname2.testdom",
3375 FLAG_MOD_ADD, "servicePrincipalName")
3379 except LdbError as e77:
3381 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3384 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3385 m["servicePrincipalName"] = MessageElement("HOST/testname3",
3386 FLAG_MOD_ADD, "servicePrincipalName")
3389 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3390 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3391 self.assertTrue(len(res) == 1)
3392 self.assertEquals(res[0]["dNSHostName"][0], "testname2.testdom")
3393 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3394 self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
3395 self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
3396 self.assertTrue("HOST/testname3" in res[0]["servicePrincipalName"])
3397 self.assertTrue("HOST/testname2.testdom" in res[0]["servicePrincipalName"])
3400 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3401 m["dNSHostName"] = MessageElement("testname3.testdom",
3402 FLAG_MOD_REPLACE, "dNSHostName")
3403 m["servicePrincipalName"] = MessageElement("HOST/testname3.testdom",
3404 FLAG_MOD_ADD, "servicePrincipalName")
3407 res = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
3408 scope=SCOPE_BASE, attrs=["dNSHostName", "sAMAccountName", "servicePrincipalName"])
3409 self.assertTrue(len(res) == 1)
3410 self.assertEquals(res[0]["dNSHostName"][0], "testname3.testdom")
3411 self.assertEquals(res[0]["sAMAccountName"][0], "testname2$")
3412 self.assertTrue(len(res[0]["servicePrincipalName"]) == 3)
3413 self.assertTrue("HOST/testname2" in res[0]["servicePrincipalName"])
3414 self.assertTrue("HOST/testname3" in res[0]["servicePrincipalName"])
3415 self.assertTrue("HOST/testname3.testdom" in res[0]["servicePrincipalName"])
3417 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
3419 def test_sam_description_attribute(self):
3420 """Test SAM description attribute"""
3421 print("Test SAM description attribute")
3424 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3425 "objectclass": "group",
3426 "description": "desc1"
3429 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3430 scope=SCOPE_BASE, attrs=["description"])
3431 self.assertTrue(len(res) == 1)
3432 self.assertTrue("description" in res[0])
3433 self.assertTrue(len(res[0]["description"]) == 1)
3434 self.assertEquals(res[0]["description"][0], "desc1")
3436 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3439 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3440 "objectclass": "group",
3441 "description": ["desc1", "desc2"]})
3443 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3444 scope=SCOPE_BASE, attrs=["description"])
3445 self.assertTrue(len(res) == 1)
3446 self.assertTrue("description" in res[0])
3447 self.assertTrue(len(res[0]["description"]) == 2)
3448 self.assertTrue(res[0]["description"][0] == "desc1" or
3449 res[0]["description"][1] == "desc1")
3450 self.assertTrue(res[0]["description"][0] == "desc2" or
3451 res[0]["description"][1] == "desc2")
3454 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3455 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_REPLACE,
3460 except LdbError as e78:
3462 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3465 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3466 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_DELETE,
3470 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3473 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3474 "objectclass": "group"})
3477 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3478 m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
3482 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3483 scope=SCOPE_BASE, attrs=["description"])
3484 self.assertTrue(len(res) == 1)
3485 self.assertTrue("description" in res[0])
3486 self.assertTrue(len(res[0]["description"]) == 1)
3487 self.assertEquals(res[0]["description"][0], "desc1")
3489 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3492 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3493 "objectclass": "group",
3494 "description": ["desc1", "desc2"]})
3497 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3498 m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
3502 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3503 scope=SCOPE_BASE, attrs=["description"])
3504 self.assertTrue(len(res) == 1)
3505 self.assertTrue("description" in res[0])
3506 self.assertTrue(len(res[0]["description"]) == 1)
3507 self.assertEquals(res[0]["description"][0], "desc1")
3510 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3511 m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
3516 except LdbError as e79:
3518 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3521 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3522 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_DELETE,
3527 except LdbError as e80:
3529 self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
3532 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3533 m["description"] = MessageElement("desc1", FLAG_MOD_DELETE,
3536 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3537 scope=SCOPE_BASE, attrs=["description"])
3538 self.assertTrue(len(res) == 1)
3539 self.assertFalse("description" in res[0])
3542 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3543 m["description"] = MessageElement(["desc1", "desc2"], FLAG_MOD_REPLACE,
3548 except LdbError as e81:
3550 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3553 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3554 m["description"] = MessageElement(["desc3", "desc4"], FLAG_MOD_ADD,
3559 except LdbError as e82:
3561 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
3564 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3565 m["description"] = MessageElement("desc1", FLAG_MOD_ADD,
3569 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3570 scope=SCOPE_BASE, attrs=["description"])
3571 self.assertTrue(len(res) == 1)
3572 self.assertTrue("description" in res[0])
3573 self.assertTrue(len(res[0]["description"]) == 1)
3574 self.assertEquals(res[0]["description"][0], "desc1")
3577 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3578 m.add(MessageElement("desc1", FLAG_MOD_DELETE, "description"))
3579 m.add(MessageElement("desc2", FLAG_MOD_ADD, "description"))
3582 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
3583 scope=SCOPE_BASE, attrs=["description"])
3584 self.assertTrue(len(res) == 1)
3585 self.assertTrue("description" in res[0])
3586 self.assertTrue(len(res[0]["description"]) == 1)
3587 self.assertEquals(res[0]["description"][0], "desc2")
3589 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3591 def test_fSMORoleOwner_attribute(self):
3592 """Test fSMORoleOwner attribute"""
3593 print("Test fSMORoleOwner attribute")
3595 ds_service_name = self.ldb.get_dsServiceName()
3597 # The "fSMORoleOwner" attribute can only be set to "nTDSDSA" entries,
3598 # invalid DNs return ERR_UNWILLING_TO_PERFORM
3602 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3603 "objectclass": "group",
3604 "fSMORoleOwner": self.base_dn})
3606 except LdbError as e83:
3608 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3612 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3613 "objectclass": "group",
3614 "fSMORoleOwner": []})
3616 except LdbError as e84:
3618 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
3620 # We are able to set it to a valid "nTDSDSA" entry if the server is
3621 # capable of handling the role
3624 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3625 "objectclass": "group",
3626 "fSMORoleOwner": ds_service_name})
3628 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3631 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
3632 "objectclass": "group"})
3635 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3636 m.add(MessageElement(self.base_dn, FLAG_MOD_REPLACE, "fSMORoleOwner"))
3640 except LdbError as e85:
3642 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3645 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3646 m.add(MessageElement([], FLAG_MOD_REPLACE, "fSMORoleOwner"))
3650 except LdbError as e86:
3652 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
3654 # We are able to set it to a valid "nTDSDSA" entry if the server is
3655 # capable of handling the role
3658 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3659 m.add(MessageElement(ds_service_name, FLAG_MOD_REPLACE, "fSMORoleOwner"))
3662 # A clean-out works on plain entries, not master (schema, PDC...) DNs
3665 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3666 m.add(MessageElement([], FLAG_MOD_DELETE, "fSMORoleOwner"))
3669 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
3671 def test_protected_sid_objects(self):
3672 """Test deletion of objects with RID < 1000"""
3673 # a list of some well-known sids
3674 # objects in Builtin are aready covered by objectclass
3676 ["CN=Domain Admins", "CN=Users,"],
3677 ["CN=Schema Admins", "CN=Users,"],
3678 ["CN=Enterprise Admins", "CN=Users,"],
3679 ["CN=Administrator", "CN=Users,"],
3680 ["CN=Domain Controllers", "CN=Users,"],
3683 for pr_object in protected_list:
3685 self.ldb.delete(pr_object[0] + "," + pr_object[1] + self.base_dn)
3686 except LdbError as e7:
3688 self.assertEquals(num, ERR_OTHER)
3690 self.fail("Deleted " + pr_object[0])
3693 self.ldb.rename(pr_object[0] + "," + pr_object[1] + self.base_dn,
3694 pr_object[0] + "2," + pr_object[1] + self.base_dn)
3695 except LdbError as e8:
3697 self.fail("Could not rename " + pr_object[0])
3699 self.ldb.rename(pr_object[0] + "2," + pr_object[1] + self.base_dn,
3700 pr_object[0] + "," + pr_object[1] + self.base_dn)
3702 def test_new_user_default_attributes(self):
3703 """Test default attributes for new user objects"""
3704 print("Test default attributes for new User objects\n")
3706 user_name = "ldaptestuser"
3707 user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
3710 "objectclass": "user",
3711 "sAMAccountName": user_name})
3713 res = ldb.search(user_dn, scope=SCOPE_BASE)
3714 self.assertTrue(len(res) == 1)
3717 expected_attrs = {"primaryGroupID": MessageElement(["513"]),
3718 "logonCount": MessageElement(["0"]),
3719 "cn": MessageElement([user_name]),
3720 "countryCode": MessageElement(["0"]),
3721 "objectClass": MessageElement(["top", "person", "organizationalPerson", "user"]),
3722 "instanceType": MessageElement(["4"]),
3723 "distinguishedName": MessageElement([user_dn]),
3724 "sAMAccountType": MessageElement(["805306368"]),
3725 "objectSid": "**SKIP**",
3726 "whenCreated": "**SKIP**",
3727 "uSNCreated": "**SKIP**",
3728 "badPasswordTime": MessageElement(["0"]),
3729 "dn": Dn(ldb, user_dn),
3730 "pwdLastSet": MessageElement(["0"]),
3731 "sAMAccountName": MessageElement([user_name]),
3732 "objectCategory": MessageElement(["CN=Person,%s" % ldb.get_schema_basedn().get_linearized()]),
3733 "objectGUID": "**SKIP**",
3734 "whenChanged": "**SKIP**",
3735 "badPwdCount": MessageElement(["0"]),
3736 "accountExpires": MessageElement(["9223372036854775807"]),
3737 "name": MessageElement([user_name]),
3738 "codePage": MessageElement(["0"]),
3739 "userAccountControl": MessageElement(["546"]),
3740 "lastLogon": MessageElement(["0"]),
3741 "uSNChanged": "**SKIP**",
3742 "lastLogoff": MessageElement(["0"])}
3743 # assert we have expected attribute names
3744 actual_names = set(user_obj.keys())
3745 # Samba does not use 'dSCorePropagationData', so skip it
3746 actual_names -= set(['dSCorePropagationData'])
3747 self.assertEqual(set(expected_attrs.keys()), actual_names, "Actual object does not have expected attributes")
3748 # check attribute values
3749 for name in expected_attrs.keys():
3750 actual_val = user_obj.get(name)
3751 self.assertFalse(actual_val is None, "No value for attribute '%s'" % name)
3752 expected_val = expected_attrs[name]
3753 if expected_val == "**SKIP**":
3754 # "**ANY**" values means "any"
3756 self.assertEqual(expected_val, actual_val,
3757 "Unexpected value[%r] for '%s' expected[%r]" %
3758 (actual_val, name, expected_val))
3760 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
3763 if not "://" in host:
3764 if os.path.isfile(host):
3765 host = "tdb://%s" % host
3767 host = "ldap://%s" % host
3769 ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp)
3771 TestProgram(module=__name__, opts=subunitopts)