2 # -*- coding: utf-8 -*-
3 # This is unit with tests for LDAP access checks
9 sys.path.insert(0, "bin/python")
12 from samba.tests.subunitrun import SubunitOptions, TestProgram
14 import samba.getopt as options
15 from samba.join import dc_join
18 SCOPE_BASE, SCOPE_SUBTREE, LdbError, ERR_NO_SUCH_OBJECT,
19 ERR_UNWILLING_TO_PERFORM, ERR_INSUFFICIENT_ACCESS_RIGHTS)
20 from ldb import ERR_CONSTRAINT_VIOLATION
21 from ldb import ERR_OPERATIONS_ERROR
22 from ldb import Message, MessageElement, Dn
23 from ldb import FLAG_MOD_REPLACE, FLAG_MOD_ADD, FLAG_MOD_DELETE
24 from samba.dcerpc import security, drsuapi, misc
26 from samba.auth import system_session
27 from samba import gensec, sd_utils
28 from samba.samdb import SamDB
29 from samba.credentials import Credentials, DONT_USE_KERBEROS
31 from samba.tests import delete_force
34 parser = optparse.OptionParser("acl.py [options] <host>")
35 sambaopts = options.SambaOptions(parser)
36 parser.add_option_group(sambaopts)
37 parser.add_option_group(options.VersionOptions(parser))
39 # use command line creds if available
40 credopts = options.CredentialsOptions(parser)
41 parser.add_option_group(credopts)
42 subunitopts = SubunitOptions(parser)
43 parser.add_option_group(subunitopts)
45 opts, args = parser.parse_args()
53 ldaphost = "ldap://%s" % host
56 start = host.rindex("://")
57 host = host.lstrip(start+3)
59 lp = sambaopts.get_loadparm()
60 creds = credopts.get_credentials(lp)
61 creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
67 class AclTests(samba.tests.TestCase):
70 super(AclTests, self).setUp()
71 self.ldb_admin = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp)
72 self.base_dn = self.ldb_admin.domain_dn()
73 self.domain_sid = security.dom_sid(self.ldb_admin.get_domain_sid())
74 self.user_pass = "samba123@"
75 self.configuration_dn = self.ldb_admin.get_config_basedn().get_linearized()
76 self.sd_utils = sd_utils.SDUtils(self.ldb_admin)
77 self.addCleanup(self.delete_admin_connection)
78 #used for anonymous login
79 self.creds_tmp = Credentials()
80 self.creds_tmp.set_username("")
81 self.creds_tmp.set_password("")
82 self.creds_tmp.set_domain(creds.get_domain())
83 self.creds_tmp.set_realm(creds.get_realm())
84 self.creds_tmp.set_workstation(creds.get_workstation())
85 print "baseDN: %s" % self.base_dn
87 def get_user_dn(self, name):
88 return "CN=%s,CN=Users,%s" % (name, self.base_dn)
90 def get_ldb_connection(self, target_username, target_password):
91 creds_tmp = Credentials()
92 creds_tmp.set_username(target_username)
93 creds_tmp.set_password(target_password)
94 creds_tmp.set_domain(creds.get_domain())
95 creds_tmp.set_realm(creds.get_realm())
96 creds_tmp.set_workstation(creds.get_workstation())
97 creds_tmp.set_gensec_features(creds_tmp.get_gensec_features()
98 | gensec.FEATURE_SEAL)
99 creds_tmp.set_kerberos_state(DONT_USE_KERBEROS) # kinit is too expensive to use in a tight loop
100 ldb_target = SamDB(url=ldaphost, credentials=creds_tmp, lp=lp)
103 # Test if we have any additional groups for users than default ones
104 def assert_user_no_group_member(self, username):
105 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % self.get_user_dn(username))
107 self.assertEqual(res[0]["memberOf"][0], "")
113 def delete_admin_connection(self):
117 #tests on ldap add operations
118 class AclAddTests(AclTests):
121 super(AclAddTests, self).setUp()
122 # Domain admin that will be creator of OU parent-child structure
123 self.usr_admin_owner = "acl_add_user1"
124 # Second domain admin that will not be creator of OU parent-child structure
125 self.usr_admin_not_owner = "acl_add_user2"
127 self.regular_user = "acl_add_user3"
128 self.test_user1 = "test_add_user1"
129 self.test_group1 = "test_add_group1"
130 self.ou1 = "OU=test_add_ou1"
131 self.ou2 = "OU=test_add_ou2,%s" % self.ou1
132 self.ldb_admin.newuser(self.usr_admin_owner, self.user_pass)
133 self.ldb_admin.newuser(self.usr_admin_not_owner, self.user_pass)
134 self.ldb_admin.newuser(self.regular_user, self.user_pass)
136 # add admins to the Domain Admins group
137 self.ldb_admin.add_remove_group_members("Domain Admins", [self.usr_admin_owner],
138 add_members_operation=True)
139 self.ldb_admin.add_remove_group_members("Domain Admins", [self.usr_admin_not_owner],
140 add_members_operation=True)
142 self.ldb_owner = self.get_ldb_connection(self.usr_admin_owner, self.user_pass)
143 self.ldb_notowner = self.get_ldb_connection(self.usr_admin_not_owner, self.user_pass)
144 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
147 super(AclAddTests, self).tearDown()
148 delete_force(self.ldb_admin, "CN=%s,%s,%s" %
149 (self.test_user1, self.ou2, self.base_dn))
150 delete_force(self.ldb_admin, "CN=%s,%s,%s" %
151 (self.test_group1, self.ou2, self.base_dn))
152 delete_force(self.ldb_admin, "%s,%s" % (self.ou2, self.base_dn))
153 delete_force(self.ldb_admin, "%s,%s" % (self.ou1, self.base_dn))
154 delete_force(self.ldb_admin, self.get_user_dn(self.usr_admin_owner))
155 delete_force(self.ldb_admin, self.get_user_dn(self.usr_admin_not_owner))
156 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
157 delete_force(self.ldb_admin, self.get_user_dn("test_add_anonymous"))
159 del self.ldb_notowner
163 # Make sure top OU is deleted (and so everything under it)
164 def assert_top_ou_deleted(self):
165 res = self.ldb_admin.search(self.base_dn,
166 expression="(distinguishedName=%s,%s)" % (
167 "OU=test_add_ou1", self.base_dn))
168 self.assertEqual(len(res), 0)
170 def test_add_u1(self):
171 """Testing OU with the rights of Doman Admin not creator of the OU """
172 self.assert_top_ou_deleted()
173 # Change descriptor for top level OU
174 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
175 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
176 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.usr_admin_not_owner))
177 mod = "(D;CI;WPCC;;;%s)" % str(user_sid)
178 self.sd_utils.dacl_add_ace("OU=test_add_ou1," + self.base_dn, mod)
179 # Test user and group creation with another domain admin's credentials
180 self.ldb_notowner.newuser(self.test_user1, self.user_pass, userou=self.ou2)
181 self.ldb_notowner.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
182 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
183 # Make sure we HAVE created the two objects -- user and group
184 # !!! We should not be able to do that, but however beacuse of ACE ordering our inherited Deny ACE
185 # !!! comes after explicit (A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA) that comes from somewhere
186 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s,%s)" % ("CN=test_add_user1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn))
187 self.assertTrue(len(res) > 0)
188 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s,%s)" % ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn))
189 self.assertTrue(len(res) > 0)
191 def test_add_u2(self):
192 """Testing OU with the regular user that has no rights granted over the OU """
193 self.assert_top_ou_deleted()
194 # Create a parent-child OU structure with domain admin credentials
195 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
196 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
197 # Test user and group creation with regular user credentials
199 self.ldb_user.newuser(self.test_user1, self.user_pass, userou=self.ou2)
200 self.ldb_user.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
201 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
202 except LdbError as e:
204 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
207 # Make sure we HAVEN'T created any of two objects -- user or group
208 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s,%s)" % ("CN=test_add_user1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn))
209 self.assertEqual(len(res), 0)
210 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s,%s)" % ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn))
211 self.assertEqual(len(res), 0)
213 def test_add_u3(self):
214 """Testing OU with the rights of regular user granted the right 'Create User child objects' """
215 self.assert_top_ou_deleted()
216 # Change descriptor for top level OU
217 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
218 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
219 mod = "(OA;CI;CC;bf967aba-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid)
220 self.sd_utils.dacl_add_ace("OU=test_add_ou1," + self.base_dn, mod)
221 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
222 # Test user and group creation with granted user only to one of the objects
223 self.ldb_user.newuser(self.test_user1, self.user_pass, userou=self.ou2, setpassword=False)
225 self.ldb_user.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
226 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
227 except LdbError as e1:
229 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
232 # Make sure we HAVE created the one of two objects -- user
233 res = self.ldb_admin.search(self.base_dn,
234 expression="(distinguishedName=%s,%s)" %
235 ("CN=test_add_user1,OU=test_add_ou2,OU=test_add_ou1",
237 self.assertNotEqual(len(res), 0)
238 res = self.ldb_admin.search(self.base_dn,
239 expression="(distinguishedName=%s,%s)" %
240 ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1",
242 self.assertEqual(len(res), 0)
244 def test_add_u4(self):
245 """ 4 Testing OU with the rights of Doman Admin creator of the OU"""
246 self.assert_top_ou_deleted()
247 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
248 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
249 self.ldb_owner.newuser(self.test_user1, self.user_pass, userou=self.ou2)
250 self.ldb_owner.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
251 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
252 # Make sure we have successfully created the two objects -- user and group
253 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s,%s)" % ("CN=test_add_user1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn))
254 self.assertTrue(len(res) > 0)
255 res = self.ldb_admin.search(self.base_dn,
256 expression="(distinguishedName=%s,%s)" % ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn))
257 self.assertTrue(len(res) > 0)
259 def test_add_anonymous(self):
260 """Test add operation with anonymous user"""
261 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
263 anonymous.newuser("test_add_anonymous", self.user_pass)
264 except LdbError as e2:
266 self.assertEquals(num, ERR_OPERATIONS_ERROR)
270 #tests on ldap modify operations
271 class AclModifyTests(AclTests):
274 super(AclModifyTests, self).setUp()
275 self.user_with_wp = "acl_mod_user1"
276 self.user_with_sm = "acl_mod_user2"
277 self.user_with_group_sm = "acl_mod_user3"
278 self.ldb_admin.newuser(self.user_with_wp, self.user_pass)
279 self.ldb_admin.newuser(self.user_with_sm, self.user_pass)
280 self.ldb_admin.newuser(self.user_with_group_sm, self.user_pass)
281 self.ldb_user = self.get_ldb_connection(self.user_with_wp, self.user_pass)
282 self.ldb_user2 = self.get_ldb_connection(self.user_with_sm, self.user_pass)
283 self.ldb_user3 = self.get_ldb_connection(self.user_with_group_sm, self.user_pass)
284 self.user_sid = self.sd_utils.get_object_sid( self.get_user_dn(self.user_with_wp))
285 self.ldb_admin.newgroup("test_modify_group2", grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
286 self.ldb_admin.newgroup("test_modify_group3", grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
287 self.ldb_admin.newuser("test_modify_user2", self.user_pass)
290 super(AclModifyTests, self).tearDown()
291 delete_force(self.ldb_admin, self.get_user_dn("test_modify_user1"))
292 delete_force(self.ldb_admin, "CN=test_modify_group1,CN=Users," + self.base_dn)
293 delete_force(self.ldb_admin, "CN=test_modify_group2,CN=Users," + self.base_dn)
294 delete_force(self.ldb_admin, "CN=test_modify_group3,CN=Users," + self.base_dn)
295 delete_force(self.ldb_admin, "OU=test_modify_ou1," + self.base_dn)
296 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_wp))
297 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_sm))
298 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_group_sm))
299 delete_force(self.ldb_admin, self.get_user_dn("test_modify_user2"))
300 delete_force(self.ldb_admin, self.get_user_dn("test_anonymous"))
306 def test_modify_u1(self):
307 """5 Modify one attribute if you have DS_WRITE_PROPERTY for it"""
308 mod = "(OA;;WP;bf967953-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.user_sid)
309 # First test object -- User
310 print "Testing modify on User object"
311 self.ldb_admin.newuser("test_modify_user1", self.user_pass)
312 self.sd_utils.dacl_add_ace(self.get_user_dn("test_modify_user1"), mod)
314 dn: """ + self.get_user_dn("test_modify_user1") + """
317 displayName: test_changed"""
318 self.ldb_user.modify_ldif(ldif)
319 res = self.ldb_admin.search(self.base_dn,
320 expression="(distinguishedName=%s)" % self.get_user_dn("test_modify_user1"))
321 self.assertEqual(res[0]["displayName"][0], "test_changed")
322 # Second test object -- Group
323 print "Testing modify on Group object"
324 self.ldb_admin.newgroup("test_modify_group1",
325 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
326 self.sd_utils.dacl_add_ace("CN=test_modify_group1,CN=Users," + self.base_dn, mod)
328 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
331 displayName: test_changed"""
332 self.ldb_user.modify_ldif(ldif)
333 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % str("CN=test_modify_group1,CN=Users," + self.base_dn))
334 self.assertEqual(res[0]["displayName"][0], "test_changed")
335 # Third test object -- Organizational Unit
336 print "Testing modify on OU object"
337 #delete_force(self.ldb_admin, "OU=test_modify_ou1," + self.base_dn)
338 self.ldb_admin.create_ou("OU=test_modify_ou1," + self.base_dn)
339 self.sd_utils.dacl_add_ace("OU=test_modify_ou1," + self.base_dn, mod)
341 dn: OU=test_modify_ou1,""" + self.base_dn + """
344 displayName: test_changed"""
345 self.ldb_user.modify_ldif(ldif)
346 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % str("OU=test_modify_ou1," + self.base_dn))
347 self.assertEqual(res[0]["displayName"][0], "test_changed")
349 def test_modify_u2(self):
350 """6 Modify two attributes as you have DS_WRITE_PROPERTY granted only for one of them"""
351 mod = "(OA;;WP;bf967953-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.user_sid)
352 # First test object -- User
353 print "Testing modify on User object"
354 #delete_force(self.ldb_admin, self.get_user_dn("test_modify_user1"))
355 self.ldb_admin.newuser("test_modify_user1", self.user_pass)
356 self.sd_utils.dacl_add_ace(self.get_user_dn("test_modify_user1"), mod)
357 # Modify on attribute you have rights for
359 dn: """ + self.get_user_dn("test_modify_user1") + """
362 displayName: test_changed"""
363 self.ldb_user.modify_ldif(ldif)
364 res = self.ldb_admin.search(self.base_dn,
365 expression="(distinguishedName=%s)" %
366 self.get_user_dn("test_modify_user1"))
367 self.assertEqual(res[0]["displayName"][0], "test_changed")
368 # Modify on attribute you do not have rights for granted
370 dn: """ + self.get_user_dn("test_modify_user1") + """
373 url: www.samba.org"""
375 self.ldb_user.modify_ldif(ldif)
376 except LdbError as e3:
378 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
380 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
382 # Second test object -- Group
383 print "Testing modify on Group object"
384 self.ldb_admin.newgroup("test_modify_group1",
385 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
386 self.sd_utils.dacl_add_ace("CN=test_modify_group1,CN=Users," + self.base_dn, mod)
388 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
391 displayName: test_changed"""
392 self.ldb_user.modify_ldif(ldif)
393 res = self.ldb_admin.search(self.base_dn,
394 expression="(distinguishedName=%s)" %
395 str("CN=test_modify_group1,CN=Users," + self.base_dn))
396 self.assertEqual(res[0]["displayName"][0], "test_changed")
397 # Modify on attribute you do not have rights for granted
399 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
402 url: www.samba.org"""
404 self.ldb_user.modify_ldif(ldif)
405 except LdbError as e4:
407 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
409 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
411 # Modify on attribute you do not have rights for granted while also modifying something you do have rights for
413 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
418 displayName: test_changed"""
420 self.ldb_user.modify_ldif(ldif)
421 except LdbError as e5:
423 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
425 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
427 # Second test object -- Organizational Unit
428 print "Testing modify on OU object"
429 self.ldb_admin.create_ou("OU=test_modify_ou1," + self.base_dn)
430 self.sd_utils.dacl_add_ace("OU=test_modify_ou1," + self.base_dn, mod)
432 dn: OU=test_modify_ou1,""" + self.base_dn + """
435 displayName: test_changed"""
436 self.ldb_user.modify_ldif(ldif)
437 res = self.ldb_admin.search(self.base_dn,
438 expression="(distinguishedName=%s)" % str("OU=test_modify_ou1,"
440 self.assertEqual(res[0]["displayName"][0], "test_changed")
441 # Modify on attribute you do not have rights for granted
443 dn: OU=test_modify_ou1,""" + self.base_dn + """
446 url: www.samba.org"""
448 self.ldb_user.modify_ldif(ldif)
449 except LdbError as e6:
451 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
453 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
456 def test_modify_u3(self):
457 """7 Modify one attribute as you have no what so ever rights granted"""
458 # First test object -- User
459 print "Testing modify on User object"
460 self.ldb_admin.newuser("test_modify_user1", self.user_pass)
461 # Modify on attribute you do not have rights for granted
463 dn: """ + self.get_user_dn("test_modify_user1") + """
466 url: www.samba.org"""
468 self.ldb_user.modify_ldif(ldif)
469 except LdbError as e7:
471 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
473 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
476 # Second test object -- Group
477 print "Testing modify on Group object"
478 self.ldb_admin.newgroup("test_modify_group1",
479 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
480 # Modify on attribute you do not have rights for granted
482 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
485 url: www.samba.org"""
487 self.ldb_user.modify_ldif(ldif)
488 except LdbError as e8:
490 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
492 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
495 # Second test object -- Organizational Unit
496 print "Testing modify on OU object"
497 #delete_force(self.ldb_admin, "OU=test_modify_ou1," + self.base_dn)
498 self.ldb_admin.create_ou("OU=test_modify_ou1," + self.base_dn)
499 # Modify on attribute you do not have rights for granted
501 dn: OU=test_modify_ou1,""" + self.base_dn + """
504 url: www.samba.org"""
506 self.ldb_user.modify_ldif(ldif)
507 except LdbError as e9:
509 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
511 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
515 def test_modify_u4(self):
516 """11 Grant WP to PRINCIPAL_SELF and test modify"""
518 dn: """ + self.get_user_dn(self.user_with_wp) + """
520 add: adminDescription
521 adminDescription: blah blah blah"""
523 self.ldb_user.modify_ldif(ldif)
524 except LdbError as e10:
526 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
528 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
531 mod = "(OA;;WP;bf967919-0de6-11d0-a285-00aa003049e2;;PS)"
532 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
533 # Modify on attribute you have rights for
534 self.ldb_user.modify_ldif(ldif)
535 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" \
536 % self.get_user_dn(self.user_with_wp), attrs=["adminDescription"] )
537 self.assertEqual(res[0]["adminDescription"][0], "blah blah blah")
539 def test_modify_u5(self):
540 """12 test self membership"""
542 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
545 Member: """ + self.get_user_dn(self.user_with_sm)
546 #the user has no rights granted, this should fail
548 self.ldb_user2.modify_ldif(ldif)
549 except LdbError as e11:
551 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
553 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
556 #grant self-membership, should be able to add himself
557 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.user_with_sm))
558 mod = "(OA;;SW;bf9679c0-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid)
559 self.sd_utils.dacl_add_ace("CN=test_modify_group2,CN=Users," + self.base_dn, mod)
560 self.ldb_user2.modify_ldif(ldif)
561 res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
562 % ("CN=test_modify_group2,CN=Users," + self.base_dn), attrs=["Member"])
563 self.assertEqual(res[0]["Member"][0], self.get_user_dn(self.user_with_sm))
566 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
569 Member: CN=test_modify_user2,CN=Users,""" + self.base_dn
571 self.ldb_user2.modify_ldif(ldif)
572 except LdbError as e12:
574 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
578 def test_modify_u6(self):
579 """13 test self membership"""
581 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
584 Member: """ + self.get_user_dn(self.user_with_sm) + """
585 Member: CN=test_modify_user2,CN=Users,""" + self.base_dn
587 #grant self-membership, should be able to add himself but not others at the same time
588 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.user_with_sm))
589 mod = "(OA;;SW;bf9679c0-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid)
590 self.sd_utils.dacl_add_ace("CN=test_modify_group2,CN=Users," + self.base_dn, mod)
592 self.ldb_user2.modify_ldif(ldif)
593 except LdbError as e13:
595 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
599 def test_modify_u7(self):
600 """13 User with WP modifying Member"""
601 #a second user is given write property permission
602 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.user_with_wp))
603 mod = "(A;;WP;;;%s)" % str(user_sid)
604 self.sd_utils.dacl_add_ace("CN=test_modify_group2,CN=Users," + self.base_dn, mod)
606 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
609 Member: """ + self.get_user_dn(self.user_with_wp)
610 self.ldb_user.modify_ldif(ldif)
611 res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
612 % ("CN=test_modify_group2,CN=Users," + self.base_dn), attrs=["Member"])
613 self.assertEqual(res[0]["Member"][0], self.get_user_dn(self.user_with_wp))
615 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
618 self.ldb_user.modify_ldif(ldif)
620 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
623 Member: CN=test_modify_user2,CN=Users,""" + self.base_dn
624 self.ldb_user.modify_ldif(ldif)
625 res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
626 % ("CN=test_modify_group2,CN=Users," + self.base_dn), attrs=["Member"])
627 self.assertEqual(res[0]["Member"][0], "CN=test_modify_user2,CN=Users," + self.base_dn)
629 def test_modify_anonymous(self):
630 """Test add operation with anonymous user"""
631 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
632 self.ldb_admin.newuser("test_anonymous", "samba123@")
634 m.dn = Dn(anonymous, self.get_user_dn("test_anonymous"))
636 m["description"] = MessageElement("sambauser2",
641 except LdbError as e14:
643 self.assertEquals(num, ERR_OPERATIONS_ERROR)
647 #enable these when we have search implemented
648 class AclSearchTests(AclTests):
651 super(AclSearchTests, self).setUp()
652 # Get the old "dSHeuristics" if it was set
653 dsheuristics = self.ldb_admin.get_dsheuristics()
654 # Reset the "dSHeuristics" as they were before
655 self.addCleanup(self.ldb_admin.set_dsheuristics, dsheuristics)
656 # Set the "dSHeuristics" to activate the correct "userPassword" behaviour
657 self.ldb_admin.set_dsheuristics("000000001")
658 # Get the old "minPwdAge"
659 minPwdAge = self.ldb_admin.get_minPwdAge()
660 # Reset the "minPwdAge" as it was before
661 self.addCleanup(self.ldb_admin.set_minPwdAge, minPwdAge)
662 # Set it temporarely to "0"
663 self.ldb_admin.set_minPwdAge("0")
665 self.u1 = "search_u1"
666 self.u2 = "search_u2"
667 self.u3 = "search_u3"
668 self.group1 = "group1"
669 self.ldb_admin.newuser(self.u1, self.user_pass)
670 self.ldb_admin.newuser(self.u2, self.user_pass)
671 self.ldb_admin.newuser(self.u3, self.user_pass)
672 self.ldb_admin.newgroup(self.group1, grouptype=samba.dsdb.GTYPE_SECURITY_GLOBAL_GROUP)
673 self.ldb_admin.add_remove_group_members(self.group1, [self.u2],
674 add_members_operation=True)
675 self.ldb_user = self.get_ldb_connection(self.u1, self.user_pass)
676 self.ldb_user2 = self.get_ldb_connection(self.u2, self.user_pass)
677 self.ldb_user3 = self.get_ldb_connection(self.u3, self.user_pass)
678 self.full_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
679 Dn(self.ldb_admin, "OU=ou1," + self.base_dn),
680 Dn(self.ldb_admin, "OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
681 Dn(self.ldb_admin, "OU=ou4,OU=ou2,OU=ou1," + self.base_dn),
682 Dn(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
683 Dn(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)]
684 self.user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.u1))
685 self.group_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.group1))
687 def create_clean_ou(self, object_dn):
688 """ Base repeating setup for unittests to follow """
689 res = self.ldb_admin.search(base=self.base_dn, scope=SCOPE_SUBTREE, \
690 expression="distinguishedName=%s" % object_dn)
691 # Make sure top testing OU has been deleted before starting the test
692 self.assertEqual(len(res), 0)
693 self.ldb_admin.create_ou(object_dn)
694 desc_sddl = self.sd_utils.get_sd_as_sddl(object_dn)
695 # Make sure there are inheritable ACEs initially
696 self.assertTrue("CI" in desc_sddl or "OI" in desc_sddl)
697 # Find and remove all inherit ACEs
698 res = re.findall("\(.*?\)", desc_sddl)
699 res = [x for x in res if ("CI" in x) or ("OI" in x)]
701 desc_sddl = desc_sddl.replace(x, "")
702 # Add flag 'protected' in both DACL and SACL so no inherit ACEs
703 # can propagate from above
704 # remove SACL, we are not interested
705 desc_sddl = desc_sddl.replace(":AI", ":AIP")
706 self.sd_utils.modify_sd_on_dn(object_dn, desc_sddl)
707 # Verify all inheritable ACEs are gone
708 desc_sddl = self.sd_utils.get_sd_as_sddl(object_dn)
709 self.assertFalse("CI" in desc_sddl)
710 self.assertFalse("OI" in desc_sddl)
713 super(AclSearchTests, self).tearDown()
714 delete_force(self.ldb_admin, "OU=test_search_ou2,OU=test_search_ou1," + self.base_dn)
715 delete_force(self.ldb_admin, "OU=test_search_ou1," + self.base_dn)
716 delete_force(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
717 delete_force(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
718 delete_force(self.ldb_admin, "OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
719 delete_force(self.ldb_admin, "OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
720 delete_force(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn)
721 delete_force(self.ldb_admin, "OU=ou1," + self.base_dn)
722 delete_force(self.ldb_admin, self.get_user_dn("search_u1"))
723 delete_force(self.ldb_admin, self.get_user_dn("search_u2"))
724 delete_force(self.ldb_admin, self.get_user_dn("search_u3"))
725 delete_force(self.ldb_admin, self.get_user_dn("group1"))
731 def test_search_anonymous1(self):
732 """Verify access of rootDSE with the correct request"""
733 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
734 res = anonymous.search("", expression="(objectClass=*)", scope=SCOPE_BASE)
735 self.assertEquals(len(res), 1)
736 #verify some of the attributes
737 #don't care about values
738 self.assertTrue("ldapServiceName" in res[0])
739 self.assertTrue("namingContexts" in res[0])
740 self.assertTrue("isSynchronized" in res[0])
741 self.assertTrue("dsServiceName" in res[0])
742 self.assertTrue("supportedSASLMechanisms" in res[0])
743 self.assertTrue("isGlobalCatalogReady" in res[0])
744 self.assertTrue("domainControllerFunctionality" in res[0])
745 self.assertTrue("serverName" in res[0])
747 def test_search_anonymous2(self):
748 """Make sure we cannot access anything else"""
749 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
751 res = anonymous.search("", expression="(objectClass=*)", scope=SCOPE_SUBTREE)
752 except LdbError as e15:
754 self.assertEquals(num, ERR_OPERATIONS_ERROR)
758 res = anonymous.search(self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE)
759 except LdbError as e16:
761 self.assertEquals(num, ERR_OPERATIONS_ERROR)
765 res = anonymous.search(anonymous.get_config_basedn(), expression="(objectClass=*)",
767 except LdbError as e17:
769 self.assertEquals(num, ERR_OPERATIONS_ERROR)
773 def test_search_anonymous3(self):
774 """Set dsHeuristics and repeat"""
775 self.ldb_admin.set_dsheuristics("0000002")
776 self.ldb_admin.create_ou("OU=test_search_ou1," + self.base_dn)
777 mod = "(A;CI;LC;;;AN)"
778 self.sd_utils.dacl_add_ace("OU=test_search_ou1," + self.base_dn, mod)
779 self.ldb_admin.create_ou("OU=test_search_ou2,OU=test_search_ou1," + self.base_dn)
780 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
781 res = anonymous.search("OU=test_search_ou2,OU=test_search_ou1," + self.base_dn,
782 expression="(objectClass=*)", scope=SCOPE_SUBTREE)
783 self.assertEquals(len(res), 1)
784 self.assertTrue("dn" in res[0])
785 self.assertTrue(res[0]["dn"] == Dn(self.ldb_admin,
786 "OU=test_search_ou2,OU=test_search_ou1," + self.base_dn))
787 res = anonymous.search(anonymous.get_config_basedn(), expression="(objectClass=*)",
789 self.assertEquals(len(res), 1)
790 self.assertTrue("dn" in res[0])
791 self.assertTrue(res[0]["dn"] == Dn(self.ldb_admin, self.configuration_dn))
793 def test_search1(self):
794 """Make sure users can see us if given LC to user and group"""
795 self.create_clean_ou("OU=ou1," + self.base_dn)
796 mod = "(A;;LC;;;%s)(A;;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
797 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
798 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
800 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
801 self.ldb_admin.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
802 self.ldb_admin.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
803 self.ldb_admin.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
804 self.ldb_admin.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
806 #regular users must see only ou1 and ou2
807 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
809 self.assertEquals(len(res), 2)
810 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
811 Dn(self.ldb_admin, "OU=ou1," + self.base_dn)]
813 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
814 self.assertEquals(sorted(res_list), sorted(ok_list))
816 #these users should see all ous
817 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
819 self.assertEquals(len(res), 6)
820 res_list = [ x["dn"] for x in res if x["dn"] in self.full_list ]
821 self.assertEquals(sorted(res_list), sorted(self.full_list))
823 res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
825 self.assertEquals(len(res), 6)
826 res_list = [ x["dn"] for x in res if x["dn"] in self.full_list ]
827 self.assertEquals(sorted(res_list), sorted(self.full_list))
829 def test_search2(self):
830 """Make sure users can't see us if access is explicitly denied"""
831 self.create_clean_ou("OU=ou1," + self.base_dn)
832 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn)
833 self.ldb_admin.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
834 self.ldb_admin.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
835 self.ldb_admin.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
836 self.ldb_admin.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
837 mod = "(D;;LC;;;%s)(D;;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
838 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
839 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
841 #this user should see all ous
842 res_list = [ x["dn"] for x in res if x["dn"] in self.full_list ]
843 self.assertEquals(sorted(res_list), sorted(self.full_list))
845 #these users should see ou1, 2, 5 and 6 but not 3 and 4
846 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
848 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
849 Dn(self.ldb_admin, "OU=ou1," + self.base_dn),
850 Dn(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
851 Dn(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)]
852 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
853 self.assertEquals(sorted(res_list), sorted(ok_list))
855 res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
857 self.assertEquals(len(res), 4)
858 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
859 self.assertEquals(sorted(res_list), sorted(ok_list))
861 def test_search3(self):
862 """Make sure users can't see ous if access is explicitly denied - 2"""
863 self.create_clean_ou("OU=ou1," + self.base_dn)
864 mod = "(A;CI;LC;;;%s)(A;CI;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
865 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
866 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
868 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
869 self.ldb_admin.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
870 self.ldb_admin.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
871 self.ldb_admin.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
872 self.ldb_admin.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
874 print "Testing correct behavior on nonaccessible search base"
876 self.ldb_user3.search("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
878 except LdbError as e18:
880 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
884 mod = "(D;;LC;;;%s)(D;;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
885 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
887 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
888 Dn(self.ldb_admin, "OU=ou1," + self.base_dn)]
890 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
892 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
893 self.assertEquals(sorted(res_list), sorted(ok_list))
895 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
896 Dn(self.ldb_admin, "OU=ou1," + self.base_dn),
897 Dn(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
898 Dn(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)]
900 #should not see ou3 and ou4, but should see ou5 and ou6
901 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
903 self.assertEquals(len(res), 4)
904 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
905 self.assertEquals(sorted(res_list), sorted(ok_list))
907 res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
909 self.assertEquals(len(res), 4)
910 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
911 self.assertEquals(sorted(res_list), sorted(ok_list))
913 def test_search4(self):
914 """There is no difference in visibility if the user is also creator"""
915 self.create_clean_ou("OU=ou1," + self.base_dn)
916 mod = "(A;CI;CC;;;%s)" % (str(self.user_sid))
917 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
918 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
920 self.ldb_user.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
921 self.ldb_user.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
922 self.ldb_user.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
923 self.ldb_user.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
924 self.ldb_user.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
926 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
927 Dn(self.ldb_admin, "OU=ou1," + self.base_dn)]
928 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
930 self.assertEquals(len(res), 2)
931 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
932 self.assertEquals(sorted(res_list), sorted(ok_list))
934 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
936 self.assertEquals(len(res), 2)
937 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
938 self.assertEquals(sorted(res_list), sorted(ok_list))
940 def test_search5(self):
941 """Make sure users can see only attributes they are allowed to see"""
942 self.create_clean_ou("OU=ou1," + self.base_dn)
943 mod = "(A;CI;LC;;;%s)" % (str(self.user_sid))
944 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
945 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
947 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
948 # assert user can only see dn
949 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
952 self.assertEquals(len(res), 1)
953 res_list = res[0].keys()
954 self.assertEquals(res_list, ok_list)
956 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
957 scope=SCOPE_BASE, attrs=["ou"])
959 self.assertEquals(len(res), 1)
960 res_list = res[0].keys()
961 self.assertEquals(res_list, ok_list)
963 #give read property on ou and assert user can only see dn and ou
964 mod = "(OA;;RP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % (str(self.user_sid))
965 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
966 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
967 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
969 ok_list = ['dn', 'ou']
970 self.assertEquals(len(res), 1)
971 res_list = res[0].keys()
972 self.assertEquals(sorted(res_list), sorted(ok_list))
974 #give read property on Public Information and assert user can see ou and other members
975 mod = "(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;%s)" % (str(self.user_sid))
976 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
977 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
978 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
981 ok_list = ['dn', 'objectClass', 'ou', 'distinguishedName', 'name', 'objectGUID', 'objectCategory']
982 res_list = res[0].keys()
983 self.assertEquals(sorted(res_list), sorted(ok_list))
985 def test_search6(self):
986 """If an attribute that cannot be read is used in a filter, it is as if the attribute does not exist"""
987 self.create_clean_ou("OU=ou1," + self.base_dn)
988 mod = "(A;CI;LCCC;;;%s)" % (str(self.user_sid))
989 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
990 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
992 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
993 self.ldb_user.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
995 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou3)",
997 #nothing should be returned as ou is not accessible
998 self.assertEquals(len(res), 0)
1000 #give read property on ou and assert user can only see dn and ou
1001 mod = "(OA;;RP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % (str(self.user_sid))
1002 self.sd_utils.dacl_add_ace("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, mod)
1003 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou3)",
1004 scope=SCOPE_SUBTREE)
1005 self.assertEquals(len(res), 1)
1006 ok_list = ['dn', 'ou']
1007 res_list = res[0].keys()
1008 self.assertEquals(sorted(res_list), sorted(ok_list))
1010 #give read property on Public Information and assert user can see ou and other members
1011 mod = "(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;%s)" % (str(self.user_sid))
1012 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
1013 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou2)",
1014 scope=SCOPE_SUBTREE)
1015 self.assertEquals(len(res), 1)
1016 ok_list = ['dn', 'objectClass', 'ou', 'distinguishedName', 'name', 'objectGUID', 'objectCategory']
1017 res_list = res[0].keys()
1018 self.assertEquals(sorted(res_list), sorted(ok_list))
1020 #tests on ldap delete operations
1021 class AclDeleteTests(AclTests):
1024 super(AclDeleteTests, self).setUp()
1025 self.regular_user = "acl_delete_user1"
1026 # Create regular user
1027 self.ldb_admin.newuser(self.regular_user, self.user_pass)
1028 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
1031 super(AclDeleteTests, self).tearDown()
1032 delete_force(self.ldb_admin, self.get_user_dn("test_delete_user1"))
1033 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
1034 delete_force(self.ldb_admin, self.get_user_dn("test_anonymous"))
1038 def test_delete_u1(self):
1039 """User is prohibited by default to delete another User object"""
1040 # Create user that we try to delete
1041 self.ldb_admin.newuser("test_delete_user1", self.user_pass)
1042 # Here delete User object should ALWAYS through exception
1044 self.ldb_user.delete(self.get_user_dn("test_delete_user1"))
1045 except LdbError as e19:
1047 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1051 def test_delete_u2(self):
1052 """User's group has RIGHT_DELETE to another User object"""
1053 user_dn = self.get_user_dn("test_delete_user1")
1054 # Create user that we try to delete
1055 self.ldb_admin.newuser("test_delete_user1", self.user_pass)
1056 mod = "(A;;SD;;;AU)"
1057 self.sd_utils.dacl_add_ace(user_dn, mod)
1058 # Try to delete User object
1059 self.ldb_user.delete(user_dn)
1060 res = self.ldb_admin.search(self.base_dn,
1061 expression="(distinguishedName=%s)" % user_dn)
1062 self.assertEqual(len(res), 0)
1064 def test_delete_u3(self):
1065 """User indentified by SID has RIGHT_DELETE to another User object"""
1066 user_dn = self.get_user_dn("test_delete_user1")
1067 # Create user that we try to delete
1068 self.ldb_admin.newuser("test_delete_user1", self.user_pass)
1069 mod = "(A;;SD;;;%s)" % self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1070 self.sd_utils.dacl_add_ace(user_dn, mod)
1071 # Try to delete User object
1072 self.ldb_user.delete(user_dn)
1073 res = self.ldb_admin.search(self.base_dn,
1074 expression="(distinguishedName=%s)" % user_dn)
1075 self.assertEqual(len(res), 0)
1077 def test_delete_anonymous(self):
1078 """Test add operation with anonymous user"""
1079 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
1080 self.ldb_admin.newuser("test_anonymous", "samba123@")
1083 anonymous.delete(self.get_user_dn("test_anonymous"))
1084 except LdbError as e20:
1086 self.assertEquals(num, ERR_OPERATIONS_ERROR)
1090 #tests on ldap rename operations
1091 class AclRenameTests(AclTests):
1094 super(AclRenameTests, self).setUp()
1095 self.regular_user = "acl_rename_user1"
1096 self.ou1 = "OU=test_rename_ou1"
1097 self.ou2 = "OU=test_rename_ou2"
1098 self.ou3 = "OU=test_rename_ou3,%s" % self.ou2
1099 self.testuser1 = "test_rename_user1"
1100 self.testuser2 = "test_rename_user2"
1101 self.testuser3 = "test_rename_user3"
1102 self.testuser4 = "test_rename_user4"
1103 self.testuser5 = "test_rename_user5"
1104 # Create regular user
1105 self.ldb_admin.newuser(self.regular_user, self.user_pass)
1106 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
1109 super(AclRenameTests, self).tearDown()
1111 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser1, self.ou3, self.base_dn))
1112 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser2, self.ou3, self.base_dn))
1113 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser5, self.ou3, self.base_dn))
1114 delete_force(self.ldb_admin, "%s,%s" % (self.ou3, self.base_dn))
1116 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser1, self.ou2, self.base_dn))
1117 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser2, self.ou2, self.base_dn))
1118 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser5, self.ou2, self.base_dn))
1119 delete_force(self.ldb_admin, "%s,%s" % (self.ou2, self.base_dn))
1121 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser1, self.ou1, self.base_dn))
1122 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser2, self.ou1, self.base_dn))
1123 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser5, self.ou1, self.base_dn))
1124 delete_force(self.ldb_admin, "OU=test_rename_ou3,%s,%s" % (self.ou1, self.base_dn))
1125 delete_force(self.ldb_admin, "%s,%s" % (self.ou1, self.base_dn))
1126 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
1130 def test_rename_u1(self):
1131 """Regular user fails to rename 'User object' within single OU"""
1132 # Create OU structure
1133 self.ldb_admin.create_ou("OU=test_rename_ou1," + self.base_dn)
1134 self.ldb_admin.newuser(self.testuser1, self.user_pass, userou=self.ou1)
1136 self.ldb_user.rename("CN=%s,%s,%s" % (self.testuser1, self.ou1, self.base_dn), \
1137 "CN=%s,%s,%s" % (self.testuser5, self.ou1, self.base_dn))
1138 except LdbError as e21:
1140 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1144 def test_rename_u2(self):
1145 """Grant WRITE_PROPERTY to AU so regular user can rename 'User object' within single OU"""
1146 ou_dn = "OU=test_rename_ou1," + self.base_dn
1147 user_dn = "CN=test_rename_user1," + ou_dn
1148 rename_user_dn = "CN=test_rename_user5," + ou_dn
1149 # Create OU structure
1150 self.ldb_admin.create_ou(ou_dn)
1151 self.ldb_admin.newuser(self.testuser1, self.user_pass, userou=self.ou1)
1152 mod = "(A;;WP;;;AU)"
1153 self.sd_utils.dacl_add_ace(user_dn, mod)
1154 # Rename 'User object' having WP to AU
1155 self.ldb_user.rename(user_dn, rename_user_dn)
1156 res = self.ldb_admin.search(self.base_dn,
1157 expression="(distinguishedName=%s)" % user_dn)
1158 self.assertEqual(len(res), 0)
1159 res = self.ldb_admin.search(self.base_dn,
1160 expression="(distinguishedName=%s)" % rename_user_dn)
1161 self.assertNotEqual(len(res), 0)
1163 def test_rename_u3(self):
1164 """Test rename with rights granted to 'User object' SID"""
1165 ou_dn = "OU=test_rename_ou1," + self.base_dn
1166 user_dn = "CN=test_rename_user1," + ou_dn
1167 rename_user_dn = "CN=test_rename_user5," + ou_dn
1168 # Create OU structure
1169 self.ldb_admin.create_ou(ou_dn)
1170 self.ldb_admin.newuser(self.testuser1, self.user_pass, userou=self.ou1)
1171 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1172 mod = "(A;;WP;;;%s)" % str(sid)
1173 self.sd_utils.dacl_add_ace(user_dn, mod)
1174 # Rename 'User object' having WP to AU
1175 self.ldb_user.rename(user_dn, rename_user_dn)
1176 res = self.ldb_admin.search(self.base_dn,
1177 expression="(distinguishedName=%s)" % user_dn)
1178 self.assertEqual(len(res), 0)
1179 res = self.ldb_admin.search(self.base_dn,
1180 expression="(distinguishedName=%s)" % rename_user_dn)
1181 self.assertNotEqual(len(res), 0)
1183 def test_rename_u4(self):
1184 """Rename 'User object' cross OU with WP, SD and CC right granted on reg. user to AU"""
1185 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1186 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1187 user_dn = "CN=test_rename_user2," + ou1_dn
1188 rename_user_dn = "CN=test_rename_user5," + ou2_dn
1189 # Create OU structure
1190 self.ldb_admin.create_ou(ou1_dn)
1191 self.ldb_admin.create_ou(ou2_dn)
1192 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1193 mod = "(A;;WPSD;;;AU)"
1194 self.sd_utils.dacl_add_ace(user_dn, mod)
1195 mod = "(A;;CC;;;AU)"
1196 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1197 # Rename 'User object' having SD and CC to AU
1198 self.ldb_user.rename(user_dn, rename_user_dn)
1199 res = self.ldb_admin.search(self.base_dn,
1200 expression="(distinguishedName=%s)" % user_dn)
1201 self.assertEqual(len(res), 0)
1202 res = self.ldb_admin.search(self.base_dn,
1203 expression="(distinguishedName=%s)" % rename_user_dn)
1204 self.assertNotEqual(len(res), 0)
1206 def test_rename_u5(self):
1207 """Test rename with rights granted to 'User object' SID"""
1208 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1209 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1210 user_dn = "CN=test_rename_user2," + ou1_dn
1211 rename_user_dn = "CN=test_rename_user5," + ou2_dn
1212 # Create OU structure
1213 self.ldb_admin.create_ou(ou1_dn)
1214 self.ldb_admin.create_ou(ou2_dn)
1215 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1216 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1217 mod = "(A;;WPSD;;;%s)" % str(sid)
1218 self.sd_utils.dacl_add_ace(user_dn, mod)
1219 mod = "(A;;CC;;;%s)" % str(sid)
1220 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1221 # Rename 'User object' having SD and CC to AU
1222 self.ldb_user.rename(user_dn, rename_user_dn)
1223 res = self.ldb_admin.search(self.base_dn,
1224 expression="(distinguishedName=%s)" % user_dn)
1225 self.assertEqual(len(res), 0)
1226 res = self.ldb_admin.search(self.base_dn,
1227 expression="(distinguishedName=%s)" % rename_user_dn)
1228 self.assertNotEqual(len(res), 0)
1230 def test_rename_u6(self):
1231 """Rename 'User object' cross OU with WP, DC and CC right granted on OU & user to AU"""
1232 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1233 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1234 user_dn = "CN=test_rename_user2," + ou1_dn
1235 rename_user_dn = "CN=test_rename_user2," + ou2_dn
1236 # Create OU structure
1237 self.ldb_admin.create_ou(ou1_dn)
1238 self.ldb_admin.create_ou(ou2_dn)
1239 #mod = "(A;CI;DCWP;;;AU)"
1240 mod = "(A;;DC;;;AU)"
1241 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1242 mod = "(A;;CC;;;AU)"
1243 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1244 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1245 mod = "(A;;WP;;;AU)"
1246 self.sd_utils.dacl_add_ace(user_dn, mod)
1247 # Rename 'User object' having SD and CC to AU
1248 self.ldb_user.rename(user_dn, rename_user_dn)
1249 res = self.ldb_admin.search(self.base_dn,
1250 expression="(distinguishedName=%s)" % user_dn)
1251 self.assertEqual(len(res), 0)
1252 res = self.ldb_admin.search(self.base_dn,
1253 expression="(distinguishedName=%s)" % rename_user_dn)
1254 self.assertNotEqual(len(res), 0)
1256 def test_rename_u7(self):
1257 """Rename 'User object' cross OU (second level) with WP, DC and CC right granted on OU to AU"""
1258 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1259 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1260 ou3_dn = "OU=test_rename_ou3," + ou2_dn
1261 user_dn = "CN=test_rename_user2," + ou1_dn
1262 rename_user_dn = "CN=test_rename_user5," + ou3_dn
1263 # Create OU structure
1264 self.ldb_admin.create_ou(ou1_dn)
1265 self.ldb_admin.create_ou(ou2_dn)
1266 self.ldb_admin.create_ou(ou3_dn)
1267 mod = "(A;CI;WPDC;;;AU)"
1268 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1269 mod = "(A;;CC;;;AU)"
1270 self.sd_utils.dacl_add_ace(ou3_dn, mod)
1271 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1272 # Rename 'User object' having SD and CC to AU
1273 self.ldb_user.rename(user_dn, rename_user_dn)
1274 res = self.ldb_admin.search(self.base_dn,
1275 expression="(distinguishedName=%s)" % user_dn)
1276 self.assertEqual(len(res), 0)
1277 res = self.ldb_admin.search(self.base_dn,
1278 expression="(distinguishedName=%s)" % rename_user_dn)
1279 self.assertNotEqual(len(res), 0)
1281 def test_rename_u8(self):
1282 """Test rename on an object with and without modify access on the RDN attribute"""
1283 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1284 ou2_dn = "OU=test_rename_ou2," + ou1_dn
1285 ou3_dn = "OU=test_rename_ou3," + ou1_dn
1286 # Create OU structure
1287 self.ldb_admin.create_ou(ou1_dn)
1288 self.ldb_admin.create_ou(ou2_dn)
1289 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1290 mod = "(OA;;WP;bf967a0e-0de6-11d0-a285-00aa003049e2;;%s)" % str(sid)
1291 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1292 mod = "(OD;;WP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % str(sid)
1293 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1295 self.ldb_user.rename(ou2_dn, ou3_dn)
1296 except LdbError as e22:
1298 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1300 # This rename operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
1302 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1303 mod = "(A;;WP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % str(sid)
1304 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1305 self.ldb_user.rename(ou2_dn, ou3_dn)
1306 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % ou2_dn)
1307 self.assertEqual(len(res), 0)
1308 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % ou3_dn)
1309 self.assertNotEqual(len(res), 0)
1311 def test_rename_u9(self):
1312 """Rename 'User object' cross OU, with explicit deny on sd and dc"""
1313 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1314 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1315 user_dn = "CN=test_rename_user2," + ou1_dn
1316 rename_user_dn = "CN=test_rename_user5," + ou2_dn
1317 # Create OU structure
1318 self.ldb_admin.create_ou(ou1_dn)
1319 self.ldb_admin.create_ou(ou2_dn)
1320 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1321 mod = "(D;;SD;;;DA)"
1322 self.sd_utils.dacl_add_ace(user_dn, mod)
1323 mod = "(D;;DC;;;DA)"
1324 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1325 # Rename 'User object' having SD and CC to AU
1327 self.ldb_admin.rename(user_dn, rename_user_dn)
1328 except LdbError as e23:
1330 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1333 #add an allow ace so we can delete this ou
1334 mod = "(A;;DC;;;DA)"
1335 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1338 #tests on Control Access Rights
1339 class AclCARTests(AclTests):
1342 super(AclCARTests, self).setUp()
1344 # Get the old "dSHeuristics" if it was set
1345 dsheuristics = self.ldb_admin.get_dsheuristics()
1346 # Reset the "dSHeuristics" as they were before
1347 self.addCleanup(self.ldb_admin.set_dsheuristics, dsheuristics)
1348 # Set the "dSHeuristics" to activate the correct "userPassword" behaviour
1349 self.ldb_admin.set_dsheuristics("000000001")
1350 # Get the old "minPwdAge"
1351 minPwdAge = self.ldb_admin.get_minPwdAge()
1352 # Reset the "minPwdAge" as it was before
1353 self.addCleanup(self.ldb_admin.set_minPwdAge, minPwdAge)
1354 # Set it temporarely to "0"
1355 self.ldb_admin.set_minPwdAge("0")
1357 self.user_with_wp = "acl_car_user1"
1358 self.user_with_pc = "acl_car_user2"
1359 self.ldb_admin.newuser(self.user_with_wp, self.user_pass)
1360 self.ldb_admin.newuser(self.user_with_pc, self.user_pass)
1361 self.ldb_user = self.get_ldb_connection(self.user_with_wp, self.user_pass)
1362 self.ldb_user2 = self.get_ldb_connection(self.user_with_pc, self.user_pass)
1365 super(AclCARTests, self).tearDown()
1366 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_wp))
1367 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_pc))
1372 def test_change_password1(self):
1373 """Try a password change operation without any CARs given"""
1374 #users have change password by default - remove for negative testing
1375 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1376 sddl = desc.as_sddl(self.domain_sid)
1377 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)", "")
1378 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)", "")
1379 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1381 self.ldb_user.modify_ldif("""
1382 dn: """ + self.get_user_dn(self.user_with_wp) + """
1385 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')) + """
1387 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
1389 except LdbError as e24:
1391 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1393 # for some reason we get constraint violation instead of insufficient access error
1396 def test_change_password2(self):
1397 """Make sure WP has no influence"""
1398 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1399 sddl = desc.as_sddl(self.domain_sid)
1400 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)", "")
1401 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)", "")
1402 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1403 mod = "(A;;WP;;;PS)"
1404 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1405 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1406 sddl = desc.as_sddl(self.domain_sid)
1408 self.ldb_user.modify_ldif("""
1409 dn: """ + self.get_user_dn(self.user_with_wp) + """
1412 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')) + """
1414 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
1416 except LdbError as e25:
1418 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1420 # for some reason we get constraint violation instead of insufficient access error
1423 def test_change_password3(self):
1424 """Make sure WP has no influence"""
1425 mod = "(D;;WP;;;PS)"
1426 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1427 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1428 sddl = desc.as_sddl(self.domain_sid)
1429 self.ldb_user.modify_ldif("""
1430 dn: """ + self.get_user_dn(self.user_with_wp) + """
1433 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')) + """
1435 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
1438 def test_change_password5(self):
1439 """Make sure rights have no influence on dBCSPwd"""
1440 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1441 sddl = desc.as_sddl(self.domain_sid)
1442 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)", "")
1443 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)", "")
1444 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1445 mod = "(D;;WP;;;PS)"
1446 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1448 self.ldb_user.modify_ldif("""
1449 dn: """ + self.get_user_dn(self.user_with_wp) + """
1452 dBCSPwd: XXXXXXXXXXXXXXXX
1454 dBCSPwd: YYYYYYYYYYYYYYYY
1456 except LdbError as e26:
1458 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1462 def test_change_password6(self):
1463 """Test uneven delete/adds"""
1465 self.ldb_user.modify_ldif("""
1466 dn: """ + self.get_user_dn(self.user_with_wp) + """
1468 delete: userPassword
1469 userPassword: thatsAcomplPASS1
1470 delete: userPassword
1471 userPassword: thatsAcomplPASS1
1473 userPassword: thatsAcomplPASS2
1475 except LdbError as e27:
1477 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1480 mod = "(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1481 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1483 self.ldb_user.modify_ldif("""
1484 dn: """ + self.get_user_dn(self.user_with_wp) + """
1486 delete: userPassword
1487 userPassword: thatsAcomplPASS1
1488 delete: userPassword
1489 userPassword: thatsAcomplPASS1
1491 userPassword: thatsAcomplPASS2
1493 # This fails on Windows 2000 domain level with constraint violation
1494 except LdbError as e28:
1496 self.assertTrue(num == ERR_CONSTRAINT_VIOLATION or
1497 num == ERR_UNWILLING_TO_PERFORM)
1502 def test_change_password7(self):
1503 """Try a password change operation without any CARs given"""
1504 #users have change password by default - remove for negative testing
1505 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1506 sddl = desc.as_sddl(self.domain_sid)
1507 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1508 #first change our own password
1509 self.ldb_user2.modify_ldif("""
1510 dn: """ + self.get_user_dn(self.user_with_pc) + """
1513 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')) + """
1515 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """
1517 #then someone else's
1518 self.ldb_user2.modify_ldif("""
1519 dn: """ + self.get_user_dn(self.user_with_wp) + """
1522 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')) + """
1524 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')) + """
1527 def test_reset_password1(self):
1528 """Try a user password reset operation (unicodePwd) before and after granting CAR"""
1530 self.ldb_user.modify_ldif("""
1531 dn: """ + self.get_user_dn(self.user_with_wp) + """
1534 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """
1536 except LdbError as e29:
1538 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1541 mod = "(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1542 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1543 self.ldb_user.modify_ldif("""
1544 dn: """ + self.get_user_dn(self.user_with_wp) + """
1547 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """
1550 def test_reset_password2(self):
1551 """Try a user password reset operation (userPassword) before and after granting CAR"""
1553 self.ldb_user.modify_ldif("""
1554 dn: """ + self.get_user_dn(self.user_with_wp) + """
1556 replace: userPassword
1557 userPassword: thatsAcomplPASS1
1559 except LdbError as e30:
1561 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1564 mod = "(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1565 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1567 self.ldb_user.modify_ldif("""
1568 dn: """ + self.get_user_dn(self.user_with_wp) + """
1570 replace: userPassword
1571 userPassword: thatsAcomplPASS1
1573 # This fails on Windows 2000 domain level with constraint violation
1574 except LdbError as e31:
1576 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1578 def test_reset_password3(self):
1579 """Grant WP and see what happens (unicodePwd)"""
1580 mod = "(A;;WP;;;PS)"
1581 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1583 self.ldb_user.modify_ldif("""
1584 dn: """ + self.get_user_dn(self.user_with_wp) + """
1587 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """
1589 except LdbError as e32:
1591 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1595 def test_reset_password4(self):
1596 """Grant WP and see what happens (userPassword)"""
1597 mod = "(A;;WP;;;PS)"
1598 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1600 self.ldb_user.modify_ldif("""
1601 dn: """ + self.get_user_dn(self.user_with_wp) + """
1603 replace: userPassword
1604 userPassword: thatsAcomplPASS1
1606 except LdbError as e33:
1608 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1612 def test_reset_password5(self):
1613 """Explicitly deny WP but grant CAR (unicodePwd)"""
1614 mod = "(D;;WP;;;PS)(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1615 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1616 self.ldb_user.modify_ldif("""
1617 dn: """ + self.get_user_dn(self.user_with_wp) + """
1620 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')) + """
1623 def test_reset_password6(self):
1624 """Explicitly deny WP but grant CAR (userPassword)"""
1625 mod = "(D;;WP;;;PS)(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1626 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1628 self.ldb_user.modify_ldif("""
1629 dn: """ + self.get_user_dn(self.user_with_wp) + """
1631 replace: userPassword
1632 userPassword: thatsAcomplPASS1
1634 # This fails on Windows 2000 domain level with constraint violation
1635 except LdbError as e34:
1637 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1639 class AclExtendedTests(AclTests):
1642 super(AclExtendedTests, self).setUp()
1643 #regular user, will be the creator
1649 self.ldb_admin.newuser(self.u1, self.user_pass)
1650 self.ldb_admin.newuser(self.u2, self.user_pass)
1651 self.ldb_admin.newuser(self.u3, self.user_pass)
1652 self.ldb_admin.add_remove_group_members("Domain Admins", [self.u3],
1653 add_members_operation=True)
1654 self.ldb_user1 = self.get_ldb_connection(self.u1, self.user_pass)
1655 self.ldb_user2 = self.get_ldb_connection(self.u2, self.user_pass)
1656 self.ldb_user3 = self.get_ldb_connection(self.u3, self.user_pass)
1657 self.user_sid1 = self.sd_utils.get_object_sid(self.get_user_dn(self.u1))
1658 self.user_sid2 = self.sd_utils.get_object_sid(self.get_user_dn(self.u2))
1661 super(AclExtendedTests, self).tearDown()
1662 delete_force(self.ldb_admin, self.get_user_dn(self.u1))
1663 delete_force(self.ldb_admin, self.get_user_dn(self.u2))
1664 delete_force(self.ldb_admin, self.get_user_dn(self.u3))
1665 delete_force(self.ldb_admin, "CN=ext_group1,OU=ext_ou1," + self.base_dn)
1666 delete_force(self.ldb_admin, "ou=ext_ou1," + self.base_dn)
1672 def test_ntSecurityDescriptor(self):
1674 self.ldb_admin.create_ou("ou=ext_ou1," + self.base_dn)
1675 #give u1 Create children access
1676 mod = "(A;;CC;;;%s)" % str(self.user_sid1)
1677 self.sd_utils.dacl_add_ace("OU=ext_ou1," + self.base_dn, mod)
1678 mod = "(A;;LC;;;%s)" % str(self.user_sid2)
1679 self.sd_utils.dacl_add_ace("OU=ext_ou1," + self.base_dn, mod)
1680 #create a group under that, grant RP to u2
1681 self.ldb_user1.newgroup("ext_group1", groupou="OU=ext_ou1",
1682 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
1683 mod = "(A;;RP;;;%s)" % str(self.user_sid2)
1684 self.sd_utils.dacl_add_ace("CN=ext_group1,OU=ext_ou1," + self.base_dn, mod)
1685 #u2 must not read the descriptor
1686 res = self.ldb_user2.search("CN=ext_group1,OU=ext_ou1," + self.base_dn,
1687 SCOPE_BASE, None, ["nTSecurityDescriptor"])
1688 self.assertNotEqual(len(res), 0)
1689 self.assertFalse("nTSecurityDescriptor" in res[0].keys())
1690 #grant RC to u2 - still no access
1691 mod = "(A;;RC;;;%s)" % str(self.user_sid2)
1692 self.sd_utils.dacl_add_ace("CN=ext_group1,OU=ext_ou1," + self.base_dn, mod)
1693 res = self.ldb_user2.search("CN=ext_group1,OU=ext_ou1," + self.base_dn,
1694 SCOPE_BASE, None, ["nTSecurityDescriptor"])
1695 self.assertNotEqual(len(res), 0)
1696 self.assertFalse("nTSecurityDescriptor" in res[0].keys())
1697 #u3 is member of administrators group, should be able to read sd
1698 res = self.ldb_user3.search("CN=ext_group1,OU=ext_ou1," + self.base_dn,
1699 SCOPE_BASE, None, ["nTSecurityDescriptor"])
1700 self.assertEqual(len(res),1)
1701 self.assertTrue("nTSecurityDescriptor" in res[0].keys())
1703 class AclUndeleteTests(AclTests):
1706 super(AclUndeleteTests, self).setUp()
1707 self.regular_user = "undeleter1"
1708 self.ou1 = "OU=undeleted_ou,"
1709 self.testuser1 = "to_be_undeleted1"
1710 self.testuser2 = "to_be_undeleted2"
1711 self.testuser3 = "to_be_undeleted3"
1712 self.testuser4 = "to_be_undeleted4"
1713 self.testuser5 = "to_be_undeleted5"
1714 self.testuser6 = "to_be_undeleted6"
1716 self.new_dn_ou = "CN="+ self.testuser4 + "," + self.ou1 + self.base_dn
1718 # Create regular user
1719 self.testuser1_dn = self.get_user_dn(self.testuser1)
1720 self.testuser2_dn = self.get_user_dn(self.testuser2)
1721 self.testuser3_dn = self.get_user_dn(self.testuser3)
1722 self.testuser4_dn = self.get_user_dn(self.testuser4)
1723 self.testuser5_dn = self.get_user_dn(self.testuser5)
1724 self.deleted_dn1 = self.create_delete_user(self.testuser1)
1725 self.deleted_dn2 = self.create_delete_user(self.testuser2)
1726 self.deleted_dn3 = self.create_delete_user(self.testuser3)
1727 self.deleted_dn4 = self.create_delete_user(self.testuser4)
1728 self.deleted_dn5 = self.create_delete_user(self.testuser5)
1730 self.ldb_admin.create_ou(self.ou1 + self.base_dn)
1732 self.ldb_admin.newuser(self.regular_user, self.user_pass)
1733 self.ldb_admin.add_remove_group_members("Domain Admins", [self.regular_user],
1734 add_members_operation=True)
1735 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
1736 self.sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1739 super(AclUndeleteTests, self).tearDown()
1740 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
1741 delete_force(self.ldb_admin, self.get_user_dn(self.testuser1))
1742 delete_force(self.ldb_admin, self.get_user_dn(self.testuser2))
1743 delete_force(self.ldb_admin, self.get_user_dn(self.testuser3))
1744 delete_force(self.ldb_admin, self.get_user_dn(self.testuser4))
1745 delete_force(self.ldb_admin, self.get_user_dn(self.testuser5))
1746 delete_force(self.ldb_admin, self.new_dn_ou)
1747 delete_force(self.ldb_admin, self.ou1 + self.base_dn)
1751 def GUID_string(self, guid):
1752 return ldb.schema_format_value("objectGUID", guid)
1754 def create_delete_user(self, new_user):
1755 self.ldb_admin.newuser(new_user, self.user_pass)
1757 res = self.ldb_admin.search(expression="(objectClass=*)",
1758 base=self.get_user_dn(new_user),
1760 controls=["show_deleted:1"])
1761 guid = res[0]["objectGUID"][0]
1762 self.ldb_admin.delete(self.get_user_dn(new_user))
1763 res = self.ldb_admin.search(base="<GUID=%s>" % self.GUID_string(guid),
1764 scope=SCOPE_BASE, controls=["show_deleted:1"])
1765 self.assertEquals(len(res), 1)
1766 return str(res[0].dn)
1768 def undelete_deleted(self, olddn, newdn):
1770 msg.dn = Dn(self.ldb_user, olddn)
1771 msg["isDeleted"] = MessageElement([], FLAG_MOD_DELETE, "isDeleted")
1772 msg["distinguishedName"] = MessageElement([newdn], FLAG_MOD_REPLACE, "distinguishedName")
1773 res = self.ldb_user.modify(msg, ["show_recycled:1"])
1775 def undelete_deleted_with_mod(self, olddn, newdn):
1777 msg.dn = Dn(ldb, olddn)
1778 msg["isDeleted"] = MessageElement([], FLAG_MOD_DELETE, "isDeleted")
1779 msg["distinguishedName"] = MessageElement([newdn], FLAG_MOD_REPLACE, "distinguishedName")
1780 msg["url"] = MessageElement(["www.samba.org"], FLAG_MOD_REPLACE, "url")
1781 res = self.ldb_user.modify(msg, ["show_deleted:1"])
1783 def test_undelete(self):
1784 # it appears the user has to have LC on the old parent to be able to move the object
1785 # otherwise we get no such object. Since only System can modify the SD on deleted object
1786 # we cannot grant this permission via LDAP, and this leaves us with "negative" tests at the moment
1788 # deny write property on rdn, should fail
1789 mod = "(OD;;WP;bf967a0e-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
1790 self.sd_utils.dacl_add_ace(self.deleted_dn1, mod)
1792 self.undelete_deleted(self.deleted_dn1, self.testuser1_dn)
1794 except LdbError as e35:
1796 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1798 # seems that permissions on isDeleted and distinguishedName are irrelevant
1799 mod = "(OD;;WP;bf96798f-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
1800 self.sd_utils.dacl_add_ace(self.deleted_dn2, mod)
1801 mod = "(OD;;WP;bf9679e4-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
1802 self.sd_utils.dacl_add_ace(self.deleted_dn2, mod)
1803 self.undelete_deleted(self.deleted_dn2, self.testuser2_dn)
1805 # attempt undelete with simultanious addition of url, WP to which is denied
1806 mod = "(OD;;WP;9a9a0221-4a5b-11d1-a9c3-0000f80367c1;;%s)" % str(self.sid)
1807 self.sd_utils.dacl_add_ace(self.deleted_dn3, mod)
1809 self.undelete_deleted_with_mod(self.deleted_dn3, self.testuser3_dn)
1811 except LdbError as e36:
1813 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1815 # undelete in an ou, in which we have no right to create children
1816 mod = "(D;;CC;;;%s)" % str(self.sid)
1817 self.sd_utils.dacl_add_ace(self.ou1 + self.base_dn, mod)
1819 self.undelete_deleted(self.deleted_dn4, self.new_dn_ou)
1821 except LdbError as e37:
1823 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1825 # delete is not required
1826 mod = "(D;;SD;;;%s)" % str(self.sid)
1827 self.sd_utils.dacl_add_ace(self.deleted_dn5, mod)
1828 self.undelete_deleted(self.deleted_dn5, self.testuser5_dn)
1830 # deny Reanimate-Tombstone, should fail
1831 mod = "(OD;;CR;45ec5156-db7e-47bb-b53f-dbeb2d03c40f;;%s)" % str(self.sid)
1832 self.sd_utils.dacl_add_ace(self.base_dn, mod)
1834 self.undelete_deleted(self.deleted_dn4, self.testuser4_dn)
1836 except LdbError as e38:
1838 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1840 class AclSPNTests(AclTests):
1843 super(AclSPNTests, self).setUp()
1844 self.dcname = "TESTSRV8"
1845 self.rodcname = "TESTRODC8"
1846 self.computername = "testcomp8"
1847 self.test_user = "spn_test_user8"
1848 self.computerdn = "CN=%s,CN=computers,%s" % (self.computername, self.base_dn)
1849 self.dc_dn = "CN=%s,OU=Domain Controllers,%s" % (self.dcname, self.base_dn)
1850 self.site = "Default-First-Site-Name"
1851 self.rodcctx = dc_join(server=host, creds=creds, lp=lp,
1852 site=self.site, netbios_name=self.rodcname, targetdir=None,
1854 self.dcctx = dc_join(server=host, creds=creds, lp=lp, site=self.site,
1855 netbios_name=self.dcname, targetdir=None, domain=None)
1856 self.ldb_admin.newuser(self.test_user, self.user_pass)
1857 self.ldb_user1 = self.get_ldb_connection(self.test_user, self.user_pass)
1858 self.user_sid1 = self.sd_utils.get_object_sid(self.get_user_dn(self.test_user))
1859 self.create_computer(self.computername, self.dcctx.dnsdomain)
1860 self.create_rodc(self.rodcctx)
1861 self.create_dc(self.dcctx)
1864 super(AclSPNTests, self).tearDown()
1865 self.rodcctx.cleanup_old_join()
1866 self.dcctx.cleanup_old_join()
1867 delete_force(self.ldb_admin, "cn=%s,cn=computers,%s" % (self.computername, self.base_dn))
1868 delete_force(self.ldb_admin, self.get_user_dn(self.test_user))
1872 def replace_spn(self, _ldb, dn, spn):
1873 print "Setting spn %s on %s" % (spn, dn)
1874 res = self.ldb_admin.search(dn, expression="(objectClass=*)",
1875 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1876 if "servicePrincipalName" in res[0].keys():
1877 flag = FLAG_MOD_REPLACE
1882 msg.dn = Dn(self.ldb_admin, dn)
1883 msg["servicePrincipalName"] = MessageElement(spn, flag,
1884 "servicePrincipalName")
1887 def create_computer(self, computername, domainname):
1888 dn = "CN=%s,CN=computers,%s" % (computername, self.base_dn)
1889 samaccountname = computername + "$"
1890 dnshostname = "%s.%s" % (computername, domainname)
1891 self.ldb_admin.add({
1893 "objectclass": "computer",
1894 "sAMAccountName": samaccountname,
1895 "userAccountControl": str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT),
1896 "dNSHostName": dnshostname})
1898 # same as for join_RODC, but do not set any SPNs
1899 def create_rodc(self, ctx):
1900 ctx.nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1901 ctx.full_nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1902 ctx.krbtgt_dn = "CN=krbtgt_%s,CN=Users,%s" % (ctx.myname, ctx.base_dn)
1904 ctx.never_reveal_sid = [ "<SID=%s-%s>" % (ctx.domsid, security.DOMAIN_RID_RODC_DENY),
1905 "<SID=%s>" % security.SID_BUILTIN_ADMINISTRATORS,
1906 "<SID=%s>" % security.SID_BUILTIN_SERVER_OPERATORS,
1907 "<SID=%s>" % security.SID_BUILTIN_BACKUP_OPERATORS,
1908 "<SID=%s>" % security.SID_BUILTIN_ACCOUNT_OPERATORS ]
1909 ctx.reveal_sid = "<SID=%s-%s>" % (ctx.domsid, security.DOMAIN_RID_RODC_ALLOW)
1911 mysid = ctx.get_mysid()
1912 admin_dn = "<SID=%s>" % mysid
1913 ctx.managedby = admin_dn
1915 ctx.userAccountControl = (samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT |
1916 samba.dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION |
1917 samba.dsdb.UF_PARTIAL_SECRETS_ACCOUNT)
1919 ctx.connection_dn = "CN=RODC Connection (FRS),%s" % ctx.ntds_dn
1920 ctx.secure_channel_type = misc.SEC_CHAN_RODC
1922 ctx.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC |
1923 drsuapi.DRSUAPI_DRS_PER_SYNC |
1924 drsuapi.DRSUAPI_DRS_GET_ANC |
1925 drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
1926 drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
1928 ctx.join_add_objects()
1930 def create_dc(self, ctx):
1931 ctx.nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1932 ctx.full_nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1933 ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
1934 ctx.secure_channel_type = misc.SEC_CHAN_BDC
1935 ctx.replica_flags = (drsuapi.DRSUAPI_DRS_WRIT_REP |
1936 drsuapi.DRSUAPI_DRS_INIT_SYNC |
1937 drsuapi.DRSUAPI_DRS_PER_SYNC |
1938 drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS |
1939 drsuapi.DRSUAPI_DRS_NEVER_SYNCED)
1941 ctx.join_add_objects()
1943 def dc_spn_test(self, ctx):
1944 netbiosdomain = self.dcctx.get_domain_name()
1946 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s/%s" % (ctx.myname, netbiosdomain))
1947 except LdbError as e39:
1949 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1951 mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1)
1952 self.sd_utils.dacl_add_ace(ctx.acct_dn, mod)
1953 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s/%s" % (ctx.myname, netbiosdomain))
1954 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s" % (ctx.myname))
1955 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s.%s/%s" %
1956 (ctx.myname, ctx.dnsdomain, netbiosdomain))
1957 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s/%s" % (ctx.myname, ctx.dnsdomain))
1958 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s.%s/%s" %
1959 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
1960 self.replace_spn(self.ldb_user1, ctx.acct_dn, "GC/%s.%s/%s" %
1961 (ctx.myname, ctx.dnsdomain, ctx.dnsforest))
1962 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s/%s" % (ctx.myname, netbiosdomain))
1963 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/%s" %
1964 (ctx.myname, ctx.dnsdomain, netbiosdomain))
1965 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s" % (ctx.myname))
1966 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s/%s" % (ctx.myname, ctx.dnsdomain))
1967 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/%s" %
1968 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
1969 self.replace_spn(self.ldb_user1, ctx.acct_dn, "DNS/%s/%s" % (ctx.myname, ctx.dnsdomain))
1970 self.replace_spn(self.ldb_user1, ctx.acct_dn, "RestrictedKrbHost/%s/%s" %
1971 (ctx.myname, ctx.dnsdomain))
1972 self.replace_spn(self.ldb_user1, ctx.acct_dn, "RestrictedKrbHost/%s" %
1974 self.replace_spn(self.ldb_user1, ctx.acct_dn, "Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/%s/%s" %
1975 (ctx.myname, ctx.dnsdomain))
1976 self.replace_spn(self.ldb_user1, ctx.acct_dn, "NtFrs-88f5d2bd-b646-11d2-a6d3-00c04fc9b232/%s/%s" %
1977 (ctx.myname, ctx.dnsdomain))
1978 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s._msdcs.%s" %
1979 (ctx.ntds_guid, ctx.dnsdomain))
1981 #the following spns do not match the restrictions and should fail
1983 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/ForestDnsZones.%s" %
1984 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
1985 except LdbError as e40:
1987 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1989 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/DomainDnsZones.%s" %
1990 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
1991 except LdbError as e41:
1993 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1995 self.replace_spn(self.ldb_user1, ctx.acct_dn, "nosuchservice/%s/%s" % ("abcd", "abcd"))
1996 except LdbError as e42:
1998 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2000 self.replace_spn(self.ldb_user1, ctx.acct_dn, "GC/%s.%s/%s" %
2001 (ctx.myname, ctx.dnsdomain, netbiosdomain))
2002 except LdbError as e43:
2004 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2006 self.replace_spn(self.ldb_user1, ctx.acct_dn, "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s" %
2007 (ctx.ntds_guid, ctx.dnsdomain))
2008 except LdbError as e44:
2010 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2012 def test_computer_spn(self):
2013 # with WP, any value can be set
2014 netbiosdomain = self.dcctx.get_domain_name()
2015 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s/%s" %
2016 (self.computername, netbiosdomain))
2017 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s" % (self.computername))
2018 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s.%s/%s" %
2019 (self.computername, self.dcctx.dnsdomain, netbiosdomain))
2020 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s/%s" %
2021 (self.computername, self.dcctx.dnsdomain))
2022 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s.%s/%s" %
2023 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2024 self.replace_spn(self.ldb_admin, self.computerdn, "GC/%s.%s/%s" %
2025 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsforest))
2026 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s/%s" % (self.computername, netbiosdomain))
2027 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/ForestDnsZones.%s" %
2028 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2029 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/DomainDnsZones.%s" %
2030 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2031 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/%s" %
2032 (self.computername, self.dcctx.dnsdomain, netbiosdomain))
2033 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s" % (self.computername))
2034 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s/%s" %
2035 (self.computername, self.dcctx.dnsdomain))
2036 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/%s" %
2037 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2038 self.replace_spn(self.ldb_admin, self.computerdn, "DNS/%s/%s" %
2039 (self.computername, self.dcctx.dnsdomain))
2040 self.replace_spn(self.ldb_admin, self.computerdn, "RestrictedKrbHost/%s/%s" %
2041 (self.computername, self.dcctx.dnsdomain))
2042 self.replace_spn(self.ldb_admin, self.computerdn, "RestrictedKrbHost/%s" %
2043 (self.computername))
2044 self.replace_spn(self.ldb_admin, self.computerdn, "Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/%s/%s" %
2045 (self.computername, self.dcctx.dnsdomain))
2046 self.replace_spn(self.ldb_admin, self.computerdn, "NtFrs-88f5d2bd-b646-11d2-a6d3-00c04fc9b232/%s/%s" %
2047 (self.computername, self.dcctx.dnsdomain))
2048 self.replace_spn(self.ldb_admin, self.computerdn, "nosuchservice/%s/%s" % ("abcd", "abcd"))
2050 #user has neither WP nor Validated-SPN, access denied expected
2052 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, netbiosdomain))
2053 except LdbError as e45:
2055 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2057 mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1)
2058 self.sd_utils.dacl_add_ace(self.computerdn, mod)
2059 #grant Validated-SPN and check which values are accepted
2060 #see 3.1.1.5.3.1.1.4 servicePrincipalName for reference
2062 # for regular computer objects we shouldalways get constraint violation
2064 # This does not pass against Windows, although it should according to docs
2065 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s" % (self.computername))
2066 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s" %
2067 (self.computername, self.dcctx.dnsdomain))
2070 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, netbiosdomain))
2071 except LdbError as e46:
2073 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2075 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" %
2076 (self.computername, self.dcctx.dnsdomain, netbiosdomain))
2077 except LdbError as e47:
2079 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2081 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" %
2082 (self.computername, self.dcctx.dnsdomain))
2083 except LdbError as e48:
2085 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2087 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" %
2088 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2089 except LdbError as e49:
2091 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2093 self.replace_spn(self.ldb_user1, self.computerdn, "GC/%s.%s/%s" %
2094 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsforest))
2095 except LdbError as e50:
2097 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2099 self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s/%s" % (self.computername, netbiosdomain))
2100 except LdbError as e51:
2102 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2104 self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s.%s/ForestDnsZones.%s" %
2105 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2106 except LdbError as e52:
2108 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2110 def test_spn_rwdc(self):
2111 self.dc_spn_test(self.dcctx)
2113 def test_spn_rodc(self):
2114 self.dc_spn_test(self.rodcctx)
2117 # Important unit running information
2119 ldb = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp)
2121 TestProgram(module=__name__, opts=subunitopts)