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, ERR_INSUFFICIENT_ACCESS_RIGHTS
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, UF_TEMP_DUPLICATE_ACCOUNT,
33 UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE, ATYPE_NORMAL_ACCOUNT,
34 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
35 GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP,
36 GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP, GTYPE_DISTRIBUTION_GLOBAL_GROUP,
37 GTYPE_DISTRIBUTION_UNIVERSAL_GROUP,
38 ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_UNIVERSAL_GROUP,
39 ATYPE_SECURITY_LOCAL_GROUP, ATYPE_DISTRIBUTION_GLOBAL_GROUP,
40 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP, ATYPE_DISTRIBUTION_LOCAL_GROUP,
41 ATYPE_WORKSTATION_TRUST, SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE,
42 SYSTEM_FLAG_CONFIG_ALLOW_RENAME, SYSTEM_FLAG_CONFIG_ALLOW_MOVE,
43 SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE)
44 from samba.dcerpc.security import (DOMAIN_RID_USERS, DOMAIN_RID_DOMAIN_MEMBERS,
45 DOMAIN_RID_DCS, DOMAIN_RID_READONLY_DCS)
47 from subunit.run import SubunitTestRunner
50 from samba.ndr import ndr_pack, ndr_unpack
51 from samba.dcerpc import security
53 parser = optparse.OptionParser("sam.py [options] <host>")
54 sambaopts = options.SambaOptions(parser)
55 parser.add_option_group(sambaopts)
56 parser.add_option_group(options.VersionOptions(parser))
57 # use command line creds if available
58 credopts = options.CredentialsOptions(parser)
59 parser.add_option_group(credopts)
60 opts, args = parser.parse_args()
68 lp = sambaopts.get_loadparm()
69 creds = credopts.get_credentials(lp)
71 class SamTests(unittest.TestCase):
73 def delete_force(self, ldb, dn):
76 except LdbError, (num, _):
77 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
79 def find_basedn(self, ldb):
80 res = ldb.search(base="", expression="", scope=SCOPE_BASE,
81 attrs=["defaultNamingContext"])
82 self.assertEquals(len(res), 1)
83 return res[0]["defaultNamingContext"][0]
85 def find_domain_sid(self):
86 res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
87 return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
90 super(SamTests, self).setUp()
93 self.base_dn = self.find_basedn(ldb)
94 self.domain_sid = self.find_domain_sid()
96 print "baseDN: %s\n" % self.base_dn
98 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
99 self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=users," + self.base_dn)
100 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
101 self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
103 def test_users_groups(self):
104 """This tests the SAM users and groups behaviour"""
105 print "Testing users and groups behaviour\n"
108 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
109 "objectclass": "group"})
112 "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
113 "objectclass": "group"})
115 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
116 scope=SCOPE_BASE, attrs=["objectSID"])
117 self.assertTrue(len(res1) == 1)
118 group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
119 res1[0]["objectSID"][0])).split()[1]
121 res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
122 scope=SCOPE_BASE, attrs=["objectSID"])
123 self.assertTrue(len(res1) == 1)
124 group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
125 res1[0]["objectSID"][0])).split()[1]
127 # Try to create a user with an invalid primary group
130 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
131 "objectclass": ["user", "person"],
132 "primaryGroupID": "0"})
134 except LdbError, (num, _):
135 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
136 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
138 # Try to Create a user with a valid primary group
141 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
142 "objectclass": ["user", "person"],
143 "primaryGroupID": str(group_rid_1)})
145 except LdbError, (num, _):
146 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
147 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
149 # Test to see how we should behave when the user account doesn't
152 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
153 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
158 except LdbError, (num, _):
159 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
161 # Test to see how we should behave when the account isn't a user
163 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
164 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
169 except LdbError, (num, _):
170 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
172 # Test default primary groups on add operations
175 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
176 "objectclass": ["user", "person"]})
178 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
179 scope=SCOPE_BASE, attrs=["primaryGroupID"])
180 self.assertTrue(len(res1) == 1)
181 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
183 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
186 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
187 "objectclass": ["user", "person"],
188 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD) })
190 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
191 scope=SCOPE_BASE, attrs=["primaryGroupID"])
192 self.assertTrue(len(res1) == 1)
193 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
195 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
197 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
198 # since such accounts aren't directly creatable (ACCESS_DENIED)
201 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
202 "objectclass": ["computer"],
203 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
205 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
206 scope=SCOPE_BASE, attrs=["primaryGroupID"])
207 self.assertTrue(len(res1) == 1)
208 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
210 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
213 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
214 "objectclass": ["computer"],
215 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
217 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
218 scope=SCOPE_BASE, attrs=["primaryGroupID"])
219 self.assertTrue(len(res1) == 1)
220 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
222 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
224 # Read-only DC accounts are only creatable by
225 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
226 # we have a fallback in the assertion)
228 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
229 "objectclass": ["computer"],
230 "userAccountControl": str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD) })
232 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
233 scope=SCOPE_BASE, attrs=["primaryGroupID"])
234 self.assertTrue(len(res1) == 1)
235 self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
236 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
238 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
240 # Test default primary groups on modify operations
243 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
244 "objectclass": ["user", "person"]})
247 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
248 m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
249 "userAccountControl")
252 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
253 scope=SCOPE_BASE, attrs=["primaryGroupID"])
254 self.assertTrue(len(res1) == 1)
255 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
257 # unfortunately the INTERDOMAIN_TRUST_ACCOUNT case cannot be tested
258 # since such accounts aren't directly creatable (ACCESS_DENIED)
260 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
263 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
264 "objectclass": ["computer"]})
266 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
267 scope=SCOPE_BASE, attrs=["primaryGroupID"])
268 self.assertTrue(len(res1) == 1)
269 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_USERS))
272 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
273 m["userAccountControl"] = MessageElement(str(UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
274 "userAccountControl")
277 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
278 scope=SCOPE_BASE, attrs=["primaryGroupID"])
279 self.assertTrue(len(res1) == 1)
280 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DOMAIN_MEMBERS))
283 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
284 m["userAccountControl"] = MessageElement(str(UF_SERVER_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
285 "userAccountControl")
288 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
289 scope=SCOPE_BASE, attrs=["primaryGroupID"])
290 self.assertTrue(len(res1) == 1)
291 self.assertEquals(res1[0]["primaryGroupID"][0], str(DOMAIN_RID_DCS))
293 # Read-only DC accounts are only creatable by
294 # UF_WORKSTATION_TRUST_ACCOUNT and work only on DCs >= 2008 (therefore
295 # we have a fallback in the assertion)
297 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
298 m["userAccountControl"] = MessageElement(str(UF_PARTIAL_SECRETS_ACCOUNT | UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_REPLACE,
299 "userAccountControl")
302 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
303 scope=SCOPE_BASE, attrs=["primaryGroupID"])
304 self.assertTrue(len(res1) == 1)
305 self.assertTrue(res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_READONLY_DCS) or
306 res1[0]["primaryGroupID"][0] == str(DOMAIN_RID_DOMAIN_MEMBERS))
308 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
310 # Recreate account for further tests
313 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
314 "objectclass": ["user", "person"]})
316 # We should be able to reset our actual primary group
318 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
319 m["primaryGroupID"] = MessageElement(str(DOMAIN_RID_USERS), FLAG_MOD_REPLACE,
323 # Try to add invalid primary group
325 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
326 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
331 except LdbError, (num, _):
332 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
334 # Try to make group 1 primary - should be denied since it is not yet
337 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
338 m["primaryGroupID"] = MessageElement(str(group_rid_1),
339 FLAG_MOD_REPLACE, "primaryGroupID")
343 except LdbError, (num, _):
344 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
346 # Make group 1 secondary
348 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
349 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
350 FLAG_MOD_REPLACE, "member")
353 # Make group 1 primary
355 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
356 m["primaryGroupID"] = MessageElement(str(group_rid_1),
357 FLAG_MOD_REPLACE, "primaryGroupID")
360 # Try to delete group 1 - should be denied
362 ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
364 except LdbError, (num, _):
365 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
367 # Try to add group 1 also as secondary - should be denied
369 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
370 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
371 FLAG_MOD_ADD, "member")
375 except LdbError, (num, _):
376 self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
378 # Try to add invalid member to group 1 - should be denied
380 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
381 m["member"] = MessageElement(
382 "cn=ldaptestuser3,cn=users," + self.base_dn,
383 FLAG_MOD_ADD, "member")
387 except LdbError, (num, _):
388 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
390 # Make group 2 secondary
392 m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
393 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
394 FLAG_MOD_ADD, "member")
399 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
400 m["primaryGroupID"] = MessageElement(str(group_rid_2),
401 FLAG_MOD_REPLACE, "primaryGroupID")
404 # Old primary group should contain a "member" attribute for the user,
405 # the new shouldn't contain anymore one
406 res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
407 scope=SCOPE_BASE, attrs=["member"])
408 self.assertTrue(len(res1) == 1)
409 self.assertTrue(len(res1[0]["member"]) == 1)
410 self.assertEquals(res1[0]["member"][0].lower(),
411 ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
413 res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
414 scope=SCOPE_BASE, attrs=["member"])
415 self.assertTrue(len(res1) == 1)
416 self.assertFalse("member" in res1[0])
418 # Also this should be denied
421 "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
422 "objectclass": ["user", "person"],
423 "primaryGroupID": "0"})
425 except LdbError, (num, _):
426 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
428 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
429 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
430 self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
432 def test_sam_attributes(self):
433 """Test the behaviour of special attributes of SAM objects"""
434 print "Testing the behaviour of special attributes of SAM objects\n"""
437 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
438 "objectclass": ["user", "person"]})
440 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
441 "objectclass": "group"})
444 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
445 m["groupType"] = MessageElement("0", FLAG_MOD_ADD,
450 except LdbError, (num, _):
451 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
454 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
455 m["groupType"] = MessageElement([], FLAG_MOD_DELETE,
460 except LdbError, (num, _):
461 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
464 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
465 m["primaryGroupID"] = MessageElement("0", FLAG_MOD_ADD,
470 except LdbError, (num, _):
471 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
474 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
475 m["primaryGroupID"] = MessageElement([], FLAG_MOD_DELETE,
480 except LdbError, (num, _):
481 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
484 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
485 m["userAccountControl"] = MessageElement("0", FLAG_MOD_ADD,
486 "userAccountControl")
490 except LdbError, (num, _):
491 self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
494 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
495 m["userAccountControl"] = MessageElement([], FLAG_MOD_DELETE,
496 "userAccountControl")
500 except LdbError, (num, _):
501 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
504 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
505 m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
510 except LdbError, (num, _):
511 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
514 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
515 m["sAMAccountType"] = MessageElement([], FLAG_MOD_REPLACE,
520 except LdbError, (num, _):
521 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
524 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
525 m["sAMAccountType"] = MessageElement([], FLAG_MOD_DELETE,
530 except LdbError, (num, _):
531 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
533 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
534 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
536 def test_primary_group_token_constructed(self):
537 """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
538 print "Testing primary group token behaviour and other constructed attributes\n"
542 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
543 "objectclass": "group",
544 "primaryGroupToken": "100"})
546 except LdbError, (num, _):
547 self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
548 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
551 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
552 "objectclass": ["user", "person"]})
555 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
556 "objectclass": "group"})
558 # Testing for one invalid, and one valid operational attribute, but also the things they are built from
559 res1 = ldb.search(self.base_dn,
560 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
561 self.assertTrue(len(res1) == 1)
562 self.assertFalse("primaryGroupToken" in res1[0])
563 self.assertTrue("canonicalName" in res1[0])
564 self.assertTrue("objectClass" in res1[0])
565 self.assertTrue("objectSid" in res1[0])
567 res1 = ldb.search(self.base_dn,
568 scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
569 self.assertTrue(len(res1) == 1)
570 self.assertFalse("primaryGroupToken" in res1[0])
571 self.assertFalse("objectSid" in res1[0])
572 self.assertFalse("objectClass" in res1[0])
573 self.assertTrue("canonicalName" in res1[0])
575 res1 = ldb.search("cn=users," + self.base_dn,
576 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
577 self.assertTrue(len(res1) == 1)
578 self.assertFalse("primaryGroupToken" in res1[0])
580 res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
581 scope=SCOPE_BASE, attrs=["primaryGroupToken"])
582 self.assertTrue(len(res1) == 1)
583 self.assertFalse("primaryGroupToken" in res1[0])
585 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
587 self.assertTrue(len(res1) == 1)
588 self.assertFalse("primaryGroupToken" in res1[0])
590 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
591 scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
592 self.assertTrue(len(res1) == 1)
593 primary_group_token = int(res1[0]["primaryGroupToken"][0])
595 rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
596 self.assertEquals(primary_group_token, rid)
599 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
600 m["primaryGroupToken"] = "100"
604 except LdbError, (num, _):
605 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
607 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
608 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
610 def test_tokenGroups(self):
611 """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
612 print "Testing tokenGroups behaviour\n"
614 # The domain object shouldn't contain any "tokenGroups" entry
615 res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
616 self.assertTrue(len(res) == 1)
617 self.assertFalse("tokenGroups" in res[0])
619 # The domain administrator should contain "tokenGroups" entries
620 # (the exact number depends on the domain/forest function level and the
621 # DC software versions)
622 res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
623 scope=SCOPE_BASE, attrs=["tokenGroups"])
624 self.assertTrue(len(res) == 1)
625 self.assertTrue("tokenGroups" in res[0])
628 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
629 "objectclass": ["user", "person"]})
631 # This testuser should contain at least two "tokenGroups" entries
632 # (exactly two on an unmodified "Domain Users" and "Users" group)
633 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
634 scope=SCOPE_BASE, attrs=["tokenGroups"])
635 self.assertTrue(len(res) == 1)
636 self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
638 # one entry which we need to find should point to domains "Domain Users"
639 # group and another entry should point to the builtin "Users"group
640 domain_users_group_found = False
641 users_group_found = False
642 for sid in res[0]["tokenGroups"]:
643 rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
645 domain_users_group_found = True
647 users_group_found = True
649 self.assertTrue(domain_users_group_found)
650 self.assertTrue(users_group_found)
652 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
654 def test_groupType(self):
655 """Test the groupType behaviour"""
656 print "Testing groupType behaviour\n"
658 # You can never create or change to a
659 # "GTYPE_SECURITY_BUILTIN_LOCAL_GROUP"
666 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
667 "objectclass": "group",
670 except LdbError, (num, _):
671 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
672 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
676 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
677 "objectclass": "group",
678 "groupType": str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP)})
680 except LdbError, (num, _):
681 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
682 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
685 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
686 "objectclass": "group",
687 "groupType": str(GTYPE_SECURITY_GLOBAL_GROUP)})
689 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
690 scope=SCOPE_BASE, attrs=["sAMAccountType"])
691 self.assertTrue(len(res1) == 1)
692 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
693 ATYPE_SECURITY_GLOBAL_GROUP)
694 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
697 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
698 "objectclass": "group",
699 "groupType": str(GTYPE_SECURITY_UNIVERSAL_GROUP)})
701 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
702 scope=SCOPE_BASE, attrs=["sAMAccountType"])
703 self.assertTrue(len(res1) == 1)
704 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
705 ATYPE_SECURITY_UNIVERSAL_GROUP)
706 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
709 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
710 "objectclass": "group",
711 "groupType": str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP)})
713 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
714 scope=SCOPE_BASE, attrs=["sAMAccountType"])
715 self.assertTrue(len(res1) == 1)
716 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
717 ATYPE_SECURITY_LOCAL_GROUP)
718 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
721 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
722 "objectclass": "group",
723 "groupType": str(GTYPE_DISTRIBUTION_GLOBAL_GROUP)})
725 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
726 scope=SCOPE_BASE, attrs=["sAMAccountType"])
727 self.assertTrue(len(res1) == 1)
728 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
729 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
730 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
733 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
734 "objectclass": "group",
735 "groupType": str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP)})
737 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
738 scope=SCOPE_BASE, attrs=["sAMAccountType"])
739 self.assertTrue(len(res1) == 1)
740 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
741 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
742 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
745 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
746 "objectclass": "group",
747 "groupType": str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)})
749 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
750 scope=SCOPE_BASE, attrs=["sAMAccountType"])
751 self.assertTrue(len(res1) == 1)
752 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
753 ATYPE_DISTRIBUTION_LOCAL_GROUP)
754 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
759 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
760 "objectclass": "group"})
762 # We can change in this direction: global <-> universal <-> local
763 # On each step also the group type itself (security/distribution) is
766 # After creation we should have a "security global group"
767 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
768 scope=SCOPE_BASE, attrs=["sAMAccountType"])
769 self.assertTrue(len(res1) == 1)
770 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
771 ATYPE_SECURITY_GLOBAL_GROUP)
776 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
777 m["groupType"] = MessageElement("0",
778 FLAG_MOD_REPLACE, "groupType")
781 except LdbError, (num, _):
782 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
786 # Default is "global group"
789 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
790 m["groupType"] = MessageElement(
791 str(GTYPE_SECURITY_GLOBAL_GROUP),
792 FLAG_MOD_REPLACE, "groupType")
795 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
796 scope=SCOPE_BASE, attrs=["sAMAccountType"])
797 self.assertTrue(len(res1) == 1)
798 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
799 ATYPE_SECURITY_GLOBAL_GROUP)
801 # Change to "local" (shouldn't work)
805 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
806 m["groupType"] = MessageElement(
807 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
808 FLAG_MOD_REPLACE, "groupType")
811 except LdbError, (num, _):
812 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
814 # Change to "universal"
817 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
818 m["groupType"] = MessageElement(
819 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
820 FLAG_MOD_REPLACE, "groupType")
823 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
824 scope=SCOPE_BASE, attrs=["sAMAccountType"])
825 self.assertTrue(len(res1) == 1)
826 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
827 ATYPE_SECURITY_UNIVERSAL_GROUP)
829 # Change back to "global"
832 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
833 m["groupType"] = MessageElement(
834 str(GTYPE_SECURITY_GLOBAL_GROUP),
835 FLAG_MOD_REPLACE, "groupType")
838 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
839 scope=SCOPE_BASE, attrs=["sAMAccountType"])
840 self.assertTrue(len(res1) == 1)
841 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
842 ATYPE_SECURITY_GLOBAL_GROUP)
844 # Change back to "universal"
847 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
848 m["groupType"] = MessageElement(
849 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
850 FLAG_MOD_REPLACE, "groupType")
853 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
854 scope=SCOPE_BASE, attrs=["sAMAccountType"])
855 self.assertTrue(len(res1) == 1)
856 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
857 ATYPE_SECURITY_UNIVERSAL_GROUP)
862 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
863 m["groupType"] = MessageElement(
864 str(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP),
865 FLAG_MOD_REPLACE, "groupType")
868 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
869 scope=SCOPE_BASE, attrs=["sAMAccountType"])
870 self.assertTrue(len(res1) == 1)
871 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
872 ATYPE_SECURITY_LOCAL_GROUP)
874 # Change to "global" (shouldn't work)
878 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
879 m["groupType"] = MessageElement(
880 str(GTYPE_SECURITY_GLOBAL_GROUP),
881 FLAG_MOD_REPLACE, "groupType")
884 except LdbError, (num, _):
885 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
887 # Change to "builtin local" (shouldn't work)
891 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
892 m["groupType"] = MessageElement(
893 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
894 FLAG_MOD_REPLACE, "groupType")
897 except LdbError, (num, _):
898 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
901 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
903 # Change back to "universal"
906 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
907 m["groupType"] = MessageElement(
908 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
909 FLAG_MOD_REPLACE, "groupType")
912 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
913 scope=SCOPE_BASE, attrs=["sAMAccountType"])
914 self.assertTrue(len(res1) == 1)
915 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
916 ATYPE_SECURITY_UNIVERSAL_GROUP)
918 # Change to "builtin local" (shouldn't work)
922 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
923 m["groupType"] = MessageElement(
924 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
925 FLAG_MOD_REPLACE, "groupType")
928 except LdbError, (num, _):
929 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
931 # Change back to "global"
934 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
935 m["groupType"] = MessageElement(
936 str(GTYPE_SECURITY_GLOBAL_GROUP),
937 FLAG_MOD_REPLACE, "groupType")
940 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
941 scope=SCOPE_BASE, attrs=["sAMAccountType"])
942 self.assertTrue(len(res1) == 1)
943 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
944 ATYPE_SECURITY_GLOBAL_GROUP)
946 # Change to "builtin local" (shouldn't work)
950 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
951 m["groupType"] = MessageElement(
952 str(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP),
953 FLAG_MOD_REPLACE, "groupType")
956 except LdbError, (num, _):
957 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
959 # Distribution groups
961 # Default is "global group"
964 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
965 m["groupType"] = MessageElement(
966 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
967 FLAG_MOD_REPLACE, "groupType")
970 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
971 scope=SCOPE_BASE, attrs=["sAMAccountType"])
972 self.assertTrue(len(res1) == 1)
973 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
974 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
976 # Change to local (shouldn't work)
980 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
981 m["groupType"] = MessageElement(
982 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
983 FLAG_MOD_REPLACE, "groupType")
986 except LdbError, (num, _):
987 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
989 # Change to "universal"
992 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
993 m["groupType"] = MessageElement(
994 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
995 FLAG_MOD_REPLACE, "groupType")
998 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
999 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1000 self.assertTrue(len(res1) == 1)
1001 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1002 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1004 # Change back to "global"
1007 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1008 m["groupType"] = MessageElement(
1009 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1010 FLAG_MOD_REPLACE, "groupType")
1013 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1014 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1015 self.assertTrue(len(res1) == 1)
1016 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1017 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1019 # Change back to "universal"
1022 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1023 m["groupType"] = MessageElement(
1024 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1025 FLAG_MOD_REPLACE, "groupType")
1028 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1029 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1030 self.assertTrue(len(res1) == 1)
1031 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1032 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1037 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1038 m["groupType"] = MessageElement(
1039 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1040 FLAG_MOD_REPLACE, "groupType")
1043 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1044 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1045 self.assertTrue(len(res1) == 1)
1046 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1047 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1049 # Change to "global" (shouldn't work)
1053 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1054 m["groupType"] = MessageElement(
1055 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1056 FLAG_MOD_REPLACE, "groupType")
1059 except LdbError, (num, _):
1060 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1062 # Change back to "universal"
1064 # Try to add invalid member to group 1 - should be denied
1066 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1067 m["member"] = MessageElement(
1068 "cn=ldaptestuser3,cn=users," + self.base_dn,
1069 FLAG_MOD_ADD, "member")
1073 except LdbError, (num, _):
1074 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1076 # Make group 2 secondary
1078 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1079 m["groupType"] = MessageElement(
1080 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1081 FLAG_MOD_REPLACE, "groupType")
1084 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1085 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1086 self.assertTrue(len(res1) == 1)
1087 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1088 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1090 # Change back to "global"
1093 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1094 m["groupType"] = MessageElement(
1095 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1096 FLAG_MOD_REPLACE, "groupType")
1099 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1100 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1101 self.assertTrue(len(res1) == 1)
1102 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1103 ATYPE_DISTRIBUTION_GLOBAL_GROUP)
1105 # Both group types: this performs only random checks - all possibilities
1106 # would require too much code.
1108 # Default is "global group"
1111 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1112 m["groupType"] = MessageElement(
1113 str(GTYPE_SECURITY_GLOBAL_GROUP),
1114 FLAG_MOD_REPLACE, "groupType")
1117 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1118 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1119 self.assertTrue(len(res1) == 1)
1120 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1121 ATYPE_SECURITY_GLOBAL_GROUP)
1123 # Change to "local" (shouldn't work)
1127 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1128 m["groupType"] = MessageElement(
1129 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1130 FLAG_MOD_REPLACE, "groupType")
1133 except LdbError, (num, _):
1134 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1136 # Change to "universal"
1139 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1140 m["groupType"] = MessageElement(
1141 str(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP),
1142 FLAG_MOD_REPLACE, "groupType")
1145 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1146 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1147 self.assertTrue(len(res1) == 1)
1148 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1149 ATYPE_DISTRIBUTION_UNIVERSAL_GROUP)
1151 # Change back to "global"
1154 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1155 m["groupType"] = MessageElement(
1156 str(GTYPE_SECURITY_GLOBAL_GROUP),
1157 FLAG_MOD_REPLACE, "groupType")
1160 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1161 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1162 self.assertTrue(len(res1) == 1)
1163 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1164 ATYPE_SECURITY_GLOBAL_GROUP)
1166 # Change back to "universal"
1169 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1170 m["groupType"] = MessageElement(
1171 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1172 FLAG_MOD_REPLACE, "groupType")
1175 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1176 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1177 self.assertTrue(len(res1) == 1)
1178 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1179 ATYPE_SECURITY_UNIVERSAL_GROUP)
1184 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1185 m["groupType"] = MessageElement(
1186 str(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP),
1187 FLAG_MOD_REPLACE, "groupType")
1190 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1191 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1192 self.assertTrue(len(res1) == 1)
1193 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1194 ATYPE_DISTRIBUTION_LOCAL_GROUP)
1196 # Change to "global" (shouldn't work)
1200 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1201 m["groupType"] = MessageElement(
1202 str(GTYPE_DISTRIBUTION_GLOBAL_GROUP),
1203 FLAG_MOD_REPLACE, "groupType")
1206 except LdbError, (num, _):
1207 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1209 # Change back to "universal"
1212 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1213 m["groupType"] = MessageElement(
1214 str(GTYPE_SECURITY_UNIVERSAL_GROUP),
1215 FLAG_MOD_REPLACE, "groupType")
1218 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1219 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1220 self.assertTrue(len(res1) == 1)
1221 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1222 ATYPE_SECURITY_UNIVERSAL_GROUP)
1224 # Change back to "global"
1227 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1228 m["groupType"] = MessageElement(
1229 str(GTYPE_SECURITY_GLOBAL_GROUP),
1230 FLAG_MOD_REPLACE, "groupType")
1233 res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1234 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1235 self.assertTrue(len(res1) == 1)
1236 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1237 ATYPE_SECURITY_GLOBAL_GROUP)
1239 self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1241 def test_userAccountControl(self):
1242 """Test the userAccountControl behaviour"""
1243 print "Testing userAccountControl behaviour\n"
1245 # With a user object
1249 # As user you can only set a normal account.
1250 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1252 # With SYSTEM rights you can set a interdomain trust account.
1257 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1258 "objectclass": ["user", "person"],
1259 "userAccountControl": "0"})
1261 except LdbError, (num, _):
1262 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1263 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1265 # This has to wait until s4 supports it (needs a password module change)
1268 # "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1269 # "objectclass": ["user", "person"],
1270 # "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1272 # except LdbError, (num, _):
1273 # self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1274 # self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1277 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1278 "objectclass": ["user", "person"],
1279 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1281 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1282 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1283 self.assertTrue(len(res1) == 1)
1284 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1285 ATYPE_NORMAL_ACCOUNT)
1286 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1290 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1291 "objectclass": ["user", "person"],
1292 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1294 except LdbError, (num, _):
1295 self.assertEquals(num, ERR_OTHER)
1296 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1298 # This isn't supported yet in s4
1301 # "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1302 # "objectclass": ["user", "person"],
1303 # "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1305 # except LdbError, (num, _):
1306 # self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1307 # self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1311 # "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1312 # "objectclass": ["user", "person"],
1313 # "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1314 # except LdbError, (num, _):
1315 # self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1316 # self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1318 # This isn't supported yet in s4 - needs ACL module adaption
1321 # "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1322 # "objectclass": ["user", "person"],
1323 # "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1325 # except LdbError, (num, _):
1326 # self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1327 # self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1332 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1333 "objectclass": ["user", "person"]})
1335 # After creation we should have a normal account
1336 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1337 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1338 self.assertTrue(len(res1) == 1)
1339 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1340 ATYPE_NORMAL_ACCOUNT)
1342 # As user you can only switch from a normal account to a workstation
1343 # trust account and back.
1344 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1346 # With SYSTEM rights you can switch to a interdomain trust account.
1351 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1352 m["userAccountControl"] = MessageElement("0",
1353 FLAG_MOD_REPLACE, "userAccountControl")
1355 except LdbError, (num, _):
1356 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1358 # This has to wait until s4 supports it (needs a password module change)
1361 # m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1362 # m["userAccountControl"] = MessageElement(
1363 # str(UF_NORMAL_ACCOUNT),
1364 # FLAG_MOD_REPLACE, "userAccountControl")
1366 # except LdbError, (num, _):
1367 # self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1370 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1371 m["userAccountControl"] = MessageElement(
1372 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1373 FLAG_MOD_REPLACE, "userAccountControl")
1376 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1377 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1378 self.assertTrue(len(res1) == 1)
1379 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1380 ATYPE_NORMAL_ACCOUNT)
1384 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1385 m["userAccountControl"] = MessageElement(
1386 str(UF_TEMP_DUPLICATE_ACCOUNT),
1387 FLAG_MOD_REPLACE, "userAccountControl")
1390 except LdbError, (num, _):
1391 self.assertEquals(num, ERR_OTHER)
1393 # This isn't supported yet in s4
1396 # m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1397 # m["userAccountControl"] = MessageElement(
1398 # str(UF_SERVER_TRUST_ACCOUNT),
1399 # FLAG_MOD_REPLACE, "userAccountControl")
1402 # except LdbError, (num, _):
1403 # self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1406 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1407 m["userAccountControl"] = MessageElement(
1408 str(UF_WORKSTATION_TRUST_ACCOUNT),
1409 FLAG_MOD_REPLACE, "userAccountControl")
1412 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1413 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1414 self.assertTrue(len(res1) == 1)
1415 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1416 ATYPE_WORKSTATION_TRUST)
1419 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1420 m["userAccountControl"] = MessageElement(
1421 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1422 FLAG_MOD_REPLACE, "userAccountControl")
1425 res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1426 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1427 self.assertTrue(len(res1) == 1)
1428 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1429 ATYPE_NORMAL_ACCOUNT)
1431 # This isn't supported yet in s4 - needs ACL module adaption
1434 # m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1435 # m["userAccountControl"] = MessageElement(
1436 # str(UF_INTERDOMAIN_TRUST_ACCOUNT),
1437 # FLAG_MOD_REPLACE, "userAccountControl")
1440 # except LdbError, (num, _):
1441 # self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1443 # With a computer object
1447 # As computer you can set a normal account and a server trust account.
1448 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1450 # With SYSTEM rights you can set a interdomain trust account.
1455 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1456 "objectclass": ["computer"],
1457 "userAccountControl": "0"})
1459 except LdbError, (num, _):
1460 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1461 self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1463 # This has to wait until s4 supports it (needs a password module change)
1466 # "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1467 # "objectclass": ["computer"],
1468 # "userAccountControl": str(UF_NORMAL_ACCOUNT)})
1470 # except LdbError, (num, _):
1471 # self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1472 # self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1475 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1476 "objectclass": ["computer"],
1477 "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD)})
1479 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1480 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1481 self.assertTrue(len(res1) == 1)
1482 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1483 ATYPE_NORMAL_ACCOUNT)
1484 self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1488 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1489 "objectclass": ["computer"],
1490 "userAccountControl": str(UF_TEMP_DUPLICATE_ACCOUNT)})
1492 except LdbError, (num, _):
1493 self.assertEquals(num, ERR_OTHER)
1494 self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1497 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1498 "objectclass": ["computer"],
1499 "userAccountControl": str(UF_SERVER_TRUST_ACCOUNT)})
1501 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1502 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1503 self.assertTrue(len(res1) == 1)
1504 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1505 ATYPE_WORKSTATION_TRUST)
1506 self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1510 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1511 "objectclass": ["computer"],
1512 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT)})
1513 except LdbError, (num, _):
1514 self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1515 self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1517 # This isn't supported yet in s4 - needs ACL module adaption
1520 # "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1521 # "objectclass": ["computer"],
1522 # "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
1524 # except LdbError, (num, _):
1525 # self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1526 # self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1531 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1532 "objectclass": ["computer"]})
1534 # After creation we should have a normal account
1535 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1536 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1537 self.assertTrue(len(res1) == 1)
1538 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1539 ATYPE_NORMAL_ACCOUNT)
1541 # As computer you can switch from a normal account to a workstation
1542 # or server trust account and back (also swapping between trust
1543 # accounts is allowed).
1544 # The UF_PASSWD_NOTREQD flag is needed since we haven't requested a
1546 # With SYSTEM rights you can switch to a interdomain trust account.
1551 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1552 m["userAccountControl"] = MessageElement("0",
1553 FLAG_MOD_REPLACE, "userAccountControl")
1555 except LdbError, (num, _):
1556 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1558 # This has to wait until s4 supports it (needs a password module change)
1561 # m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1562 # m["userAccountControl"] = MessageElement(
1563 # str(UF_NORMAL_ACCOUNT),
1564 # FLAG_MOD_REPLACE, "userAccountControl")
1566 # except LdbError, (num, _):
1567 # self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1570 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1571 m["userAccountControl"] = MessageElement(
1572 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1573 FLAG_MOD_REPLACE, "userAccountControl")
1576 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1577 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1578 self.assertTrue(len(res1) == 1)
1579 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1580 ATYPE_NORMAL_ACCOUNT)
1584 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1585 m["userAccountControl"] = MessageElement(
1586 str(UF_TEMP_DUPLICATE_ACCOUNT),
1587 FLAG_MOD_REPLACE, "userAccountControl")
1590 except LdbError, (num, _):
1591 self.assertEquals(num, ERR_OTHER)
1594 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1595 m["userAccountControl"] = MessageElement(
1596 str(UF_SERVER_TRUST_ACCOUNT),
1597 FLAG_MOD_REPLACE, "userAccountControl")
1600 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1601 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1602 self.assertTrue(len(res1) == 1)
1603 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1604 ATYPE_WORKSTATION_TRUST)
1607 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1608 m["userAccountControl"] = MessageElement(
1609 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1610 FLAG_MOD_REPLACE, "userAccountControl")
1613 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1614 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1615 self.assertTrue(len(res1) == 1)
1616 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1617 ATYPE_NORMAL_ACCOUNT)
1620 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1621 m["userAccountControl"] = MessageElement(
1622 str(UF_WORKSTATION_TRUST_ACCOUNT),
1623 FLAG_MOD_REPLACE, "userAccountControl")
1626 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1627 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1628 self.assertTrue(len(res1) == 1)
1629 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1630 ATYPE_WORKSTATION_TRUST)
1633 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1634 m["userAccountControl"] = MessageElement(
1635 str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD),
1636 FLAG_MOD_REPLACE, "userAccountControl")
1639 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1640 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1641 self.assertTrue(len(res1) == 1)
1642 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1643 ATYPE_NORMAL_ACCOUNT)
1646 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1647 m["userAccountControl"] = MessageElement(
1648 str(UF_SERVER_TRUST_ACCOUNT),
1649 FLAG_MOD_REPLACE, "userAccountControl")
1652 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1653 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1654 self.assertTrue(len(res1) == 1)
1655 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1656 ATYPE_WORKSTATION_TRUST)
1659 m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1660 m["userAccountControl"] = MessageElement(
1661 str(UF_WORKSTATION_TRUST_ACCOUNT),
1662 FLAG_MOD_REPLACE, "userAccountControl")
1665 res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
1666 scope=SCOPE_BASE, attrs=["sAMAccountType"])
1667 self.assertTrue(len(res1) == 1)
1668 self.assertEquals(int(res1[0]["sAMAccountType"][0]),
1669 ATYPE_WORKSTATION_TRUST)
1671 # This isn't supported yet in s4 - needs ACL module adaption
1674 # m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1675 # m["userAccountControl"] = MessageElement(
1676 # str(UF_INTERDOMAIN_TRUST_ACCOUNT),
1677 # FLAG_MOD_REPLACE, "userAccountControl")
1680 # except LdbError, (num, _):
1681 # self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1683 self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1684 self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1686 if not "://" in host:
1687 if os.path.isfile(host):
1688 host = "tdb://%s" % host
1690 host = "ldap://%s" % host
1692 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
1693 if not "tdb://" in host:
1694 gc_ldb = Ldb("%s:3268" % host, credentials=creds,
1695 session_info=system_session(), lp=lp)
1699 runner = SubunitTestRunner()
1701 if not runner.run(unittest.makeSuite(SamTests)).wasSuccessful():