2 # -*- coding: utf-8 -*-
4 # Unix SMB/CIFS implementation.
5 # Copyright (C) Catalyst.Net Ltd. 2017
6 # Copyright (C) Andrew Bartlett <abartlet@samba.org> 2019
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 from samba
import sd_utils
25 from ldb
import LdbError
27 class ReplAclTestCase(drs_base
.DrsBaseTestCase
):
30 super(ReplAclTestCase
, self
).setUp()
31 self
.mod
= "(A;CIOI;GA;;;SY)"
32 self
.mod_becomes
= "(A;OICIIO;GA;;;SY)"
33 self
.mod_inherits_as
= "(A;OICIIOID;GA;;;SY)"
35 self
.sd_utils_dc1
= sd_utils
.SDUtils(self
.ldb_dc1
)
36 self
.sd_utils_dc2
= sd_utils
.SDUtils(self
.ldb_dc2
)
38 self
.ou
= samba
.tests
.create_test_ou(self
.ldb_dc1
,
41 # disable replication for the tests so we can control at what point
42 # the DCs try to replicate
43 self
._disable
_all
_repl
(self
.dnsname_dc1
)
44 self
._disable
_all
_repl
(self
.dnsname_dc2
)
46 # make sure DCs are synchronized before the test
47 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True)
48 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True)
51 self
.ldb_dc1
.delete(self
.ou
, ["tree_delete:1"])
53 # re-enable replication
54 self
._enable
_all
_repl
(self
.dnsname_dc1
)
55 self
._enable
_all
_repl
(self
.dnsname_dc2
)
57 super(ReplAclTestCase
, self
).tearDown()
59 def test_acl_inheirt_new_object_1_pass(self
):
60 # Set the inherited ACL on the parent OU
61 self
.sd_utils_dc1
.dacl_add_ace(self
.ou
, self
.mod
)
63 # Assert ACL set stuck as expected
64 self
.assertIn(self
.mod_becomes
,
65 self
.sd_utils_dc1
.get_sd_as_sddl(self
.ou
))
68 dn
= ldb
.Dn(self
.ldb_dc1
, "OU=l2,%s" % self
.ou
)
69 self
.ldb_dc1
.add({"dn": dn
, "objectclass": "organizationalUnit"})
71 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
72 fromDC
=self
.dnsname_dc1
,
75 # Assert ACL replicated as expected
76 self
.assertIn(self
.mod_becomes
,
77 self
.sd_utils_dc2
.get_sd_as_sddl(self
.ou
))
79 # Confirm inherited ACLs are identical and were inherited
81 self
.assertIn(self
.mod_inherits_as
,
82 self
.sd_utils_dc1
.get_sd_as_sddl(dn
))
83 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(dn
),
84 self
.sd_utils_dc2
.get_sd_as_sddl(dn
))
86 def test_acl_inheirt_new_object(self
):
87 # Set the inherited ACL on the parent OU
88 self
.sd_utils_dc1
.dacl_add_ace(self
.ou
, self
.mod
)
90 # Assert ACL set stuck as expected
91 self
.assertIn(self
.mod_becomes
,
92 self
.sd_utils_dc1
.get_sd_as_sddl(self
.ou
))
96 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
97 fromDC
=self
.dnsname_dc1
,
101 dn
= ldb
.Dn(self
.ldb_dc1
, "OU=l2,%s" % self
.ou
)
102 self
.ldb_dc1
.add({"dn": dn
, "objectclass": "organizationalUnit"})
104 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
105 fromDC
=self
.dnsname_dc1
,
108 # Assert ACL replicated as expected
109 self
.assertIn(self
.mod_becomes
,
110 self
.sd_utils_dc2
.get_sd_as_sddl(self
.ou
))
112 # Confirm inherited ACLs are identical and were inherited
114 self
.assertIn(self
.mod_inherits_as
,
115 self
.sd_utils_dc1
.get_sd_as_sddl(dn
))
116 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(dn
),
117 self
.sd_utils_dc2
.get_sd_as_sddl(dn
))
119 def test_acl_inherit_existing_object(self
):
121 dn
= ldb
.Dn(self
.ldb_dc1
, "OU=l2,%s" % self
.ou
)
122 self
.ldb_dc1
.add({"dn": dn
, "objectclass": "organizationalUnit"})
125 self
.ldb_dc2
.search(scope
=ldb
.SCOPE_BASE
,
129 except LdbError
as err
:
131 self
.assertEqual(enum
, ldb
.ERR_NO_SUCH_OBJECT
)
133 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
134 fromDC
=self
.dnsname_dc1
,
137 # Confirm it is now replicated
138 self
.ldb_dc2
.search(scope
=ldb
.SCOPE_BASE
,
142 # Set the inherited ACL on the parent OU
143 self
.sd_utils_dc1
.dacl_add_ace(self
.ou
, self
.mod
)
145 # Assert ACL set stuck as expected
146 self
.assertIn(self
.mod_becomes
,
147 self
.sd_utils_dc1
.get_sd_as_sddl(self
.ou
))
151 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
152 fromDC
=self
.dnsname_dc1
,
155 # Confirm inherited ACLs are identical and were inherited
157 # Assert ACL replicated as expected
158 self
.assertIn(self
.mod_becomes
,
159 self
.sd_utils_dc2
.get_sd_as_sddl(self
.ou
))
161 self
.assertIn(self
.mod_inherits_as
,
162 self
.sd_utils_dc1
.get_sd_as_sddl(dn
))
163 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(dn
),
164 self
.sd_utils_dc2
.get_sd_as_sddl(dn
))
166 def test_acl_inheirt_existing_object_1_pass(self
):
168 dn
= ldb
.Dn(self
.ldb_dc1
, "OU=l2,%s" % self
.ou
)
169 self
.ldb_dc1
.add({"dn": dn
, "objectclass": "organizationalUnit"})
172 self
.ldb_dc2
.search(scope
=ldb
.SCOPE_BASE
,
176 except LdbError
as err
:
178 self
.assertEqual(enum
, ldb
.ERR_NO_SUCH_OBJECT
)
180 # Set the inherited ACL on the parent OU
181 self
.sd_utils_dc1
.dacl_add_ace(self
.ou
, self
.mod
)
183 # Assert ACL set as expected
184 self
.assertIn(self
.mod_becomes
,
185 self
.sd_utils_dc1
.get_sd_as_sddl(self
.ou
))
189 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
190 fromDC
=self
.dnsname_dc1
,
193 # Assert ACL replicated as expected
194 self
.assertIn(self
.mod_becomes
,
195 self
.sd_utils_dc2
.get_sd_as_sddl(self
.ou
))
197 # Confirm inherited ACLs are identical and were inherited
199 self
.assertIn(self
.mod_inherits_as
,
200 self
.sd_utils_dc1
.get_sd_as_sddl(dn
))
201 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(dn
),
202 self
.sd_utils_dc2
.get_sd_as_sddl(dn
))
204 def test_acl_inheirt_renamed_object(self
):
206 new_ou
= samba
.tests
.create_test_ou(self
.ldb_dc1
,
209 sub_ou_dn
= ldb
.Dn(self
.ldb_dc1
, "OU=l2,%s" % self
.ou
)
212 self
.ldb_dc2
.search(scope
=ldb
.SCOPE_BASE
,
216 except LdbError
as err
:
218 self
.assertEqual(enum
, ldb
.ERR_NO_SUCH_OBJECT
)
220 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
221 fromDC
=self
.dnsname_dc1
,
224 # Confirm it is now replicated
225 self
.ldb_dc2
.search(scope
=ldb
.SCOPE_BASE
,
229 # Set the inherited ACL on the parent OU on DC1
230 self
.sd_utils_dc1
.dacl_add_ace(self
.ou
, self
.mod
)
232 # Assert ACL set as expected
233 self
.assertIn(self
.mod_becomes
,
234 self
.sd_utils_dc1
.get_sd_as_sddl(self
.ou
))
238 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
239 fromDC
=self
.dnsname_dc1
,
242 # Assert ACL replicated as expected
243 self
.assertIn(self
.mod_becomes
,
244 self
.sd_utils_dc2
.get_sd_as_sddl(self
.ou
))
246 # Rename to under self.ou
248 self
.ldb_dc1
.rename(new_ou
, sub_ou_dn
)
252 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
253 fromDC
=self
.dnsname_dc1
,
256 # Confirm inherited ACLs are identical and were inherited
257 self
.assertIn(self
.mod_inherits_as
,
258 self
.sd_utils_dc1
.get_sd_as_sddl(sub_ou_dn
))
259 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(sub_ou_dn
),
260 self
.sd_utils_dc2
.get_sd_as_sddl(sub_ou_dn
))
263 def test_acl_inheirt_renamed_child_object(self
):
265 new_ou
= samba
.tests
.create_test_ou(self
.ldb_dc1
,
268 # Here is where the new OU will end up at the end.
269 sub2_ou_dn_final
= ldb
.Dn(self
.ldb_dc1
, "OU=l2,%s" % self
.ou
)
271 sub3_ou_dn
= ldb
.Dn(self
.ldb_dc1
, "OU=l3,%s" % new_ou
)
272 sub3_ou_dn_final
= ldb
.Dn(self
.ldb_dc1
, "OU=l3,%s" % sub2_ou_dn_final
)
274 self
.ldb_dc1
.add({"dn": sub3_ou_dn
,
275 "objectclass": "organizationalUnit"})
277 sub4_ou_dn
= ldb
.Dn(self
.ldb_dc1
, "OU=l4,%s" % sub3_ou_dn
)
278 sub4_ou_dn_final
= ldb
.Dn(self
.ldb_dc1
, "OU=l4,%s" % sub3_ou_dn_final
)
280 self
.ldb_dc1
.add({"dn": sub4_ou_dn
,
281 "objectclass": "organizationalUnit"})
284 self
.ldb_dc2
.search(scope
=ldb
.SCOPE_BASE
,
288 except LdbError
as err
:
290 self
.assertEqual(enum
, ldb
.ERR_NO_SUCH_OBJECT
)
292 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
293 fromDC
=self
.dnsname_dc1
,
296 # Confirm it is now replicated
297 self
.ldb_dc2
.search(scope
=ldb
.SCOPE_BASE
,
302 # Given a tree new_ou -> l3 -> l4
305 # Set the inherited ACL on the grandchild OU (l3) on DC1
306 self
.sd_utils_dc1
.dacl_add_ace(sub3_ou_dn
, self
.mod
)
308 # Assert ACL set stuck as expected
309 self
.assertIn(self
.mod_becomes
,
310 self
.sd_utils_dc1
.get_sd_as_sddl(sub3_ou_dn
))
312 # Rename new_ou (l2) to under self.ou (this must happen second). If the
313 # inheritance between l3 and l4 is name-based, this could
316 # The tree is now self.ou -> l2 -> l3 -> l4
318 self
.ldb_dc1
.rename(new_ou
, sub2_ou_dn_final
)
320 # Assert ACL set remained as expected
321 self
.assertIn(self
.mod_becomes
,
322 self
.sd_utils_dc1
.get_sd_as_sddl(sub3_ou_dn_final
))
326 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
327 fromDC
=self
.dnsname_dc1
,
330 # Confirm set ACLs (on l3 ) are identical and were inherited
331 self
.assertIn(self
.mod_becomes
,
332 self
.sd_utils_dc2
.get_sd_as_sddl(sub3_ou_dn_final
))
333 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(sub3_ou_dn_final
),
334 self
.sd_utils_dc2
.get_sd_as_sddl(sub3_ou_dn_final
))
336 # Confirm inherited ACLs (from l3 to l4) are identical
338 self
.assertIn(self
.mod_inherits_as
,
339 self
.sd_utils_dc1
.get_sd_as_sddl(sub4_ou_dn_final
))
340 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(sub4_ou_dn_final
),
341 self
.sd_utils_dc2
.get_sd_as_sddl(sub4_ou_dn_final
))
344 def test_acl_inheirt_renamed_object_in_conflict(self
):
345 # Make a new object to be renamed under self.ou
346 new_ou
= samba
.tests
.create_test_ou(self
.ldb_dc1
,
349 # Make a new OU under self.ou (on DC2)
350 sub_ou_dn
= ldb
.Dn(self
.ldb_dc2
, "OU=l2,%s" % self
.ou
)
351 self
.ldb_dc2
.add({"dn": sub_ou_dn
,
352 "objectclass": "organizationalUnit"})
354 # Set the inherited ACL on the parent OU
355 self
.sd_utils_dc1
.dacl_add_ace(self
.ou
, self
.mod
)
357 # Assert ACL set stuck as expected
358 self
.assertIn(self
.mod_becomes
,
359 self
.sd_utils_dc1
.get_sd_as_sddl(self
.ou
))
363 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
364 fromDC
=self
.dnsname_dc1
,
367 # Rename to under self.ou
368 self
.ldb_dc1
.rename(new_ou
, sub_ou_dn
)
369 self
.assertIn(self
.mod_inherits_as
,
370 self
.sd_utils_dc1
.get_sd_as_sddl(sub_ou_dn
))
372 # Replicate to DC2 (will cause a conflict, DC1 to win, version
373 # is higher since named twice)
375 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
,
376 fromDC
=self
.dnsname_dc1
,
379 children
= self
.ldb_dc2
.search(scope
=ldb
.SCOPE_ONELEVEL
,
382 for child
in children
:
383 self
.assertIn(self
.mod_inherits_as
,
384 self
.sd_utils_dc2
.get_sd_as_sddl(child
.dn
))
385 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(sub_ou_dn
),
386 self
.sd_utils_dc2
.get_sd_as_sddl(child
.dn
))
389 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
,
390 fromDC
=self
.dnsname_dc2
,
393 self
.assertIn(self
.mod_inherits_as
,
394 self
.sd_utils_dc1
.get_sd_as_sddl(sub_ou_dn
))
396 for child
in children
:
397 self
.assertIn(self
.mod_inherits_as
,
398 self
.sd_utils_dc1
.get_sd_as_sddl(child
.dn
))
399 self
.assertEqual(self
.sd_utils_dc1
.get_sd_as_sddl(child
.dn
),
400 self
.sd_utils_dc2
.get_sd_as_sddl(child
.dn
))