2 # -*- coding: utf-8 -*-
3 # This is unit with tests for LDAP access checks
5 from __future__ import print_function
10 sys.path.insert(0, "bin/python")
13 from samba.tests.subunitrun import SubunitOptions, TestProgram
15 import samba.getopt as options
16 from samba.join import DCJoinContext
19 SCOPE_BASE, SCOPE_SUBTREE, LdbError, ERR_NO_SUCH_OBJECT,
20 ERR_UNWILLING_TO_PERFORM, ERR_INSUFFICIENT_ACCESS_RIGHTS)
21 from ldb import ERR_CONSTRAINT_VIOLATION
22 from ldb import ERR_OPERATIONS_ERROR
23 from ldb import Message, MessageElement, Dn
24 from ldb import FLAG_MOD_REPLACE, FLAG_MOD_ADD, FLAG_MOD_DELETE
25 from samba.dcerpc import security, drsuapi, misc
27 from samba.auth import system_session
28 from samba import gensec, sd_utils
29 from samba.samdb import SamDB
30 from samba.credentials import Credentials, DONT_USE_KERBEROS
32 from samba.tests import delete_force
34 from samba.tests.password_test import PasswordCommon
36 parser = optparse.OptionParser("acl.py [options] <host>")
37 sambaopts = options.SambaOptions(parser)
38 parser.add_option_group(sambaopts)
39 parser.add_option_group(options.VersionOptions(parser))
41 # use command line creds if available
42 credopts = options.CredentialsOptions(parser)
43 parser.add_option_group(credopts)
44 subunitopts = SubunitOptions(parser)
45 parser.add_option_group(subunitopts)
47 opts, args = parser.parse_args()
55 ldaphost = "ldap://%s" % host
58 start = host.rindex("://")
59 host = host.lstrip(start+3)
61 lp = sambaopts.get_loadparm()
62 creds = credopts.get_credentials(lp)
63 creds.set_gensec_features(creds.get_gensec_features() | gensec.FEATURE_SEAL)
69 class AclTests(samba.tests.TestCase):
72 super(AclTests, self).setUp()
73 self.ldb_admin = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp)
74 self.base_dn = self.ldb_admin.domain_dn()
75 self.domain_sid = security.dom_sid(self.ldb_admin.get_domain_sid())
76 self.user_pass = "samba123@"
77 self.configuration_dn = self.ldb_admin.get_config_basedn().get_linearized()
78 self.sd_utils = sd_utils.SDUtils(self.ldb_admin)
79 self.addCleanup(self.delete_admin_connection)
80 #used for anonymous login
81 self.creds_tmp = Credentials()
82 self.creds_tmp.set_username("")
83 self.creds_tmp.set_password("")
84 self.creds_tmp.set_domain(creds.get_domain())
85 self.creds_tmp.set_realm(creds.get_realm())
86 self.creds_tmp.set_workstation(creds.get_workstation())
87 print("baseDN: %s" % self.base_dn)
89 def get_user_dn(self, name):
90 return "CN=%s,CN=Users,%s" % (name, self.base_dn)
92 def get_ldb_connection(self, target_username, target_password):
93 creds_tmp = Credentials()
94 creds_tmp.set_username(target_username)
95 creds_tmp.set_password(target_password)
96 creds_tmp.set_domain(creds.get_domain())
97 creds_tmp.set_realm(creds.get_realm())
98 creds_tmp.set_workstation(creds.get_workstation())
99 creds_tmp.set_gensec_features(creds_tmp.get_gensec_features()
100 | gensec.FEATURE_SEAL)
101 creds_tmp.set_kerberos_state(DONT_USE_KERBEROS) # kinit is too expensive to use in a tight loop
102 ldb_target = SamDB(url=ldaphost, credentials=creds_tmp, lp=lp)
105 # Test if we have any additional groups for users than default ones
106 def assert_user_no_group_member(self, username):
107 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % self.get_user_dn(username))
109 self.assertEqual(res[0]["memberOf"][0], "")
115 def delete_admin_connection(self):
119 #tests on ldap add operations
120 class AclAddTests(AclTests):
123 super(AclAddTests, self).setUp()
124 # Domain admin that will be creator of OU parent-child structure
125 self.usr_admin_owner = "acl_add_user1"
126 # Second domain admin that will not be creator of OU parent-child structure
127 self.usr_admin_not_owner = "acl_add_user2"
129 self.regular_user = "acl_add_user3"
130 self.test_user1 = "test_add_user1"
131 self.test_group1 = "test_add_group1"
132 self.ou1 = "OU=test_add_ou1"
133 self.ou2 = "OU=test_add_ou2,%s" % self.ou1
134 self.ldb_admin.newuser(self.usr_admin_owner, self.user_pass)
135 self.ldb_admin.newuser(self.usr_admin_not_owner, self.user_pass)
136 self.ldb_admin.newuser(self.regular_user, self.user_pass)
138 # add admins to the Domain Admins group
139 self.ldb_admin.add_remove_group_members("Domain Admins", [self.usr_admin_owner],
140 add_members_operation=True)
141 self.ldb_admin.add_remove_group_members("Domain Admins", [self.usr_admin_not_owner],
142 add_members_operation=True)
144 self.ldb_owner = self.get_ldb_connection(self.usr_admin_owner, self.user_pass)
145 self.ldb_notowner = self.get_ldb_connection(self.usr_admin_not_owner, self.user_pass)
146 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
149 super(AclAddTests, self).tearDown()
150 delete_force(self.ldb_admin, "CN=%s,%s,%s" %
151 (self.test_user1, self.ou2, self.base_dn))
152 delete_force(self.ldb_admin, "CN=%s,%s,%s" %
153 (self.test_group1, self.ou2, self.base_dn))
154 delete_force(self.ldb_admin, "%s,%s" % (self.ou2, self.base_dn))
155 delete_force(self.ldb_admin, "%s,%s" % (self.ou1, self.base_dn))
156 delete_force(self.ldb_admin, self.get_user_dn(self.usr_admin_owner))
157 delete_force(self.ldb_admin, self.get_user_dn(self.usr_admin_not_owner))
158 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
159 delete_force(self.ldb_admin, self.get_user_dn("test_add_anonymous"))
161 del self.ldb_notowner
165 # Make sure top OU is deleted (and so everything under it)
166 def assert_top_ou_deleted(self):
167 res = self.ldb_admin.search(self.base_dn,
168 expression="(distinguishedName=%s,%s)" % (
169 "OU=test_add_ou1", self.base_dn))
170 self.assertEqual(len(res), 0)
172 def test_add_u1(self):
173 """Testing OU with the rights of Doman Admin not creator of the OU """
174 self.assert_top_ou_deleted()
175 # Change descriptor for top level OU
176 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
177 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
178 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.usr_admin_not_owner))
179 mod = "(D;CI;WPCC;;;%s)" % str(user_sid)
180 self.sd_utils.dacl_add_ace("OU=test_add_ou1," + self.base_dn, mod)
181 # Test user and group creation with another domain admin's credentials
182 self.ldb_notowner.newuser(self.test_user1, self.user_pass, userou=self.ou2)
183 self.ldb_notowner.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
184 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
185 # Make sure we HAVE created the two objects -- user and group
186 # !!! We should not be able to do that, but however beacuse of ACE ordering our inherited Deny ACE
187 # !!! comes after explicit (A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA) that comes from somewhere
188 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))
189 self.assertTrue(len(res) > 0)
190 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))
191 self.assertTrue(len(res) > 0)
193 def test_add_u2(self):
194 """Testing OU with the regular user that has no rights granted over the OU """
195 self.assert_top_ou_deleted()
196 # Create a parent-child OU structure with domain admin credentials
197 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
198 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
199 # Test user and group creation with regular user credentials
201 self.ldb_user.newuser(self.test_user1, self.user_pass, userou=self.ou2)
202 self.ldb_user.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
203 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
204 except LdbError as e:
206 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
209 # Make sure we HAVEN'T created any of two objects -- user or group
210 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))
211 self.assertEqual(len(res), 0)
212 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))
213 self.assertEqual(len(res), 0)
215 def test_add_u3(self):
216 """Testing OU with the rights of regular user granted the right 'Create User child objects' """
217 self.assert_top_ou_deleted()
218 # Change descriptor for top level OU
219 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
220 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
221 mod = "(OA;CI;CC;bf967aba-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid)
222 self.sd_utils.dacl_add_ace("OU=test_add_ou1," + self.base_dn, mod)
223 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
224 # Test user and group creation with granted user only to one of the objects
225 self.ldb_user.newuser(self.test_user1, self.user_pass, userou=self.ou2, setpassword=False)
227 self.ldb_user.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
228 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
229 except LdbError as e1:
231 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
234 # Make sure we HAVE created the one of two objects -- user
235 res = self.ldb_admin.search(self.base_dn,
236 expression="(distinguishedName=%s,%s)" %
237 ("CN=test_add_user1,OU=test_add_ou2,OU=test_add_ou1",
239 self.assertNotEqual(len(res), 0)
240 res = self.ldb_admin.search(self.base_dn,
241 expression="(distinguishedName=%s,%s)" %
242 ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1",
244 self.assertEqual(len(res), 0)
246 def test_add_u4(self):
247 """ 4 Testing OU with the rights of Doman Admin creator of the OU"""
248 self.assert_top_ou_deleted()
249 self.ldb_owner.create_ou("OU=test_add_ou1," + self.base_dn)
250 self.ldb_owner.create_ou("OU=test_add_ou2,OU=test_add_ou1," + self.base_dn)
251 self.ldb_owner.newuser(self.test_user1, self.user_pass, userou=self.ou2)
252 self.ldb_owner.newgroup("test_add_group1", groupou="OU=test_add_ou2,OU=test_add_ou1",
253 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
254 # Make sure we have successfully created the two objects -- user and group
255 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))
256 self.assertTrue(len(res) > 0)
257 res = self.ldb_admin.search(self.base_dn,
258 expression="(distinguishedName=%s,%s)" % ("CN=test_add_group1,OU=test_add_ou2,OU=test_add_ou1", self.base_dn))
259 self.assertTrue(len(res) > 0)
261 def test_add_anonymous(self):
262 """Test add operation with anonymous user"""
263 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
265 anonymous.newuser("test_add_anonymous", self.user_pass)
266 except LdbError as e2:
268 self.assertEquals(num, ERR_OPERATIONS_ERROR)
272 #tests on ldap modify operations
273 class AclModifyTests(AclTests):
276 super(AclModifyTests, self).setUp()
277 self.user_with_wp = "acl_mod_user1"
278 self.user_with_sm = "acl_mod_user2"
279 self.user_with_group_sm = "acl_mod_user3"
280 self.ldb_admin.newuser(self.user_with_wp, self.user_pass)
281 self.ldb_admin.newuser(self.user_with_sm, self.user_pass)
282 self.ldb_admin.newuser(self.user_with_group_sm, self.user_pass)
283 self.ldb_user = self.get_ldb_connection(self.user_with_wp, self.user_pass)
284 self.ldb_user2 = self.get_ldb_connection(self.user_with_sm, self.user_pass)
285 self.ldb_user3 = self.get_ldb_connection(self.user_with_group_sm, self.user_pass)
286 self.user_sid = self.sd_utils.get_object_sid( self.get_user_dn(self.user_with_wp))
287 self.ldb_admin.newgroup("test_modify_group2", grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
288 self.ldb_admin.newgroup("test_modify_group3", grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
289 self.ldb_admin.newuser("test_modify_user2", self.user_pass)
292 super(AclModifyTests, self).tearDown()
293 delete_force(self.ldb_admin, self.get_user_dn("test_modify_user1"))
294 delete_force(self.ldb_admin, "CN=test_modify_group1,CN=Users," + self.base_dn)
295 delete_force(self.ldb_admin, "CN=test_modify_group2,CN=Users," + self.base_dn)
296 delete_force(self.ldb_admin, "CN=test_modify_group3,CN=Users," + self.base_dn)
297 delete_force(self.ldb_admin, "OU=test_modify_ou1," + self.base_dn)
298 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_wp))
299 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_sm))
300 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_group_sm))
301 delete_force(self.ldb_admin, self.get_user_dn("test_modify_user2"))
302 delete_force(self.ldb_admin, self.get_user_dn("test_anonymous"))
308 def test_modify_u1(self):
309 """5 Modify one attribute if you have DS_WRITE_PROPERTY for it"""
310 mod = "(OA;;WP;bf967953-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.user_sid)
311 # First test object -- User
312 print("Testing modify on User object")
313 self.ldb_admin.newuser("test_modify_user1", self.user_pass)
314 self.sd_utils.dacl_add_ace(self.get_user_dn("test_modify_user1"), mod)
316 dn: """ + self.get_user_dn("test_modify_user1") + """
319 displayName: test_changed"""
320 self.ldb_user.modify_ldif(ldif)
321 res = self.ldb_admin.search(self.base_dn,
322 expression="(distinguishedName=%s)" % self.get_user_dn("test_modify_user1"))
323 self.assertEqual(res[0]["displayName"][0], "test_changed")
324 # Second test object -- Group
325 print("Testing modify on Group object")
326 self.ldb_admin.newgroup("test_modify_group1",
327 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
328 self.sd_utils.dacl_add_ace("CN=test_modify_group1,CN=Users," + self.base_dn, mod)
330 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
333 displayName: test_changed"""
334 self.ldb_user.modify_ldif(ldif)
335 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % str("CN=test_modify_group1,CN=Users," + self.base_dn))
336 self.assertEqual(res[0]["displayName"][0], "test_changed")
337 # Third test object -- Organizational Unit
338 print("Testing modify on OU object")
339 #delete_force(self.ldb_admin, "OU=test_modify_ou1," + self.base_dn)
340 self.ldb_admin.create_ou("OU=test_modify_ou1," + self.base_dn)
341 self.sd_utils.dacl_add_ace("OU=test_modify_ou1," + self.base_dn, mod)
343 dn: OU=test_modify_ou1,""" + self.base_dn + """
346 displayName: test_changed"""
347 self.ldb_user.modify_ldif(ldif)
348 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % str("OU=test_modify_ou1," + self.base_dn))
349 self.assertEqual(res[0]["displayName"][0], "test_changed")
351 def test_modify_u2(self):
352 """6 Modify two attributes as you have DS_WRITE_PROPERTY granted only for one of them"""
353 mod = "(OA;;WP;bf967953-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.user_sid)
354 # First test object -- User
355 print("Testing modify on User object")
356 #delete_force(self.ldb_admin, self.get_user_dn("test_modify_user1"))
357 self.ldb_admin.newuser("test_modify_user1", self.user_pass)
358 self.sd_utils.dacl_add_ace(self.get_user_dn("test_modify_user1"), mod)
359 # Modify on attribute you have rights for
361 dn: """ + self.get_user_dn("test_modify_user1") + """
364 displayName: test_changed"""
365 self.ldb_user.modify_ldif(ldif)
366 res = self.ldb_admin.search(self.base_dn,
367 expression="(distinguishedName=%s)" %
368 self.get_user_dn("test_modify_user1"))
369 self.assertEqual(res[0]["displayName"][0], "test_changed")
370 # Modify on attribute you do not have rights for granted
372 dn: """ + self.get_user_dn("test_modify_user1") + """
375 url: www.samba.org"""
377 self.ldb_user.modify_ldif(ldif)
378 except LdbError as e3:
380 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
382 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
384 # Second test object -- Group
385 print("Testing modify on Group object")
386 self.ldb_admin.newgroup("test_modify_group1",
387 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
388 self.sd_utils.dacl_add_ace("CN=test_modify_group1,CN=Users," + self.base_dn, mod)
390 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
393 displayName: test_changed"""
394 self.ldb_user.modify_ldif(ldif)
395 res = self.ldb_admin.search(self.base_dn,
396 expression="(distinguishedName=%s)" %
397 str("CN=test_modify_group1,CN=Users," + self.base_dn))
398 self.assertEqual(res[0]["displayName"][0], "test_changed")
399 # Modify on attribute you do not have rights for granted
401 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
404 url: www.samba.org"""
406 self.ldb_user.modify_ldif(ldif)
407 except LdbError as e4:
409 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
411 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
413 # Modify on attribute you do not have rights for granted while also modifying something you do have rights for
415 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
420 displayName: test_changed"""
422 self.ldb_user.modify_ldif(ldif)
423 except LdbError as e5:
425 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
427 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
429 # Second test object -- Organizational Unit
430 print("Testing modify on OU object")
431 self.ldb_admin.create_ou("OU=test_modify_ou1," + self.base_dn)
432 self.sd_utils.dacl_add_ace("OU=test_modify_ou1," + self.base_dn, mod)
434 dn: OU=test_modify_ou1,""" + self.base_dn + """
437 displayName: test_changed"""
438 self.ldb_user.modify_ldif(ldif)
439 res = self.ldb_admin.search(self.base_dn,
440 expression="(distinguishedName=%s)" % str("OU=test_modify_ou1,"
442 self.assertEqual(res[0]["displayName"][0], "test_changed")
443 # Modify on attribute you do not have rights for granted
445 dn: OU=test_modify_ou1,""" + self.base_dn + """
448 url: www.samba.org"""
450 self.ldb_user.modify_ldif(ldif)
451 except LdbError as e6:
453 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
455 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
458 def test_modify_u3(self):
459 """7 Modify one attribute as you have no what so ever rights granted"""
460 # First test object -- User
461 print("Testing modify on User object")
462 self.ldb_admin.newuser("test_modify_user1", self.user_pass)
463 # Modify on attribute you do not have rights for granted
465 dn: """ + self.get_user_dn("test_modify_user1") + """
468 url: www.samba.org"""
470 self.ldb_user.modify_ldif(ldif)
471 except LdbError as e7:
473 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
475 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
478 # Second test object -- Group
479 print("Testing modify on Group object")
480 self.ldb_admin.newgroup("test_modify_group1",
481 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
482 # Modify on attribute you do not have rights for granted
484 dn: CN=test_modify_group1,CN=Users,""" + self.base_dn + """
487 url: www.samba.org"""
489 self.ldb_user.modify_ldif(ldif)
490 except LdbError as e8:
492 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
494 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
497 # Second test object -- Organizational Unit
498 print("Testing modify on OU object")
499 #delete_force(self.ldb_admin, "OU=test_modify_ou1," + self.base_dn)
500 self.ldb_admin.create_ou("OU=test_modify_ou1," + self.base_dn)
501 # Modify on attribute you do not have rights for granted
503 dn: OU=test_modify_ou1,""" + self.base_dn + """
506 url: www.samba.org"""
508 self.ldb_user.modify_ldif(ldif)
509 except LdbError as e9:
511 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
513 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
517 def test_modify_u4(self):
518 """11 Grant WP to PRINCIPAL_SELF and test modify"""
520 dn: """ + self.get_user_dn(self.user_with_wp) + """
522 add: adminDescription
523 adminDescription: blah blah blah"""
525 self.ldb_user.modify_ldif(ldif)
526 except LdbError as e10:
528 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
530 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
533 mod = "(OA;;WP;bf967919-0de6-11d0-a285-00aa003049e2;;PS)"
534 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
535 # Modify on attribute you have rights for
536 self.ldb_user.modify_ldif(ldif)
537 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" \
538 % self.get_user_dn(self.user_with_wp), attrs=["adminDescription"] )
539 self.assertEqual(res[0]["adminDescription"][0], "blah blah blah")
541 def test_modify_u5(self):
542 """12 test self membership"""
544 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
547 Member: """ + self.get_user_dn(self.user_with_sm)
548 #the user has no rights granted, this should fail
550 self.ldb_user2.modify_ldif(ldif)
551 except LdbError as e11:
553 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
555 # This 'modify' operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
558 #grant self-membership, should be able to add himself
559 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.user_with_sm))
560 mod = "(OA;;SW;bf9679c0-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid)
561 self.sd_utils.dacl_add_ace("CN=test_modify_group2,CN=Users," + self.base_dn, mod)
562 self.ldb_user2.modify_ldif(ldif)
563 res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
564 % ("CN=test_modify_group2,CN=Users," + self.base_dn), attrs=["Member"])
565 self.assertEqual(res[0]["Member"][0], self.get_user_dn(self.user_with_sm))
568 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
571 Member: CN=test_modify_user2,CN=Users,""" + self.base_dn
573 self.ldb_user2.modify_ldif(ldif)
574 except LdbError as e12:
576 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
580 def test_modify_u6(self):
581 """13 test self membership"""
583 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
586 Member: """ + self.get_user_dn(self.user_with_sm) + """
587 Member: CN=test_modify_user2,CN=Users,""" + self.base_dn
589 #grant self-membership, should be able to add himself but not others at the same time
590 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.user_with_sm))
591 mod = "(OA;;SW;bf9679c0-0de6-11d0-a285-00aa003049e2;;%s)" % str(user_sid)
592 self.sd_utils.dacl_add_ace("CN=test_modify_group2,CN=Users," + self.base_dn, mod)
594 self.ldb_user2.modify_ldif(ldif)
595 except LdbError as e13:
597 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
601 def test_modify_u7(self):
602 """13 User with WP modifying Member"""
603 #a second user is given write property permission
604 user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.user_with_wp))
605 mod = "(A;;WP;;;%s)" % str(user_sid)
606 self.sd_utils.dacl_add_ace("CN=test_modify_group2,CN=Users," + self.base_dn, mod)
608 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
611 Member: """ + self.get_user_dn(self.user_with_wp)
612 self.ldb_user.modify_ldif(ldif)
613 res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
614 % ("CN=test_modify_group2,CN=Users," + self.base_dn), attrs=["Member"])
615 self.assertEqual(res[0]["Member"][0], self.get_user_dn(self.user_with_wp))
617 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
620 self.ldb_user.modify_ldif(ldif)
622 dn: CN=test_modify_group2,CN=Users,""" + self.base_dn + """
625 Member: CN=test_modify_user2,CN=Users,""" + self.base_dn
626 self.ldb_user.modify_ldif(ldif)
627 res = self.ldb_admin.search( self.base_dn, expression="(distinguishedName=%s)" \
628 % ("CN=test_modify_group2,CN=Users," + self.base_dn), attrs=["Member"])
629 self.assertEqual(res[0]["Member"][0], "CN=test_modify_user2,CN=Users," + self.base_dn)
631 def test_modify_anonymous(self):
632 """Test add operation with anonymous user"""
633 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
634 self.ldb_admin.newuser("test_anonymous", "samba123@")
636 m.dn = Dn(anonymous, self.get_user_dn("test_anonymous"))
638 m["description"] = MessageElement("sambauser2",
643 except LdbError as e14:
645 self.assertEquals(num, ERR_OPERATIONS_ERROR)
649 #enable these when we have search implemented
650 class AclSearchTests(AclTests):
653 super(AclSearchTests, self).setUp()
655 # permit password changes during this test
656 PasswordCommon.allow_password_changes(self, self.ldb_admin)
658 self.u1 = "search_u1"
659 self.u2 = "search_u2"
660 self.u3 = "search_u3"
661 self.group1 = "group1"
662 self.ldb_admin.newuser(self.u1, self.user_pass)
663 self.ldb_admin.newuser(self.u2, self.user_pass)
664 self.ldb_admin.newuser(self.u3, self.user_pass)
665 self.ldb_admin.newgroup(self.group1, grouptype=samba.dsdb.GTYPE_SECURITY_GLOBAL_GROUP)
666 self.ldb_admin.add_remove_group_members(self.group1, [self.u2],
667 add_members_operation=True)
668 self.ldb_user = self.get_ldb_connection(self.u1, self.user_pass)
669 self.ldb_user2 = self.get_ldb_connection(self.u2, self.user_pass)
670 self.ldb_user3 = self.get_ldb_connection(self.u3, self.user_pass)
671 self.full_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
672 Dn(self.ldb_admin, "OU=ou1," + self.base_dn),
673 Dn(self.ldb_admin, "OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
674 Dn(self.ldb_admin, "OU=ou4,OU=ou2,OU=ou1," + self.base_dn),
675 Dn(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
676 Dn(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)]
677 self.user_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.u1))
678 self.group_sid = self.sd_utils.get_object_sid(self.get_user_dn(self.group1))
680 def create_clean_ou(self, object_dn):
681 """ Base repeating setup for unittests to follow """
682 res = self.ldb_admin.search(base=self.base_dn, scope=SCOPE_SUBTREE, \
683 expression="distinguishedName=%s" % object_dn)
684 # Make sure top testing OU has been deleted before starting the test
685 self.assertEqual(len(res), 0)
686 self.ldb_admin.create_ou(object_dn)
687 desc_sddl = self.sd_utils.get_sd_as_sddl(object_dn)
688 # Make sure there are inheritable ACEs initially
689 self.assertTrue("CI" in desc_sddl or "OI" in desc_sddl)
690 # Find and remove all inherit ACEs
691 res = re.findall("\(.*?\)", desc_sddl)
692 res = [x for x in res if ("CI" in x) or ("OI" in x)]
694 desc_sddl = desc_sddl.replace(x, "")
695 # Add flag 'protected' in both DACL and SACL so no inherit ACEs
696 # can propagate from above
697 # remove SACL, we are not interested
698 desc_sddl = desc_sddl.replace(":AI", ":AIP")
699 self.sd_utils.modify_sd_on_dn(object_dn, desc_sddl)
700 # Verify all inheritable ACEs are gone
701 desc_sddl = self.sd_utils.get_sd_as_sddl(object_dn)
702 self.assertFalse("CI" in desc_sddl)
703 self.assertFalse("OI" in desc_sddl)
706 super(AclSearchTests, self).tearDown()
707 delete_force(self.ldb_admin, "OU=test_search_ou2,OU=test_search_ou1," + self.base_dn)
708 delete_force(self.ldb_admin, "OU=test_search_ou1," + self.base_dn)
709 delete_force(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
710 delete_force(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
711 delete_force(self.ldb_admin, "OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
712 delete_force(self.ldb_admin, "OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
713 delete_force(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn)
714 delete_force(self.ldb_admin, "OU=ou1," + self.base_dn)
715 delete_force(self.ldb_admin, self.get_user_dn("search_u1"))
716 delete_force(self.ldb_admin, self.get_user_dn("search_u2"))
717 delete_force(self.ldb_admin, self.get_user_dn("search_u3"))
718 delete_force(self.ldb_admin, self.get_user_dn("group1"))
724 def test_search_anonymous1(self):
725 """Verify access of rootDSE with the correct request"""
726 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
727 res = anonymous.search("", expression="(objectClass=*)", scope=SCOPE_BASE)
728 self.assertEquals(len(res), 1)
729 #verify some of the attributes
730 #don't care about values
731 self.assertTrue("ldapServiceName" in res[0])
732 self.assertTrue("namingContexts" in res[0])
733 self.assertTrue("isSynchronized" in res[0])
734 self.assertTrue("dsServiceName" in res[0])
735 self.assertTrue("supportedSASLMechanisms" in res[0])
736 self.assertTrue("isGlobalCatalogReady" in res[0])
737 self.assertTrue("domainControllerFunctionality" in res[0])
738 self.assertTrue("serverName" in res[0])
740 def test_search_anonymous2(self):
741 """Make sure we cannot access anything else"""
742 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
744 res = anonymous.search("", expression="(objectClass=*)", scope=SCOPE_SUBTREE)
745 except LdbError as e15:
747 self.assertEquals(num, ERR_OPERATIONS_ERROR)
751 res = anonymous.search(self.base_dn, expression="(objectClass=*)", scope=SCOPE_SUBTREE)
752 except LdbError as e16:
754 self.assertEquals(num, ERR_OPERATIONS_ERROR)
758 res = anonymous.search(anonymous.get_config_basedn(), expression="(objectClass=*)",
760 except LdbError as e17:
762 self.assertEquals(num, ERR_OPERATIONS_ERROR)
766 def test_search_anonymous3(self):
767 """Set dsHeuristics and repeat"""
768 self.ldb_admin.set_dsheuristics("0000002")
769 self.ldb_admin.create_ou("OU=test_search_ou1," + self.base_dn)
770 mod = "(A;CI;LC;;;AN)"
771 self.sd_utils.dacl_add_ace("OU=test_search_ou1," + self.base_dn, mod)
772 self.ldb_admin.create_ou("OU=test_search_ou2,OU=test_search_ou1," + self.base_dn)
773 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
774 res = anonymous.search("OU=test_search_ou2,OU=test_search_ou1," + self.base_dn,
775 expression="(objectClass=*)", scope=SCOPE_SUBTREE)
776 self.assertEquals(len(res), 1)
777 self.assertTrue("dn" in res[0])
778 self.assertTrue(res[0]["dn"] == Dn(self.ldb_admin,
779 "OU=test_search_ou2,OU=test_search_ou1," + self.base_dn))
780 res = anonymous.search(anonymous.get_config_basedn(), expression="(objectClass=*)",
782 self.assertEquals(len(res), 1)
783 self.assertTrue("dn" in res[0])
784 self.assertTrue(res[0]["dn"] == Dn(self.ldb_admin, self.configuration_dn))
786 def test_search1(self):
787 """Make sure users can see us if given LC to user and group"""
788 self.create_clean_ou("OU=ou1," + self.base_dn)
789 mod = "(A;;LC;;;%s)(A;;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
790 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
791 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
793 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
794 self.ldb_admin.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
795 self.ldb_admin.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
796 self.ldb_admin.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
797 self.ldb_admin.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
799 #regular users must see only ou1 and ou2
800 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
802 self.assertEquals(len(res), 2)
803 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
804 Dn(self.ldb_admin, "OU=ou1," + self.base_dn)]
806 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
807 self.assertEquals(sorted(res_list), sorted(ok_list))
809 #these users should see all ous
810 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
812 self.assertEquals(len(res), 6)
813 res_list = [ x["dn"] for x in res if x["dn"] in self.full_list ]
814 self.assertEquals(sorted(res_list), sorted(self.full_list))
816 res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
818 self.assertEquals(len(res), 6)
819 res_list = [ x["dn"] for x in res if x["dn"] in self.full_list ]
820 self.assertEquals(sorted(res_list), sorted(self.full_list))
822 def test_search2(self):
823 """Make sure users can't see us if access is explicitly denied"""
824 self.create_clean_ou("OU=ou1," + self.base_dn)
825 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn)
826 self.ldb_admin.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
827 self.ldb_admin.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
828 self.ldb_admin.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn)
829 self.ldb_admin.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)
830 mod = "(D;;LC;;;%s)(D;;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
831 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
832 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
834 #this user should see all ous
835 res_list = [ x["dn"] for x in res if x["dn"] in self.full_list ]
836 self.assertEquals(sorted(res_list), sorted(self.full_list))
838 #these users should see ou1, 2, 5 and 6 but not 3 and 4
839 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
841 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
842 Dn(self.ldb_admin, "OU=ou1," + self.base_dn),
843 Dn(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
844 Dn(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)]
845 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
846 self.assertEquals(sorted(res_list), sorted(ok_list))
848 res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
850 self.assertEquals(len(res), 4)
851 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
852 self.assertEquals(sorted(res_list), sorted(ok_list))
854 def test_search3(self):
855 """Make sure users can't see ous if access is explicitly denied - 2"""
856 self.create_clean_ou("OU=ou1," + self.base_dn)
857 mod = "(A;CI;LC;;;%s)(A;CI;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
858 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
859 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
861 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
862 self.ldb_admin.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
863 self.ldb_admin.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
864 self.ldb_admin.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
865 self.ldb_admin.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
867 print("Testing correct behavior on nonaccessible search base")
869 self.ldb_user3.search("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
871 except LdbError as e18:
873 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
877 mod = "(D;;LC;;;%s)(D;;LC;;;%s)" % (str(self.user_sid), str(self.group_sid))
878 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
880 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
881 Dn(self.ldb_admin, "OU=ou1," + self.base_dn)]
883 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
885 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
886 self.assertEquals(sorted(res_list), sorted(ok_list))
888 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
889 Dn(self.ldb_admin, "OU=ou1," + self.base_dn),
890 Dn(self.ldb_admin, "OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn),
891 Dn(self.ldb_admin, "OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn)]
893 #should not see ou3 and ou4, but should see ou5 and ou6
894 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
896 self.assertEquals(len(res), 4)
897 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
898 self.assertEquals(sorted(res_list), sorted(ok_list))
900 res = self.ldb_user2.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
902 self.assertEquals(len(res), 4)
903 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
904 self.assertEquals(sorted(res_list), sorted(ok_list))
906 def test_search4(self):
907 """There is no difference in visibility if the user is also creator"""
908 self.create_clean_ou("OU=ou1," + self.base_dn)
909 mod = "(A;CI;CC;;;%s)" % (str(self.user_sid))
910 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
911 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
913 self.ldb_user.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
914 self.ldb_user.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
915 self.ldb_user.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
916 self.ldb_user.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
917 self.ldb_user.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
919 ok_list = [Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn),
920 Dn(self.ldb_admin, "OU=ou1," + self.base_dn)]
921 res = self.ldb_user3.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
923 self.assertEquals(len(res), 2)
924 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
925 self.assertEquals(sorted(res_list), sorted(ok_list))
927 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(objectClass=*)",
929 self.assertEquals(len(res), 2)
930 res_list = [ x["dn"] for x in res if x["dn"] in ok_list ]
931 self.assertEquals(sorted(res_list), sorted(ok_list))
933 def test_search5(self):
934 """Make sure users can see only attributes they are allowed to see"""
935 self.create_clean_ou("OU=ou1," + self.base_dn)
936 mod = "(A;CI;LC;;;%s)" % (str(self.user_sid))
937 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
938 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
940 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
941 # assert user can only see dn
942 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
945 self.assertEquals(len(res), 1)
946 res_list = list(res[0].keys())
947 self.assertEquals(res_list, ok_list)
949 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
950 scope=SCOPE_BASE, attrs=["ou"])
952 self.assertEquals(len(res), 1)
953 res_list = list(res[0].keys())
954 self.assertEquals(res_list, ok_list)
956 #give read property on ou and assert user can only see dn and ou
957 mod = "(OA;;RP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % (str(self.user_sid))
958 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
959 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
960 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
962 ok_list = ['dn', 'ou']
963 self.assertEquals(len(res), 1)
964 res_list = list(res[0].keys())
965 self.assertEquals(sorted(res_list), sorted(ok_list))
967 #give read property on Public Information and assert user can see ou and other members
968 mod = "(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;%s)" % (str(self.user_sid))
969 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
970 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
971 res = self.ldb_user.search("OU=ou2,OU=ou1," + self.base_dn, expression="(objectClass=*)",
974 ok_list = ['dn', 'objectClass', 'ou', 'distinguishedName', 'name', 'objectGUID', 'objectCategory']
975 res_list = list(res[0].keys())
976 self.assertEquals(sorted(res_list), sorted(ok_list))
978 def test_search6(self):
979 """If an attribute that cannot be read is used in a filter, it is as if the attribute does not exist"""
980 self.create_clean_ou("OU=ou1," + self.base_dn)
981 mod = "(A;CI;LCCC;;;%s)" % (str(self.user_sid))
982 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
983 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
985 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
986 self.ldb_user.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
988 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou3)",
990 #nothing should be returned as ou is not accessible
991 self.assertEquals(len(res), 0)
993 #give read property on ou and assert user can only see dn and ou
994 mod = "(OA;;RP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % (str(self.user_sid))
995 self.sd_utils.dacl_add_ace("OU=ou3,OU=ou2,OU=ou1," + self.base_dn, mod)
996 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou3)",
998 self.assertEquals(len(res), 1)
999 ok_list = ['dn', 'ou']
1000 res_list = list(res[0].keys())
1001 self.assertEquals(sorted(res_list), sorted(ok_list))
1003 #give read property on Public Information and assert user can see ou and other members
1004 mod = "(OA;;RP;e48d0154-bcf8-11d1-8702-00c04fb96050;;%s)" % (str(self.user_sid))
1005 self.sd_utils.dacl_add_ace("OU=ou2,OU=ou1," + self.base_dn, mod)
1006 res = self.ldb_user.search("OU=ou1," + self.base_dn, expression="(ou=ou2)",
1007 scope=SCOPE_SUBTREE)
1008 self.assertEquals(len(res), 1)
1009 ok_list = ['dn', 'objectClass', 'ou', 'distinguishedName', 'name', 'objectGUID', 'objectCategory']
1010 res_list = list(res[0].keys())
1011 self.assertEquals(sorted(res_list), sorted(ok_list))
1013 def assert_search_on_attr(self, dn, samdb, attr, expected_list):
1015 expected_num = len(expected_list)
1016 res = samdb.search(dn, expression="(%s=*)" % attr, scope=SCOPE_SUBTREE)
1017 self.assertEquals(len(res), expected_num)
1019 res_list = [ x["dn"] for x in res if x["dn"] in expected_list ]
1020 self.assertEquals(sorted(res_list), sorted(expected_list))
1022 def test_search7(self):
1023 """Checks object search visibility when users don't have full rights"""
1024 self.create_clean_ou("OU=ou1," + self.base_dn)
1025 mod = "(A;;LC;;;%s)(A;;LC;;;%s)" % (str(self.user_sid),
1026 str(self.group_sid))
1027 self.sd_utils.dacl_add_ace("OU=ou1," + self.base_dn, mod)
1028 tmp_desc = security.descriptor.from_sddl("D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)" + mod,
1030 self.ldb_admin.create_ou("OU=ou2,OU=ou1," + self.base_dn, sd=tmp_desc)
1031 self.ldb_admin.create_ou("OU=ou3,OU=ou2,OU=ou1," + self.base_dn,
1033 self.ldb_admin.create_ou("OU=ou4,OU=ou2,OU=ou1," + self.base_dn,
1035 self.ldb_admin.create_ou("OU=ou5,OU=ou3,OU=ou2,OU=ou1," + self.base_dn,
1037 self.ldb_admin.create_ou("OU=ou6,OU=ou4,OU=ou2,OU=ou1," + self.base_dn,
1040 ou2_dn = Dn(self.ldb_admin, "OU=ou2,OU=ou1," + self.base_dn)
1041 ou1_dn = Dn(self.ldb_admin, "OU=ou1," + self.base_dn)
1043 # even though unprivileged users can't read these attributes for OU2,
1044 # the object should still be visible in searches, because they have
1045 # 'List Contents' rights still. This isn't really disclosive because
1046 # ALL objects have these attributes
1047 visible_attrs = ["objectClass", "distinguishedName", "name",
1049 two_objects = [ou2_dn, ou1_dn]
1051 for attr in visible_attrs:
1052 # a regular user should just see the 2 objects
1053 self.assert_search_on_attr(str(ou1_dn), self.ldb_user3, attr,
1054 expected_list=two_objects)
1056 # whereas the following users have LC rights for all the objects,
1057 # so they should see them all
1058 self.assert_search_on_attr(str(ou1_dn), self.ldb_user, attr,
1059 expected_list=self.full_list)
1060 self.assert_search_on_attr(str(ou1_dn), self.ldb_user2, attr,
1061 expected_list=self.full_list)
1063 # however when searching on the following attributes, objects will not
1064 # be visible unless the user has Read Property rights
1065 hidden_attrs = ["objectCategory", "instanceType", "ou", "uSNChanged",
1066 "uSNCreated", "whenCreated"]
1067 one_object = [ou1_dn]
1069 for attr in hidden_attrs:
1070 self.assert_search_on_attr(str(ou1_dn), self.ldb_user3, attr,
1071 expected_list=one_object)
1072 self.assert_search_on_attr(str(ou1_dn), self.ldb_user, attr,
1073 expected_list=one_object)
1074 self.assert_search_on_attr(str(ou1_dn), self.ldb_user2, attr,
1075 expected_list=one_object)
1077 # admin has RP rights so can still see all the objects
1078 self.assert_search_on_attr(str(ou1_dn), self.ldb_admin, attr,
1079 expected_list=self.full_list)
1081 #tests on ldap delete operations
1082 class AclDeleteTests(AclTests):
1085 super(AclDeleteTests, self).setUp()
1086 self.regular_user = "acl_delete_user1"
1087 # Create regular user
1088 self.ldb_admin.newuser(self.regular_user, self.user_pass)
1089 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
1092 super(AclDeleteTests, self).tearDown()
1093 delete_force(self.ldb_admin, self.get_user_dn("test_delete_user1"))
1094 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
1095 delete_force(self.ldb_admin, self.get_user_dn("test_anonymous"))
1099 def test_delete_u1(self):
1100 """User is prohibited by default to delete another User object"""
1101 # Create user that we try to delete
1102 self.ldb_admin.newuser("test_delete_user1", self.user_pass)
1103 # Here delete User object should ALWAYS through exception
1105 self.ldb_user.delete(self.get_user_dn("test_delete_user1"))
1106 except LdbError as e19:
1108 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1112 def test_delete_u2(self):
1113 """User's group has RIGHT_DELETE to another User object"""
1114 user_dn = self.get_user_dn("test_delete_user1")
1115 # Create user that we try to delete
1116 self.ldb_admin.newuser("test_delete_user1", self.user_pass)
1117 mod = "(A;;SD;;;AU)"
1118 self.sd_utils.dacl_add_ace(user_dn, mod)
1119 # Try to delete User object
1120 self.ldb_user.delete(user_dn)
1121 res = self.ldb_admin.search(self.base_dn,
1122 expression="(distinguishedName=%s)" % user_dn)
1123 self.assertEqual(len(res), 0)
1125 def test_delete_u3(self):
1126 """User indentified by SID has RIGHT_DELETE to another User object"""
1127 user_dn = self.get_user_dn("test_delete_user1")
1128 # Create user that we try to delete
1129 self.ldb_admin.newuser("test_delete_user1", self.user_pass)
1130 mod = "(A;;SD;;;%s)" % self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1131 self.sd_utils.dacl_add_ace(user_dn, mod)
1132 # Try to delete User object
1133 self.ldb_user.delete(user_dn)
1134 res = self.ldb_admin.search(self.base_dn,
1135 expression="(distinguishedName=%s)" % user_dn)
1136 self.assertEqual(len(res), 0)
1138 def test_delete_anonymous(self):
1139 """Test add operation with anonymous user"""
1140 anonymous = SamDB(url=ldaphost, credentials=self.creds_tmp, lp=lp)
1141 self.ldb_admin.newuser("test_anonymous", "samba123@")
1144 anonymous.delete(self.get_user_dn("test_anonymous"))
1145 except LdbError as e20:
1147 self.assertEquals(num, ERR_OPERATIONS_ERROR)
1151 #tests on ldap rename operations
1152 class AclRenameTests(AclTests):
1155 super(AclRenameTests, self).setUp()
1156 self.regular_user = "acl_rename_user1"
1157 self.ou1 = "OU=test_rename_ou1"
1158 self.ou2 = "OU=test_rename_ou2"
1159 self.ou3 = "OU=test_rename_ou3,%s" % self.ou2
1160 self.testuser1 = "test_rename_user1"
1161 self.testuser2 = "test_rename_user2"
1162 self.testuser3 = "test_rename_user3"
1163 self.testuser4 = "test_rename_user4"
1164 self.testuser5 = "test_rename_user5"
1165 # Create regular user
1166 self.ldb_admin.newuser(self.regular_user, self.user_pass)
1167 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
1170 super(AclRenameTests, self).tearDown()
1172 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser1, self.ou3, self.base_dn))
1173 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser2, self.ou3, self.base_dn))
1174 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser5, self.ou3, self.base_dn))
1175 delete_force(self.ldb_admin, "%s,%s" % (self.ou3, self.base_dn))
1177 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser1, self.ou2, self.base_dn))
1178 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser2, self.ou2, self.base_dn))
1179 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser5, self.ou2, self.base_dn))
1180 delete_force(self.ldb_admin, "%s,%s" % (self.ou2, self.base_dn))
1182 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser1, self.ou1, self.base_dn))
1183 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser2, self.ou1, self.base_dn))
1184 delete_force(self.ldb_admin, "CN=%s,%s,%s" % (self.testuser5, self.ou1, self.base_dn))
1185 delete_force(self.ldb_admin, "OU=test_rename_ou3,%s,%s" % (self.ou1, self.base_dn))
1186 delete_force(self.ldb_admin, "%s,%s" % (self.ou1, self.base_dn))
1187 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
1191 def test_rename_u1(self):
1192 """Regular user fails to rename 'User object' within single OU"""
1193 # Create OU structure
1194 self.ldb_admin.create_ou("OU=test_rename_ou1," + self.base_dn)
1195 self.ldb_admin.newuser(self.testuser1, self.user_pass, userou=self.ou1)
1197 self.ldb_user.rename("CN=%s,%s,%s" % (self.testuser1, self.ou1, self.base_dn), \
1198 "CN=%s,%s,%s" % (self.testuser5, self.ou1, self.base_dn))
1199 except LdbError as e21:
1201 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1205 def test_rename_u2(self):
1206 """Grant WRITE_PROPERTY to AU so regular user can rename 'User object' within single OU"""
1207 ou_dn = "OU=test_rename_ou1," + self.base_dn
1208 user_dn = "CN=test_rename_user1," + ou_dn
1209 rename_user_dn = "CN=test_rename_user5," + ou_dn
1210 # Create OU structure
1211 self.ldb_admin.create_ou(ou_dn)
1212 self.ldb_admin.newuser(self.testuser1, self.user_pass, userou=self.ou1)
1213 mod = "(A;;WP;;;AU)"
1214 self.sd_utils.dacl_add_ace(user_dn, mod)
1215 # Rename 'User object' having WP to AU
1216 self.ldb_user.rename(user_dn, rename_user_dn)
1217 res = self.ldb_admin.search(self.base_dn,
1218 expression="(distinguishedName=%s)" % user_dn)
1219 self.assertEqual(len(res), 0)
1220 res = self.ldb_admin.search(self.base_dn,
1221 expression="(distinguishedName=%s)" % rename_user_dn)
1222 self.assertNotEqual(len(res), 0)
1224 def test_rename_u3(self):
1225 """Test rename with rights granted to 'User object' SID"""
1226 ou_dn = "OU=test_rename_ou1," + self.base_dn
1227 user_dn = "CN=test_rename_user1," + ou_dn
1228 rename_user_dn = "CN=test_rename_user5," + ou_dn
1229 # Create OU structure
1230 self.ldb_admin.create_ou(ou_dn)
1231 self.ldb_admin.newuser(self.testuser1, self.user_pass, userou=self.ou1)
1232 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1233 mod = "(A;;WP;;;%s)" % str(sid)
1234 self.sd_utils.dacl_add_ace(user_dn, mod)
1235 # Rename 'User object' having WP to AU
1236 self.ldb_user.rename(user_dn, rename_user_dn)
1237 res = self.ldb_admin.search(self.base_dn,
1238 expression="(distinguishedName=%s)" % user_dn)
1239 self.assertEqual(len(res), 0)
1240 res = self.ldb_admin.search(self.base_dn,
1241 expression="(distinguishedName=%s)" % rename_user_dn)
1242 self.assertNotEqual(len(res), 0)
1244 def test_rename_u4(self):
1245 """Rename 'User object' cross OU with WP, SD and CC right granted on reg. user to AU"""
1246 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1247 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1248 user_dn = "CN=test_rename_user2," + ou1_dn
1249 rename_user_dn = "CN=test_rename_user5," + ou2_dn
1250 # Create OU structure
1251 self.ldb_admin.create_ou(ou1_dn)
1252 self.ldb_admin.create_ou(ou2_dn)
1253 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1254 mod = "(A;;WPSD;;;AU)"
1255 self.sd_utils.dacl_add_ace(user_dn, mod)
1256 mod = "(A;;CC;;;AU)"
1257 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1258 # Rename 'User object' having SD and CC to AU
1259 self.ldb_user.rename(user_dn, rename_user_dn)
1260 res = self.ldb_admin.search(self.base_dn,
1261 expression="(distinguishedName=%s)" % user_dn)
1262 self.assertEqual(len(res), 0)
1263 res = self.ldb_admin.search(self.base_dn,
1264 expression="(distinguishedName=%s)" % rename_user_dn)
1265 self.assertNotEqual(len(res), 0)
1267 def test_rename_u5(self):
1268 """Test rename with rights granted to 'User object' SID"""
1269 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1270 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1271 user_dn = "CN=test_rename_user2," + ou1_dn
1272 rename_user_dn = "CN=test_rename_user5," + ou2_dn
1273 # Create OU structure
1274 self.ldb_admin.create_ou(ou1_dn)
1275 self.ldb_admin.create_ou(ou2_dn)
1276 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1277 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1278 mod = "(A;;WPSD;;;%s)" % str(sid)
1279 self.sd_utils.dacl_add_ace(user_dn, mod)
1280 mod = "(A;;CC;;;%s)" % str(sid)
1281 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1282 # Rename 'User object' having SD and CC to AU
1283 self.ldb_user.rename(user_dn, rename_user_dn)
1284 res = self.ldb_admin.search(self.base_dn,
1285 expression="(distinguishedName=%s)" % user_dn)
1286 self.assertEqual(len(res), 0)
1287 res = self.ldb_admin.search(self.base_dn,
1288 expression="(distinguishedName=%s)" % rename_user_dn)
1289 self.assertNotEqual(len(res), 0)
1291 def test_rename_u6(self):
1292 """Rename 'User object' cross OU with WP, DC and CC right granted on OU & user to AU"""
1293 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1294 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1295 user_dn = "CN=test_rename_user2," + ou1_dn
1296 rename_user_dn = "CN=test_rename_user2," + ou2_dn
1297 # Create OU structure
1298 self.ldb_admin.create_ou(ou1_dn)
1299 self.ldb_admin.create_ou(ou2_dn)
1300 #mod = "(A;CI;DCWP;;;AU)"
1301 mod = "(A;;DC;;;AU)"
1302 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1303 mod = "(A;;CC;;;AU)"
1304 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1305 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1306 mod = "(A;;WP;;;AU)"
1307 self.sd_utils.dacl_add_ace(user_dn, mod)
1308 # Rename 'User object' having SD and CC to AU
1309 self.ldb_user.rename(user_dn, rename_user_dn)
1310 res = self.ldb_admin.search(self.base_dn,
1311 expression="(distinguishedName=%s)" % user_dn)
1312 self.assertEqual(len(res), 0)
1313 res = self.ldb_admin.search(self.base_dn,
1314 expression="(distinguishedName=%s)" % rename_user_dn)
1315 self.assertNotEqual(len(res), 0)
1317 def test_rename_u7(self):
1318 """Rename 'User object' cross OU (second level) with WP, DC and CC right granted on OU to AU"""
1319 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1320 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1321 ou3_dn = "OU=test_rename_ou3," + ou2_dn
1322 user_dn = "CN=test_rename_user2," + ou1_dn
1323 rename_user_dn = "CN=test_rename_user5," + ou3_dn
1324 # Create OU structure
1325 self.ldb_admin.create_ou(ou1_dn)
1326 self.ldb_admin.create_ou(ou2_dn)
1327 self.ldb_admin.create_ou(ou3_dn)
1328 mod = "(A;CI;WPDC;;;AU)"
1329 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1330 mod = "(A;;CC;;;AU)"
1331 self.sd_utils.dacl_add_ace(ou3_dn, mod)
1332 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1333 # Rename 'User object' having SD and CC to AU
1334 self.ldb_user.rename(user_dn, rename_user_dn)
1335 res = self.ldb_admin.search(self.base_dn,
1336 expression="(distinguishedName=%s)" % user_dn)
1337 self.assertEqual(len(res), 0)
1338 res = self.ldb_admin.search(self.base_dn,
1339 expression="(distinguishedName=%s)" % rename_user_dn)
1340 self.assertNotEqual(len(res), 0)
1342 def test_rename_u8(self):
1343 """Test rename on an object with and without modify access on the RDN attribute"""
1344 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1345 ou2_dn = "OU=test_rename_ou2," + ou1_dn
1346 ou3_dn = "OU=test_rename_ou3," + ou1_dn
1347 # Create OU structure
1348 self.ldb_admin.create_ou(ou1_dn)
1349 self.ldb_admin.create_ou(ou2_dn)
1350 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1351 mod = "(OA;;WP;bf967a0e-0de6-11d0-a285-00aa003049e2;;%s)" % str(sid)
1352 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1353 mod = "(OD;;WP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % str(sid)
1354 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1356 self.ldb_user.rename(ou2_dn, ou3_dn)
1357 except LdbError as e22:
1359 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1361 # This rename operation should always throw ERR_INSUFFICIENT_ACCESS_RIGHTS
1363 sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1364 mod = "(A;;WP;bf9679f0-0de6-11d0-a285-00aa003049e2;;%s)" % str(sid)
1365 self.sd_utils.dacl_add_ace(ou2_dn, mod)
1366 self.ldb_user.rename(ou2_dn, ou3_dn)
1367 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % ou2_dn)
1368 self.assertEqual(len(res), 0)
1369 res = self.ldb_admin.search(self.base_dn, expression="(distinguishedName=%s)" % ou3_dn)
1370 self.assertNotEqual(len(res), 0)
1372 def test_rename_u9(self):
1373 """Rename 'User object' cross OU, with explicit deny on sd and dc"""
1374 ou1_dn = "OU=test_rename_ou1," + self.base_dn
1375 ou2_dn = "OU=test_rename_ou2," + self.base_dn
1376 user_dn = "CN=test_rename_user2," + ou1_dn
1377 rename_user_dn = "CN=test_rename_user5," + ou2_dn
1378 # Create OU structure
1379 self.ldb_admin.create_ou(ou1_dn)
1380 self.ldb_admin.create_ou(ou2_dn)
1381 self.ldb_admin.newuser(self.testuser2, self.user_pass, userou=self.ou1)
1382 mod = "(D;;SD;;;DA)"
1383 self.sd_utils.dacl_add_ace(user_dn, mod)
1384 mod = "(D;;DC;;;DA)"
1385 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1386 # Rename 'User object' having SD and CC to AU
1388 self.ldb_admin.rename(user_dn, rename_user_dn)
1389 except LdbError as e23:
1391 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1394 #add an allow ace so we can delete this ou
1395 mod = "(A;;DC;;;DA)"
1396 self.sd_utils.dacl_add_ace(ou1_dn, mod)
1399 #tests on Control Access Rights
1400 class AclCARTests(AclTests):
1403 super(AclCARTests, self).setUp()
1405 # Get the old "dSHeuristics" if it was set
1406 dsheuristics = self.ldb_admin.get_dsheuristics()
1407 # Reset the "dSHeuristics" as they were before
1408 self.addCleanup(self.ldb_admin.set_dsheuristics, dsheuristics)
1409 # Set the "dSHeuristics" to activate the correct "userPassword" behaviour
1410 self.ldb_admin.set_dsheuristics("000000001")
1411 # Get the old "minPwdAge"
1412 minPwdAge = self.ldb_admin.get_minPwdAge()
1413 # Reset the "minPwdAge" as it was before
1414 self.addCleanup(self.ldb_admin.set_minPwdAge, minPwdAge)
1415 # Set it temporarely to "0"
1416 self.ldb_admin.set_minPwdAge("0")
1418 self.user_with_wp = "acl_car_user1"
1419 self.user_with_pc = "acl_car_user2"
1420 self.ldb_admin.newuser(self.user_with_wp, self.user_pass)
1421 self.ldb_admin.newuser(self.user_with_pc, self.user_pass)
1422 self.ldb_user = self.get_ldb_connection(self.user_with_wp, self.user_pass)
1423 self.ldb_user2 = self.get_ldb_connection(self.user_with_pc, self.user_pass)
1426 super(AclCARTests, self).tearDown()
1427 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_wp))
1428 delete_force(self.ldb_admin, self.get_user_dn(self.user_with_pc))
1433 def test_change_password1(self):
1434 """Try a password change operation without any CARs given"""
1435 #users have change password by default - remove for negative testing
1436 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1437 sddl = desc.as_sddl(self.domain_sid)
1438 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)", "")
1439 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)", "")
1440 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1442 self.ldb_user.modify_ldif("""
1443 dn: """ + self.get_user_dn(self.user_with_wp) + """
1446 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')).decode('utf8') + """
1448 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')).decode('utf8') + """
1450 except LdbError as e24:
1452 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1454 # for some reason we get constraint violation instead of insufficient access error
1457 def test_change_password2(self):
1458 """Make sure WP has no influence"""
1459 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1460 sddl = desc.as_sddl(self.domain_sid)
1461 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)", "")
1462 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)", "")
1463 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1464 mod = "(A;;WP;;;PS)"
1465 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1466 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1467 sddl = desc.as_sddl(self.domain_sid)
1469 self.ldb_user.modify_ldif("""
1470 dn: """ + self.get_user_dn(self.user_with_wp) + """
1473 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')).decode('utf8') + """
1475 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')).decode('utf8') + """
1477 except LdbError as e25:
1479 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1481 # for some reason we get constraint violation instead of insufficient access error
1484 def test_change_password3(self):
1485 """Make sure WP has no influence"""
1486 mod = "(D;;WP;;;PS)"
1487 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1488 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1489 sddl = desc.as_sddl(self.domain_sid)
1490 self.ldb_user.modify_ldif("""
1491 dn: """ + self.get_user_dn(self.user_with_wp) + """
1494 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')).decode('utf8') + """
1496 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')).decode('utf8') + """
1499 def test_change_password5(self):
1500 """Make sure rights have no influence on dBCSPwd"""
1501 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1502 sddl = desc.as_sddl(self.domain_sid)
1503 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;WD)", "")
1504 sddl = sddl.replace("(OA;;CR;ab721a53-1e2f-11d0-9819-00aa0040529b;;PS)", "")
1505 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1506 mod = "(D;;WP;;;PS)"
1507 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1509 self.ldb_user.modify_ldif("""
1510 dn: """ + self.get_user_dn(self.user_with_wp) + """
1513 dBCSPwd: XXXXXXXXXXXXXXXX
1515 dBCSPwd: YYYYYYYYYYYYYYYY
1517 except LdbError as e26:
1519 self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1523 def test_change_password6(self):
1524 """Test uneven delete/adds"""
1526 self.ldb_user.modify_ldif("""
1527 dn: """ + self.get_user_dn(self.user_with_wp) + """
1529 delete: userPassword
1530 userPassword: thatsAcomplPASS1
1531 delete: userPassword
1532 userPassword: thatsAcomplPASS1
1534 userPassword: thatsAcomplPASS2
1536 except LdbError as e27:
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)
1544 self.ldb_user.modify_ldif("""
1545 dn: """ + self.get_user_dn(self.user_with_wp) + """
1547 delete: userPassword
1548 userPassword: thatsAcomplPASS1
1549 delete: userPassword
1550 userPassword: thatsAcomplPASS1
1552 userPassword: thatsAcomplPASS2
1554 # This fails on Windows 2000 domain level with constraint violation
1555 except LdbError as e28:
1557 self.assertTrue(num == ERR_CONSTRAINT_VIOLATION or
1558 num == ERR_UNWILLING_TO_PERFORM)
1563 def test_change_password7(self):
1564 """Try a password change operation without any CARs given"""
1565 #users have change password by default - remove for negative testing
1566 desc = self.sd_utils.read_sd_on_dn(self.get_user_dn(self.user_with_wp))
1567 sddl = desc.as_sddl(self.domain_sid)
1568 self.sd_utils.modify_sd_on_dn(self.get_user_dn(self.user_with_wp), sddl)
1569 #first change our own password
1570 self.ldb_user2.modify_ldif("""
1571 dn: """ + self.get_user_dn(self.user_with_pc) + """
1574 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')).decode('utf8') + """
1576 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')).decode('utf8') + """
1578 #then someone else's
1579 self.ldb_user2.modify_ldif("""
1580 dn: """ + self.get_user_dn(self.user_with_wp) + """
1583 unicodePwd:: """ + base64.b64encode("\"samba123@\"".encode('utf-16-le')).decode('utf8') + """
1585 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS2\"".encode('utf-16-le')).decode('utf8') + """
1588 def test_reset_password1(self):
1589 """Try a user password reset operation (unicodePwd) before and after granting CAR"""
1591 self.ldb_user.modify_ldif("""
1592 dn: """ + self.get_user_dn(self.user_with_wp) + """
1595 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')).decode('utf8') + """
1597 except LdbError as e29:
1599 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1602 mod = "(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1603 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1604 self.ldb_user.modify_ldif("""
1605 dn: """ + self.get_user_dn(self.user_with_wp) + """
1608 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')).decode('utf8') + """
1611 def test_reset_password2(self):
1612 """Try a user password reset operation (userPassword) before and after granting CAR"""
1614 self.ldb_user.modify_ldif("""
1615 dn: """ + self.get_user_dn(self.user_with_wp) + """
1617 replace: userPassword
1618 userPassword: thatsAcomplPASS1
1620 except LdbError as e30:
1622 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1625 mod = "(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 e31:
1637 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1639 def test_reset_password3(self):
1640 """Grant WP and see what happens (unicodePwd)"""
1641 mod = "(A;;WP;;;PS)"
1642 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1644 self.ldb_user.modify_ldif("""
1645 dn: """ + self.get_user_dn(self.user_with_wp) + """
1648 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')).decode('utf8') + """
1650 except LdbError as e32:
1652 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1656 def test_reset_password4(self):
1657 """Grant WP and see what happens (userPassword)"""
1658 mod = "(A;;WP;;;PS)"
1659 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1661 self.ldb_user.modify_ldif("""
1662 dn: """ + self.get_user_dn(self.user_with_wp) + """
1664 replace: userPassword
1665 userPassword: thatsAcomplPASS1
1667 except LdbError as e33:
1669 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1673 def test_reset_password5(self):
1674 """Explicitly deny WP but grant CAR (unicodePwd)"""
1675 mod = "(D;;WP;;;PS)(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1676 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1677 self.ldb_user.modify_ldif("""
1678 dn: """ + self.get_user_dn(self.user_with_wp) + """
1681 unicodePwd:: """ + base64.b64encode("\"thatsAcomplPASS1\"".encode('utf-16-le')).decode('utf8') + """
1684 def test_reset_password6(self):
1685 """Explicitly deny WP but grant CAR (userPassword)"""
1686 mod = "(D;;WP;;;PS)(OA;;CR;00299570-246d-11d0-a768-00aa006e0529;;PS)"
1687 self.sd_utils.dacl_add_ace(self.get_user_dn(self.user_with_wp), mod)
1689 self.ldb_user.modify_ldif("""
1690 dn: """ + self.get_user_dn(self.user_with_wp) + """
1692 replace: userPassword
1693 userPassword: thatsAcomplPASS1
1695 # This fails on Windows 2000 domain level with constraint violation
1696 except LdbError as e34:
1698 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1700 class AclExtendedTests(AclTests):
1703 super(AclExtendedTests, self).setUp()
1704 #regular user, will be the creator
1710 self.ldb_admin.newuser(self.u1, self.user_pass)
1711 self.ldb_admin.newuser(self.u2, self.user_pass)
1712 self.ldb_admin.newuser(self.u3, self.user_pass)
1713 self.ldb_admin.add_remove_group_members("Domain Admins", [self.u3],
1714 add_members_operation=True)
1715 self.ldb_user1 = self.get_ldb_connection(self.u1, self.user_pass)
1716 self.ldb_user2 = self.get_ldb_connection(self.u2, self.user_pass)
1717 self.ldb_user3 = self.get_ldb_connection(self.u3, self.user_pass)
1718 self.user_sid1 = self.sd_utils.get_object_sid(self.get_user_dn(self.u1))
1719 self.user_sid2 = self.sd_utils.get_object_sid(self.get_user_dn(self.u2))
1722 super(AclExtendedTests, self).tearDown()
1723 delete_force(self.ldb_admin, self.get_user_dn(self.u1))
1724 delete_force(self.ldb_admin, self.get_user_dn(self.u2))
1725 delete_force(self.ldb_admin, self.get_user_dn(self.u3))
1726 delete_force(self.ldb_admin, "CN=ext_group1,OU=ext_ou1," + self.base_dn)
1727 delete_force(self.ldb_admin, "ou=ext_ou1," + self.base_dn)
1733 def test_ntSecurityDescriptor(self):
1735 self.ldb_admin.create_ou("ou=ext_ou1," + self.base_dn)
1736 #give u1 Create children access
1737 mod = "(A;;CC;;;%s)" % str(self.user_sid1)
1738 self.sd_utils.dacl_add_ace("OU=ext_ou1," + self.base_dn, mod)
1739 mod = "(A;;LC;;;%s)" % str(self.user_sid2)
1740 self.sd_utils.dacl_add_ace("OU=ext_ou1," + self.base_dn, mod)
1741 #create a group under that, grant RP to u2
1742 self.ldb_user1.newgroup("ext_group1", groupou="OU=ext_ou1",
1743 grouptype=samba.dsdb.GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)
1744 mod = "(A;;RP;;;%s)" % str(self.user_sid2)
1745 self.sd_utils.dacl_add_ace("CN=ext_group1,OU=ext_ou1," + self.base_dn, mod)
1746 #u2 must not read the descriptor
1747 res = self.ldb_user2.search("CN=ext_group1,OU=ext_ou1," + self.base_dn,
1748 SCOPE_BASE, None, ["nTSecurityDescriptor"])
1749 self.assertNotEqual(len(res), 0)
1750 self.assertFalse("nTSecurityDescriptor" in res[0].keys())
1751 #grant RC to u2 - still no access
1752 mod = "(A;;RC;;;%s)" % str(self.user_sid2)
1753 self.sd_utils.dacl_add_ace("CN=ext_group1,OU=ext_ou1," + self.base_dn, mod)
1754 res = self.ldb_user2.search("CN=ext_group1,OU=ext_ou1," + self.base_dn,
1755 SCOPE_BASE, None, ["nTSecurityDescriptor"])
1756 self.assertNotEqual(len(res), 0)
1757 self.assertFalse("nTSecurityDescriptor" in res[0].keys())
1758 #u3 is member of administrators group, should be able to read sd
1759 res = self.ldb_user3.search("CN=ext_group1,OU=ext_ou1," + self.base_dn,
1760 SCOPE_BASE, None, ["nTSecurityDescriptor"])
1761 self.assertEqual(len(res),1)
1762 self.assertTrue("nTSecurityDescriptor" in res[0].keys())
1764 class AclUndeleteTests(AclTests):
1767 super(AclUndeleteTests, self).setUp()
1768 self.regular_user = "undeleter1"
1769 self.ou1 = "OU=undeleted_ou,"
1770 self.testuser1 = "to_be_undeleted1"
1771 self.testuser2 = "to_be_undeleted2"
1772 self.testuser3 = "to_be_undeleted3"
1773 self.testuser4 = "to_be_undeleted4"
1774 self.testuser5 = "to_be_undeleted5"
1775 self.testuser6 = "to_be_undeleted6"
1777 self.new_dn_ou = "CN="+ self.testuser4 + "," + self.ou1 + self.base_dn
1779 # Create regular user
1780 self.testuser1_dn = self.get_user_dn(self.testuser1)
1781 self.testuser2_dn = self.get_user_dn(self.testuser2)
1782 self.testuser3_dn = self.get_user_dn(self.testuser3)
1783 self.testuser4_dn = self.get_user_dn(self.testuser4)
1784 self.testuser5_dn = self.get_user_dn(self.testuser5)
1785 self.deleted_dn1 = self.create_delete_user(self.testuser1)
1786 self.deleted_dn2 = self.create_delete_user(self.testuser2)
1787 self.deleted_dn3 = self.create_delete_user(self.testuser3)
1788 self.deleted_dn4 = self.create_delete_user(self.testuser4)
1789 self.deleted_dn5 = self.create_delete_user(self.testuser5)
1791 self.ldb_admin.create_ou(self.ou1 + self.base_dn)
1793 self.ldb_admin.newuser(self.regular_user, self.user_pass)
1794 self.ldb_admin.add_remove_group_members("Domain Admins", [self.regular_user],
1795 add_members_operation=True)
1796 self.ldb_user = self.get_ldb_connection(self.regular_user, self.user_pass)
1797 self.sid = self.sd_utils.get_object_sid(self.get_user_dn(self.regular_user))
1800 super(AclUndeleteTests, self).tearDown()
1801 delete_force(self.ldb_admin, self.get_user_dn(self.regular_user))
1802 delete_force(self.ldb_admin, self.get_user_dn(self.testuser1))
1803 delete_force(self.ldb_admin, self.get_user_dn(self.testuser2))
1804 delete_force(self.ldb_admin, self.get_user_dn(self.testuser3))
1805 delete_force(self.ldb_admin, self.get_user_dn(self.testuser4))
1806 delete_force(self.ldb_admin, self.get_user_dn(self.testuser5))
1807 delete_force(self.ldb_admin, self.new_dn_ou)
1808 delete_force(self.ldb_admin, self.ou1 + self.base_dn)
1812 def GUID_string(self, guid):
1813 return ldb.schema_format_value("objectGUID", guid)
1815 def create_delete_user(self, new_user):
1816 self.ldb_admin.newuser(new_user, self.user_pass)
1818 res = self.ldb_admin.search(expression="(objectClass=*)",
1819 base=self.get_user_dn(new_user),
1821 controls=["show_deleted:1"])
1822 guid = res[0]["objectGUID"][0]
1823 self.ldb_admin.delete(self.get_user_dn(new_user))
1824 res = self.ldb_admin.search(base="<GUID=%s>" % self.GUID_string(guid),
1825 scope=SCOPE_BASE, controls=["show_deleted:1"])
1826 self.assertEquals(len(res), 1)
1827 return str(res[0].dn)
1829 def undelete_deleted(self, olddn, newdn):
1831 msg.dn = Dn(self.ldb_user, olddn)
1832 msg["isDeleted"] = MessageElement([], FLAG_MOD_DELETE, "isDeleted")
1833 msg["distinguishedName"] = MessageElement([newdn], FLAG_MOD_REPLACE, "distinguishedName")
1834 res = self.ldb_user.modify(msg, ["show_recycled:1"])
1836 def undelete_deleted_with_mod(self, olddn, newdn):
1838 msg.dn = Dn(ldb, olddn)
1839 msg["isDeleted"] = MessageElement([], FLAG_MOD_DELETE, "isDeleted")
1840 msg["distinguishedName"] = MessageElement([newdn], FLAG_MOD_REPLACE, "distinguishedName")
1841 msg["url"] = MessageElement(["www.samba.org"], FLAG_MOD_REPLACE, "url")
1842 res = self.ldb_user.modify(msg, ["show_deleted:1"])
1844 def test_undelete(self):
1845 # it appears the user has to have LC on the old parent to be able to move the object
1846 # otherwise we get no such object. Since only System can modify the SD on deleted object
1847 # we cannot grant this permission via LDAP, and this leaves us with "negative" tests at the moment
1849 # deny write property on rdn, should fail
1850 mod = "(OD;;WP;bf967a0e-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
1851 self.sd_utils.dacl_add_ace(self.deleted_dn1, mod)
1853 self.undelete_deleted(self.deleted_dn1, self.testuser1_dn)
1855 except LdbError as e35:
1857 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1859 # seems that permissions on isDeleted and distinguishedName are irrelevant
1860 mod = "(OD;;WP;bf96798f-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
1861 self.sd_utils.dacl_add_ace(self.deleted_dn2, mod)
1862 mod = "(OD;;WP;bf9679e4-0de6-11d0-a285-00aa003049e2;;%s)" % str(self.sid)
1863 self.sd_utils.dacl_add_ace(self.deleted_dn2, mod)
1864 self.undelete_deleted(self.deleted_dn2, self.testuser2_dn)
1866 # attempt undelete with simultanious addition of url, WP to which is denied
1867 mod = "(OD;;WP;9a9a0221-4a5b-11d1-a9c3-0000f80367c1;;%s)" % str(self.sid)
1868 self.sd_utils.dacl_add_ace(self.deleted_dn3, mod)
1870 self.undelete_deleted_with_mod(self.deleted_dn3, self.testuser3_dn)
1872 except LdbError as e36:
1874 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1876 # undelete in an ou, in which we have no right to create children
1877 mod = "(D;;CC;;;%s)" % str(self.sid)
1878 self.sd_utils.dacl_add_ace(self.ou1 + self.base_dn, mod)
1880 self.undelete_deleted(self.deleted_dn4, self.new_dn_ou)
1882 except LdbError as e37:
1884 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1886 # delete is not required
1887 mod = "(D;;SD;;;%s)" % str(self.sid)
1888 self.sd_utils.dacl_add_ace(self.deleted_dn5, mod)
1889 self.undelete_deleted(self.deleted_dn5, self.testuser5_dn)
1891 # deny Reanimate-Tombstone, should fail
1892 mod = "(OD;;CR;45ec5156-db7e-47bb-b53f-dbeb2d03c40f;;%s)" % str(self.sid)
1893 self.sd_utils.dacl_add_ace(self.base_dn, mod)
1895 self.undelete_deleted(self.deleted_dn4, self.testuser4_dn)
1897 except LdbError as e38:
1899 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
1901 class AclSPNTests(AclTests):
1904 super(AclSPNTests, self).setUp()
1905 self.dcname = "TESTSRV8"
1906 self.rodcname = "TESTRODC8"
1907 self.computername = "testcomp8"
1908 self.test_user = "spn_test_user8"
1909 self.computerdn = "CN=%s,CN=computers,%s" % (self.computername, self.base_dn)
1910 self.dc_dn = "CN=%s,OU=Domain Controllers,%s" % (self.dcname, self.base_dn)
1911 self.site = "Default-First-Site-Name"
1912 self.rodcctx = DCJoinContext(server=host, creds=creds, lp=lp,
1913 site=self.site, netbios_name=self.rodcname,
1914 targetdir=None, domain=None)
1915 self.dcctx = DCJoinContext(server=host, creds=creds, lp=lp,
1916 site=self.site, netbios_name=self.dcname,
1917 targetdir=None, domain=None)
1918 self.ldb_admin.newuser(self.test_user, self.user_pass)
1919 self.ldb_user1 = self.get_ldb_connection(self.test_user, self.user_pass)
1920 self.user_sid1 = self.sd_utils.get_object_sid(self.get_user_dn(self.test_user))
1921 self.create_computer(self.computername, self.dcctx.dnsdomain)
1922 self.create_rodc(self.rodcctx)
1923 self.create_dc(self.dcctx)
1926 super(AclSPNTests, self).tearDown()
1927 self.rodcctx.cleanup_old_join()
1928 self.dcctx.cleanup_old_join()
1929 delete_force(self.ldb_admin, "cn=%s,cn=computers,%s" % (self.computername, self.base_dn))
1930 delete_force(self.ldb_admin, self.get_user_dn(self.test_user))
1934 def replace_spn(self, _ldb, dn, spn):
1935 print("Setting spn %s on %s" % (spn, dn))
1936 res = self.ldb_admin.search(dn, expression="(objectClass=*)",
1937 scope=SCOPE_BASE, attrs=["servicePrincipalName"])
1938 if "servicePrincipalName" in res[0].keys():
1939 flag = FLAG_MOD_REPLACE
1944 msg.dn = Dn(self.ldb_admin, dn)
1945 msg["servicePrincipalName"] = MessageElement(spn, flag,
1946 "servicePrincipalName")
1949 def create_computer(self, computername, domainname):
1950 dn = "CN=%s,CN=computers,%s" % (computername, self.base_dn)
1951 samaccountname = computername + "$"
1952 dnshostname = "%s.%s" % (computername, domainname)
1953 self.ldb_admin.add({
1955 "objectclass": "computer",
1956 "sAMAccountName": samaccountname,
1957 "userAccountControl": str(samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT),
1958 "dNSHostName": dnshostname})
1960 # same as for join_RODC, but do not set any SPNs
1961 def create_rodc(self, ctx):
1962 ctx.nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1963 ctx.full_nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1964 ctx.krbtgt_dn = "CN=krbtgt_%s,CN=Users,%s" % (ctx.myname, ctx.base_dn)
1966 ctx.never_reveal_sid = [ "<SID=%s-%s>" % (ctx.domsid, security.DOMAIN_RID_RODC_DENY),
1967 "<SID=%s>" % security.SID_BUILTIN_ADMINISTRATORS,
1968 "<SID=%s>" % security.SID_BUILTIN_SERVER_OPERATORS,
1969 "<SID=%s>" % security.SID_BUILTIN_BACKUP_OPERATORS,
1970 "<SID=%s>" % security.SID_BUILTIN_ACCOUNT_OPERATORS ]
1971 ctx.reveal_sid = "<SID=%s-%s>" % (ctx.domsid, security.DOMAIN_RID_RODC_ALLOW)
1973 mysid = ctx.get_mysid()
1974 admin_dn = "<SID=%s>" % mysid
1975 ctx.managedby = admin_dn
1977 ctx.userAccountControl = (samba.dsdb.UF_WORKSTATION_TRUST_ACCOUNT |
1978 samba.dsdb.UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION |
1979 samba.dsdb.UF_PARTIAL_SECRETS_ACCOUNT)
1981 ctx.connection_dn = "CN=RODC Connection (FRS),%s" % ctx.ntds_dn
1982 ctx.secure_channel_type = misc.SEC_CHAN_RODC
1984 ctx.replica_flags = (drsuapi.DRSUAPI_DRS_INIT_SYNC |
1985 drsuapi.DRSUAPI_DRS_PER_SYNC |
1986 drsuapi.DRSUAPI_DRS_GET_ANC |
1987 drsuapi.DRSUAPI_DRS_NEVER_SYNCED |
1988 drsuapi.DRSUAPI_DRS_SPECIAL_SECRET_PROCESSING)
1990 ctx.join_add_objects()
1992 def create_dc(self, ctx):
1993 ctx.nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1994 ctx.full_nc_list = [ ctx.base_dn, ctx.config_dn, ctx.schema_dn ]
1995 ctx.userAccountControl = samba.dsdb.UF_SERVER_TRUST_ACCOUNT | samba.dsdb.UF_TRUSTED_FOR_DELEGATION
1996 ctx.secure_channel_type = misc.SEC_CHAN_BDC
1997 ctx.replica_flags = (drsuapi.DRSUAPI_DRS_WRIT_REP |
1998 drsuapi.DRSUAPI_DRS_INIT_SYNC |
1999 drsuapi.DRSUAPI_DRS_PER_SYNC |
2000 drsuapi.DRSUAPI_DRS_FULL_SYNC_IN_PROGRESS |
2001 drsuapi.DRSUAPI_DRS_NEVER_SYNCED)
2003 ctx.join_add_objects()
2005 def dc_spn_test(self, ctx):
2006 netbiosdomain = self.dcctx.get_domain_name()
2008 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s/%s" % (ctx.myname, netbiosdomain))
2009 except LdbError as e39:
2011 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2013 mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1)
2014 self.sd_utils.dacl_add_ace(ctx.acct_dn, mod)
2015 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s/%s" % (ctx.myname, netbiosdomain))
2016 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s" % (ctx.myname))
2017 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s.%s/%s" %
2018 (ctx.myname, ctx.dnsdomain, netbiosdomain))
2019 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s/%s" % (ctx.myname, ctx.dnsdomain))
2020 self.replace_spn(self.ldb_user1, ctx.acct_dn, "HOST/%s.%s/%s" %
2021 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
2022 self.replace_spn(self.ldb_user1, ctx.acct_dn, "GC/%s.%s/%s" %
2023 (ctx.myname, ctx.dnsdomain, ctx.dnsforest))
2024 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s/%s" % (ctx.myname, netbiosdomain))
2025 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/%s" %
2026 (ctx.myname, ctx.dnsdomain, netbiosdomain))
2027 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s" % (ctx.myname))
2028 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s/%s" % (ctx.myname, ctx.dnsdomain))
2029 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/%s" %
2030 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
2031 self.replace_spn(self.ldb_user1, ctx.acct_dn, "DNS/%s/%s" % (ctx.myname, ctx.dnsdomain))
2032 self.replace_spn(self.ldb_user1, ctx.acct_dn, "RestrictedKrbHost/%s/%s" %
2033 (ctx.myname, ctx.dnsdomain))
2034 self.replace_spn(self.ldb_user1, ctx.acct_dn, "RestrictedKrbHost/%s" %
2036 self.replace_spn(self.ldb_user1, ctx.acct_dn, "Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/%s/%s" %
2037 (ctx.myname, ctx.dnsdomain))
2038 self.replace_spn(self.ldb_user1, ctx.acct_dn, "NtFrs-88f5d2bd-b646-11d2-a6d3-00c04fc9b232/%s/%s" %
2039 (ctx.myname, ctx.dnsdomain))
2040 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s._msdcs.%s" %
2041 (ctx.ntds_guid, ctx.dnsdomain))
2043 #the following spns do not match the restrictions and should fail
2045 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/ForestDnsZones.%s" %
2046 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
2047 except LdbError as e40:
2049 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2051 self.replace_spn(self.ldb_user1, ctx.acct_dn, "ldap/%s.%s/DomainDnsZones.%s" %
2052 (ctx.myname, ctx.dnsdomain, ctx.dnsdomain))
2053 except LdbError as e41:
2055 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2057 self.replace_spn(self.ldb_user1, ctx.acct_dn, "nosuchservice/%s/%s" % ("abcd", "abcd"))
2058 except LdbError as e42:
2060 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2062 self.replace_spn(self.ldb_user1, ctx.acct_dn, "GC/%s.%s/%s" %
2063 (ctx.myname, ctx.dnsdomain, netbiosdomain))
2064 except LdbError as e43:
2066 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2068 self.replace_spn(self.ldb_user1, ctx.acct_dn, "E3514235-4B06-11D1-AB04-00C04FC2DCD2/%s/%s" %
2069 (ctx.ntds_guid, ctx.dnsdomain))
2070 except LdbError as e44:
2072 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2074 def test_computer_spn(self):
2075 # with WP, any value can be set
2076 netbiosdomain = self.dcctx.get_domain_name()
2077 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s/%s" %
2078 (self.computername, netbiosdomain))
2079 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s" % (self.computername))
2080 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s.%s/%s" %
2081 (self.computername, self.dcctx.dnsdomain, netbiosdomain))
2082 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s/%s" %
2083 (self.computername, self.dcctx.dnsdomain))
2084 self.replace_spn(self.ldb_admin, self.computerdn, "HOST/%s.%s/%s" %
2085 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2086 self.replace_spn(self.ldb_admin, self.computerdn, "GC/%s.%s/%s" %
2087 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsforest))
2088 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s/%s" % (self.computername, netbiosdomain))
2089 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/ForestDnsZones.%s" %
2090 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2091 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/DomainDnsZones.%s" %
2092 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2093 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/%s" %
2094 (self.computername, self.dcctx.dnsdomain, netbiosdomain))
2095 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s" % (self.computername))
2096 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s/%s" %
2097 (self.computername, self.dcctx.dnsdomain))
2098 self.replace_spn(self.ldb_admin, self.computerdn, "ldap/%s.%s/%s" %
2099 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2100 self.replace_spn(self.ldb_admin, self.computerdn, "DNS/%s/%s" %
2101 (self.computername, self.dcctx.dnsdomain))
2102 self.replace_spn(self.ldb_admin, self.computerdn, "RestrictedKrbHost/%s/%s" %
2103 (self.computername, self.dcctx.dnsdomain))
2104 self.replace_spn(self.ldb_admin, self.computerdn, "RestrictedKrbHost/%s" %
2105 (self.computername))
2106 self.replace_spn(self.ldb_admin, self.computerdn, "Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/%s/%s" %
2107 (self.computername, self.dcctx.dnsdomain))
2108 self.replace_spn(self.ldb_admin, self.computerdn, "NtFrs-88f5d2bd-b646-11d2-a6d3-00c04fc9b232/%s/%s" %
2109 (self.computername, self.dcctx.dnsdomain))
2110 self.replace_spn(self.ldb_admin, self.computerdn, "nosuchservice/%s/%s" % ("abcd", "abcd"))
2112 #user has neither WP nor Validated-SPN, access denied expected
2114 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, netbiosdomain))
2115 except LdbError as e45:
2117 self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
2119 mod = "(OA;;SW;f3a64788-5306-11d1-a9c5-0000f80367c1;;%s)" % str(self.user_sid1)
2120 self.sd_utils.dacl_add_ace(self.computerdn, mod)
2121 #grant Validated-SPN and check which values are accepted
2122 #see 3.1.1.5.3.1.1.4 servicePrincipalName for reference
2124 # for regular computer objects we shouldalways get constraint violation
2126 # This does not pass against Windows, although it should according to docs
2127 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s" % (self.computername))
2128 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s" %
2129 (self.computername, self.dcctx.dnsdomain))
2132 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" % (self.computername, netbiosdomain))
2133 except LdbError as e46:
2135 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2137 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" %
2138 (self.computername, self.dcctx.dnsdomain, netbiosdomain))
2139 except LdbError as e47:
2141 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2143 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s/%s" %
2144 (self.computername, self.dcctx.dnsdomain))
2145 except LdbError as e48:
2147 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2149 self.replace_spn(self.ldb_user1, self.computerdn, "HOST/%s.%s/%s" %
2150 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2151 except LdbError as e49:
2153 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2155 self.replace_spn(self.ldb_user1, self.computerdn, "GC/%s.%s/%s" %
2156 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsforest))
2157 except LdbError as e50:
2159 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2161 self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s/%s" % (self.computername, netbiosdomain))
2162 except LdbError as e51:
2164 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2166 self.replace_spn(self.ldb_user1, self.computerdn, "ldap/%s.%s/ForestDnsZones.%s" %
2167 (self.computername, self.dcctx.dnsdomain, self.dcctx.dnsdomain))
2168 except LdbError as e52:
2170 self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
2172 def test_spn_rwdc(self):
2173 self.dc_spn_test(self.dcctx)
2175 def test_spn_rodc(self):
2176 self.dc_spn_test(self.rodcctx)
2179 # Important unit running information
2181 ldb = SamDB(ldaphost, credentials=creds, session_info=system_session(lp), lp=lp)
2183 TestProgram(module=__name__, opts=subunitopts)