2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
11 sys.path.append("bin/python")
13 samba.ensure_external_module("subunit", "subunit/python")
14 samba.ensure_external_module("testtools", "testtools")
16 import samba.getopt as options
18 from samba.auth import system_session
19 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, 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_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
23 from ldb import ERR_NO_SUCH_ATTRIBUTE
24 from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
25 from ldb import ERR_NAMING_VIOLATION, ERR_CONSTRAINT_VIOLATION
26 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
27 from ldb import Message, MessageElement, Dn
28 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
30 from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_INTERDOMAIN_TRUST_ACCOUNT,
31 UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
32 UF_PARTIAL_SECRETS_ACCOUNT,
33 UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE, ATYPE_NORMAL_ACCOUNT,
34 ATYPE_WORKSTATION_TRUST, SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE,
35 SYSTEM_FLAG_CONFIG_ALLOW_RENAME, SYSTEM_FLAG_CONFIG_ALLOW_MOVE,
36 SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE)
37 from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_DOMAIN_MEMBERS,
38 DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS)
40 from subunit.run import SubunitTestRunner
43 from samba.ndr import ndr_pack, ndr_unpack
44 from samba.dcerpc import security
46 parser = optparse.OptionParser("sam.py [options] <host>")
47 sambaopts = options.SambaOptions(parser)
48 parser.add_option_group(sambaopts)
49 parser.add_option_group(options.VersionOptions(parser))
50 # use command line creds if available
51 credopts = options.CredentialsOptions(parser)
52 parser.add_option_group(credopts)
53 opts, args = parser.parse_args()
61 lp = sambaopts.get_loadparm()
62 creds = credopts.get_credentials(lp)
64 class SamTests(unittest.TestCase):
66 def delete_force(self, ldb, dn):
69 except LdbError, (num, _):
70 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
72 def find_basedn(self, ldb):
73 res = ldb.search(base="", expression="", scope=SCOPE_BASE,
74 attrs=["defaultNamingContext"])
75 self.assertEquals(len(res), 1)
76 return res[0]["defaultNamingContext"][0]
78 def find_domain_sid(self):
79 res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
80 return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
83 super(SamTests, self).setUp()
86 self.base_dn = self.find_basedn(ldb)
87 self.domain_sid = self.find_domain_sid()
89 print "baseDN: %s\n" % self.base_dn
91 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
92 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
93 self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
95 def test_users_groups(self):
96 """This tests the SAM users and groups behaviour"""
97 print "Testing users and groups behaviour\n"
100 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
101 "objectclass": "group"})
104 "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
105 "objectclass": "group"})
107 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
108 scope=SCOPE_BASE, attrs=["objectSID"])
109 self.assertTrue(len(res1) == 1)
110 group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
111 res1[0]["objectSID"][0])).split()[1]
113 res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
114 scope=SCOPE_BASE, attrs=["objectSID"])
115 self.assertTrue(len(res1) == 1)
116 group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
117 res1[0]["objectSID"][0])).split()[1]
119 # Try to create a user with an invalid primary group
122 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
123 "objectclass": ["user", "person"],
124 "primaryGroupID": "0"})
126 except LdbError, (num, _):
127 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
128 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
130 # Try to Create a user with a valid primary group
133 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
134 "objectclass": ["user", "person"],
135 "primaryGroupID": str(group_rid_1)})
137 except LdbError, (num, _):
138 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
139 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
141 # Test to see how we should behave when the user account doesn't
144 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
145 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
150 except LdbError, (num, _):
151 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
153 # Test to see how we should behave when the account isn't a user
155 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
156 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
161 except LdbError, (num, _):
162 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
164 # Test default primary groups on add operations
167 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
168 "objectclass": ["user", "person"]})
170 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
171 scope=SCOPE_BASE, attrs=["primaryGroupID"])
172 self.assertTrue(len(res1) == 1)
173 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
175 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
178 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
179 "objectclass": ["user", "person"],
180 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD) })
182 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
183 scope=SCOPE_BASE, attrs=["primaryGroupID"])
184 self.assertTrue(len(res1) == 1)
185 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
187 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
189 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
190 # since such accounts aren't directly creatable (ACCESS_DENIED)
193 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
194 "objectclass": ["computer"],
195 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
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_DOMAIN_MEMBERS))
202 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
205 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
206 "objectclass": ["computer"],
207 "userAccountControl": str(UF_SERVER_TRUST_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_DCS))
214 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
216 # Read-only DC accounts are only creatable by
217 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
218 # we have a fallback in the assertion)
220 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
221 "objectclass": ["computer"],
222 "userAccountControl": str(UF_PARTIAL_SECRETS_ACCOUNT | 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.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
228 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
230 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
232 # Test default primary groups on modify operations
235 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
236 "objectclass": ["user", "person"]})
239 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
240 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
241 "userAccountControl")
244 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
245 scope=SCOPE_BASE, attrs=["primaryGroupID"])
246 self.assertTrue(len(res1) == 1)
247 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
249 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
250 # since such accounts aren't directly creatable (ACCESS_DENIED)
252 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
255 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
256 "objectclass": ["computer"]})
258 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
259 scope=SCOPE_BASE, attrs=["primaryGroupID"])
260 self.assertTrue(len(res1) == 1)
261 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
264 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
265 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
266 "userAccountControl")
269 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
270 scope=SCOPE_BASE, attrs=["primaryGroupID"])
271 self.assertTrue(len(res1) == 1)
272 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
275 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
276 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
277 "userAccountControl")
280 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
281 scope=SCOPE_BASE, attrs=["primaryGroupID"])
282 self.assertTrue(len(res1) == 1)
283 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
285 # Read-only DC accounts are only creatable by
286 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
287 # we have a fallback in the assertion)
289 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
290 m["userAccountControl"] = MessageElement(str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
291 "userAccountControl")
294 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
295 scope=SCOPE_BASE, attrs=["primaryGroupID"])
296 self.assertTrue(len(res1) == 1)
297 self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
298 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
300 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
302 # Recreate account for further tests
305 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
306 "objectclass": ["user", "person"]})
308 # We should be able to reset our actual primary group
310 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
311 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS), FLAG_MOD_REPLACE,
315 # Try to add invalid primary group
317 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
318 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
323 except LdbError, (num, _):
324 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
326 # Try to make group 1 primary - should be denied since it is not yet
329 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
330 m["primaryGroupID"] = MessageElement(str(group_rid_1),
331 FLAG_MOD_REPLACE, "primaryGroupID")
335 except LdbError, (num, _):
336 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
338 # Make group 1 secondary
340 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
341 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
342 FLAG_MOD_REPLACE, "member")
345 # Make group 1 primary
347 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
348 m["primaryGroupID"] = MessageElement(str(group_rid_1),
349 FLAG_MOD_REPLACE, "primaryGroupID")
352 # Try to delete group 1 - should be denied
354 ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
356 except LdbError, (num, _):
357 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
359 # Try to add group 1 also as secondary - should be denied
361 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
362 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
363 FLAG_MOD_ADD, "member")
367 except LdbError, (num, _):
368 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
370 # Try to add invalid member to group 1 - should be denied
372 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
373 m["member"] = MessageElement(
374 "cn=ldaptestuser3,cn=users," + self.base_dn,
375 FLAG_MOD_ADD, "member")
379 except LdbError, (num, _):
380 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
382 # Make group 2 secondary
384 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
385 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
386 FLAG_MOD_ADD, "member")
391 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
392 m["primaryGroupID"] = MessageElement(str(group_rid_2),
393 FLAG_MOD_REPLACE, "primaryGroupID")
396 # Old primary group should contain a "member" attribute for the user,
397 # the new shouldn't contain anymore one
398 res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
399 scope=SCOPE_BASE, attrs=["member"])
400 self.assertTrue(len(res1) == 1)
401 self.assertTrue(len(res1[0]["member"]) == 1)
402 self.assertEquals(res1[0]["member"][0].lower(),
403 ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
405 res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
406 scope=SCOPE_BASE, attrs=["member"])
407 self.assertTrue(len(res1) == 1)
408 self.assertFalse("member" in res1[0])
410 # Also this should be denied
413 "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
414 "objectclass": ["user", "person"],
415 "primaryGroupID": "0"})
417 except LdbError, (num, _):
418 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
420 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
421 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
422 self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
424 def test_sam_attributes(self):
425 """Test the behaviour of special attributes of SAM objects"""
426 print "Testing the behaviour of special attributes of SAM objects\n"""
429 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
430 "objectclass": ["user", "person"]})
432 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
433 "objectclass": "group"})
436 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
437 m["groupType"] = MessageElement("0", FLAG_MOD_ADD,
442 except LdbError, (num, _):
443 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
446 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
447 m["groupType"] = MessageElement([], FLAG_MOD_DELETE,
452 except LdbError, (num, _):
453 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
456 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
457 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_ADD,
462 except LdbError, (num, _):
463 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
466 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
467 m["primaryGroupID"] = MessageElement([], FLAG_MOD_DELETE,
472 except LdbError, (num, _):
473 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
476 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
477 m["userAccountControl"] = MessageElement("0", FLAG_MOD_ADD,
478 "userAccountControl")
482 except LdbError, (num, _):
483 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
486 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
487 m["userAccountControl"] = MessageElement([], FLAG_MOD_DELETE,
488 "userAccountControl")
492 except LdbError, (num, _):
493 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
496 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
497 m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
502 except LdbError, (num, _):
503 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
506 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
507 m["sAMAccountType"] = MessageElement([], FLAG_MOD_REPLACE,
512 except LdbError, (num, _):
513 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
516 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
517 m["sAMAccountType"] = MessageElement([], FLAG_MOD_DELETE,
522 except LdbError, (num, _):
523 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
525 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
526 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
528 def test_primary_group_token_constructed(self):
529 """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
530 print "Testing primary group token behaviour and other constructed attributes\n"
534 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
535 "objectclass": "group",
536 "primaryGroupToken": "100"})
538 except LdbError, (num, _):
539 self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
540 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
543 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
544 "objectclass": ["user", "person"]})
547 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
548 "objectclass": "group"})
550 # Testing for one invalid, and one valid operational attribute, but also the things they are built from
551 res1 = ldb.search(self.base_dn,
552 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
553 self.assertTrue(len(res1) == 1)
554 self.assertFalse("primaryGroupToken" in res1[0])
555 self.assertTrue("canonicalName" in res1[0])
556 self.assertTrue("objectClass" in res1[0])
557 self.assertTrue("objectSid" in res1[0])
559 res1 = ldb.search(self.base_dn,
560 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
561 self.assertTrue(len(res1) == 1)
562 self.assertFalse("primaryGroupToken" in res1[0])
563 self.assertFalse("objectSid" in res1[0])
564 self.assertFalse("objectClass" in res1[0])
565 self.assertTrue("canonicalName" in res1[0])
567 res1 = ldb.search("cn=users,"+self.base_dn,
568 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
569 self.assertTrue(len(res1) == 1)
570 self.assertFalse("primaryGroupToken" in res1[0])
572 res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
573 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
574 self.assertTrue(len(res1) == 1)
575 self.assertFalse("primaryGroupToken" in res1[0])
577 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
579 self.assertTrue(len(res1) == 1)
580 self.assertFalse("primaryGroupToken" in res1[0])
582 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
583 scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
584 self.assertTrue(len(res1) == 1)
585 primary_group_token = int(res1[0]["primaryGroupToken"][0])
587 rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
588 self.assertEquals(primary_group_token, rid)
591 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
592 m["primaryGroupToken"] = "100"
596 except LdbError, (num, _):
597 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
599 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
600 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
602 def test_tokenGroups(self):
603 """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
604 print "Testing tokenGroups behaviour\n"
606 # The domain object shouldn't contain any "tokenGroups" entry
607 res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
608 self.assertTrue(len(res) == 1)
609 self.assertFalse("tokenGroups" in res[0])
611 # The domain administrator should contain "tokenGroups" entries
612 # (the exact number depends on the domain/forest function level and the
613 # DC software versions)
614 res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
615 scope=SCOPE_BASE, attrs=["tokenGroups"])
616 self.assertTrue(len(res) == 1)
617 self.assertTrue("tokenGroups" in res[0])
620 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
621 "objectclass": ["user", "person"]})
623 # This testuser should contain at least two "tokenGroups" entries
624 # (exactly two on an unmodified "Domain Users" and "Users" group)
625 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
626 scope=SCOPE_BASE, attrs=["tokenGroups"])
627 self.assertTrue(len(res) == 1)
628 self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
630 # one entry which we need to find should point to domains "Domain Users"
631 # group and another entry should point to the builtin "Users"group
632 domain_users_group_found = False
633 users_group_found = False
634 for sid in res[0]["tokenGroups"]:
635 rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
637 domain_users_group_found = True
639 users_group_found = True
641 self.assertTrue(domain_users_group_found)
642 self.assertTrue(users_group_found)
644 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
646 if not "://" in host:
647 if os.path.isfile(host):
648 host = "tdb://%s" % host
650 host = "ldap://%s" % host
652 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
653 if not "tdb://" in host:
654 gc_ldb = Ldb("%s:3268" % host, credentials=creds,
655 session_info=system_session(), lp=lp)
659 runner = SubunitTestRunner()
661 if not runner.run(unittest.makeSuite(SamTests)).wasSuccessful():