1 # Unix SMB/CIFS implementation. Tests for dsdb
2 # Copyright (C) Matthieu Patou <mat@matws.net> 2010
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 """Tests for samba.dsdb."""
20 from samba
.credentials
import Credentials
21 from samba
.samdb
import SamDB
22 from samba
.auth
import system_session
23 from samba
.tests
import TestCase
24 from samba
.tests
import delete_force
25 from samba
.ndr
import ndr_unpack
, ndr_pack
26 from samba
.dcerpc
import drsblobs
, security
, misc
27 from samba
import dsdb
28 from samba
import werror
33 class DsdbTests(TestCase
):
36 super(DsdbTests
, self
).setUp()
37 self
.lp
= samba
.tests
.env_loadparm()
38 self
.creds
= Credentials()
39 self
.creds
.guess(self
.lp
)
40 self
.session
= system_session()
41 self
.samdb
= SamDB(session_info
=self
.session
,
42 credentials
=self
.creds
,
46 user_name
= "dsdb-user-" + str(uuid
.uuid4().hex[0:6])
47 user_pass
= samba
.generate_random_password(32, 32)
48 user_description
= "Test user for dsdb test"
50 base_dn
= self
.samdb
.domain_dn()
52 self
.account_dn
= "cn=" + user_name
+ ",cn=Users," + base_dn
53 self
.samdb
.newuser(username
=user_name
,
55 description
=user_description
)
57 self
.addCleanup(delete_force
, self
.samdb
, self
.account_dn
)
59 def test_get_oid_from_attrid(self
):
60 oid
= self
.samdb
.get_oid_from_attid(591614)
61 self
.assertEquals(oid
, "1.2.840.113556.1.4.1790")
63 def test_error_replpropertymetadata(self
):
64 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
66 attrs
=["replPropertyMetaData"])
67 repl
= ndr_unpack(drsblobs
.replPropertyMetaDataBlob
,
68 res
[0]["replPropertyMetaData"][0])
71 # Search for Description
73 old_version
= o
.version
74 o
.version
= o
.version
+ 1
75 replBlob
= ndr_pack(repl
)
78 msg
["replPropertyMetaData"] = ldb
.MessageElement(replBlob
, ldb
.FLAG_MOD_REPLACE
, "replPropertyMetaData")
79 self
.assertRaises(ldb
.LdbError
, self
.samdb
.modify
, msg
, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
81 def test_error_replpropertymetadata_nochange(self
):
82 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
84 attrs
=["replPropertyMetaData"])
85 repl
= ndr_unpack(drsblobs
.replPropertyMetaDataBlob
,
86 res
[0]["replPropertyMetaData"][0])
87 replBlob
= ndr_pack(repl
)
90 msg
["replPropertyMetaData"] = ldb
.MessageElement(replBlob
, ldb
.FLAG_MOD_REPLACE
, "replPropertyMetaData")
91 self
.assertRaises(ldb
.LdbError
, self
.samdb
.modify
, msg
, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
93 def test_error_replpropertymetadata_allow_sort(self
):
94 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
96 attrs
=["replPropertyMetaData"])
97 repl
= ndr_unpack(drsblobs
.replPropertyMetaDataBlob
,
98 res
[0]["replPropertyMetaData"][0])
99 replBlob
= ndr_pack(repl
)
102 msg
["replPropertyMetaData"] = ldb
.MessageElement(replBlob
, ldb
.FLAG_MOD_REPLACE
, "replPropertyMetaData")
103 self
.samdb
.modify(msg
, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0", "local_oid:1.3.6.1.4.1.7165.4.3.25:0"])
105 def test_twoatt_replpropertymetadata(self
):
106 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
107 base
=self
.account_dn
,
108 attrs
=["replPropertyMetaData", "uSNChanged"])
109 repl
= ndr_unpack(drsblobs
.replPropertyMetaDataBlob
,
110 res
[0]["replPropertyMetaData"][0])
113 # Search for Description
115 old_version
= o
.version
116 o
.version
= o
.version
+ 1
117 o
.local_usn
= int(str(res
[0]["uSNChanged"])) + 1
118 replBlob
= ndr_pack(repl
)
121 msg
["replPropertyMetaData"] = ldb
.MessageElement(replBlob
, ldb
.FLAG_MOD_REPLACE
, "replPropertyMetaData")
122 msg
["description"] = ldb
.MessageElement("new val", ldb
.FLAG_MOD_REPLACE
, "description")
123 self
.assertRaises(ldb
.LdbError
, self
.samdb
.modify
, msg
, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
125 def test_set_replpropertymetadata(self
):
126 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
127 base
=self
.account_dn
,
128 attrs
=["replPropertyMetaData", "uSNChanged"])
129 repl
= ndr_unpack(drsblobs
.replPropertyMetaDataBlob
,
130 res
[0]["replPropertyMetaData"][0])
133 # Search for Description
135 old_version
= o
.version
136 o
.version
= o
.version
+ 1
137 o
.local_usn
= int(str(res
[0]["uSNChanged"])) + 1
138 o
.originating_usn
= int(str(res
[0]["uSNChanged"])) + 1
139 replBlob
= ndr_pack(repl
)
142 msg
["replPropertyMetaData"] = ldb
.MessageElement(replBlob
, ldb
.FLAG_MOD_REPLACE
, "replPropertyMetaData")
143 self
.samdb
.modify(msg
, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
145 def test_ok_get_attribute_from_attid(self
):
146 self
.assertEquals(self
.samdb
.get_attribute_from_attid(13), "description")
148 def test_ko_get_attribute_from_attid(self
):
149 self
.assertEquals(self
.samdb
.get_attribute_from_attid(11979), None)
151 def test_get_attribute_replmetadata_version(self
):
152 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
153 base
=self
.account_dn
,
155 self
.assertEquals(len(res
), 1)
157 self
.assertEqual(self
.samdb
.get_attribute_replmetadata_version(dn
, "unicodePwd"), 2)
159 def test_set_attribute_replmetadata_version(self
):
160 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
161 base
=self
.account_dn
,
163 self
.assertEquals(len(res
), 1)
165 version
= self
.samdb
.get_attribute_replmetadata_version(dn
, "description")
166 self
.samdb
.set_attribute_replmetadata_version(dn
, "description", version
+ 2)
167 self
.assertEqual(self
.samdb
.get_attribute_replmetadata_version(dn
, "description"), version
+ 2)
169 def test_no_error_on_invalid_control(self
):
171 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
172 base
=self
.account_dn
,
173 attrs
=["replPropertyMetaData"],
174 controls
=["local_oid:%s:0"
175 % dsdb
.DSDB_CONTROL_INVALID_NOT_IMPLEMENTED
])
176 except ldb
.LdbError
as e
:
177 self
.fail("Should have not raised an exception")
179 def test_error_on_invalid_critical_control(self
):
181 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
182 base
=self
.account_dn
,
183 attrs
=["replPropertyMetaData"],
184 controls
=["local_oid:%s:1"
185 % dsdb
.DSDB_CONTROL_INVALID_NOT_IMPLEMENTED
])
186 except ldb
.LdbError
as e
:
187 (errno
, estr
) = e
.args
188 if errno
!= ldb
.ERR_UNSUPPORTED_CRITICAL_EXTENSION
:
189 self
.fail("Got %s should have got ERR_UNSUPPORTED_CRITICAL_EXTENSION"
192 # Allocate a unique RID for use in the objectSID tests.
194 def allocate_rid(self
):
195 self
.samdb
.transaction_start()
197 rid
= self
.samdb
.allocate_rid()
199 self
.samdb
.transaction_cancel()
201 self
.samdb
.transaction_commit()
204 # Ensure that duplicate objectSID's are permitted for foreign security
207 def test_duplicate_objectSIDs_allowed_on_foreign_security_principals(self
):
210 # We need to build a foreign security principal SID
211 # i.e a SID not in the current domain.
213 dom_sid
= self
.samdb
.get_domain_sid()
214 if str(dom_sid
).endswith("0"):
218 sid_str
= str(dom_sid
)[:-1] + c
+ "-1000"
219 sid
= ndr_pack(security
.dom_sid(sid_str
))
220 basedn
= self
.samdb
.get_default_basedn()
221 dn
= "CN=%s,CN=ForeignSecurityPrincipals,%s" % (sid_str
, basedn
)
224 # First without control
230 "objectClass": "foreignSecurityPrincipal"})
231 self
.fail("No exception should get ERR_OBJECT_CLASS_VIOLATION")
232 except ldb
.LdbError
as e
:
234 self
.assertEqual(code
, ldb
.ERR_OBJECT_CLASS_VIOLATION
, str(e
))
235 werr
= "%08X" % werror
.WERR_DS_MISSING_REQUIRED_ATT
236 self
.assertTrue(werr
in msg
, msg
)
241 "objectClass": "foreignSecurityPrincipal",
243 self
.fail("No exception should get ERR_UNWILLING_TO_PERFORM")
244 except ldb
.LdbError
as e
:
246 self
.assertEqual(code
, ldb
.ERR_UNWILLING_TO_PERFORM
, str(e
))
247 werr
= "%08X" % werror
.WERR_DS_ILLEGAL_MOD_OPERATION
248 self
.assertTrue(werr
in msg
, msg
)
251 # We need to use the provision control
252 # in order to add foreignSecurityPrincipal
256 controls
= ["provision:0"]
259 "objectClass": "foreignSecurityPrincipal"},
262 self
.samdb
.delete(dn
)
267 "objectClass": "foreignSecurityPrincipal"},
269 except ldb
.LdbError
as e
:
271 self
.fail("Got unexpected exception %d - %s "
275 self
.samdb
.delete(dn
)
277 def _test_foreignSecurityPrincipal(self
, obj_class
, fpo_attr
):
279 dom_sid
= self
.samdb
.get_domain_sid()
280 lsid_str
= str(dom_sid
) + "-4294967294"
281 bsid_str
= "S-1-5-32-4294967294"
282 fsid_str
= "S-1-5-4294967294"
283 basedn
= self
.samdb
.get_default_basedn()
285 dn_str
= "cn=%s,cn=Users,%s" % (cn
, basedn
)
286 dn
= ldb
.Dn(self
.samdb
, dn_str
)
288 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
290 expression
="(objectSid=%s)" % lsid_str
,
292 self
.assertEqual(len(res
), 0)
293 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
295 expression
="(objectSid=%s)" % bsid_str
,
297 self
.assertEqual(len(res
), 0)
298 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
300 expression
="(objectSid=%s)" % fsid_str
,
302 self
.assertEqual(len(res
), 0)
304 self
.addCleanup(delete_force
, self
.samdb
, dn_str
)
308 "objectClass": obj_class
})
312 msg
[fpo_attr
] = ldb
.MessageElement("<SID=%s>" % lsid_str
,
316 self
.samdb
.modify(msg
)
317 self
.fail("No exception should get LDB_ERR_UNWILLING_TO_PERFORM")
318 except ldb
.LdbError
as e
:
320 self
.assertEqual(code
, ldb
.ERR_UNWILLING_TO_PERFORM
, str(e
))
321 werr
= "%08X" % werror
.WERR_DS_INVALID_GROUP_TYPE
322 self
.assertTrue(werr
in msg
, msg
)
326 msg
[fpo_attr
] = ldb
.MessageElement("<SID=%s>" % bsid_str
,
330 self
.samdb
.modify(msg
)
331 self
.fail("No exception should get LDB_ERR_NO_SUCH_OBJECT")
332 except ldb
.LdbError
as e
:
334 self
.assertEqual(code
, ldb
.ERR_NO_SUCH_OBJECT
, str(e
))
335 werr
= "%08X" % werror
.WERR_NO_SUCH_MEMBER
336 self
.assertTrue(werr
in msg
, msg
)
340 msg
[fpo_attr
] = ldb
.MessageElement("<SID=%s>" % fsid_str
,
344 self
.samdb
.modify(msg
)
345 except ldb
.LdbError
as e
:
346 self
.fail("Should have not raised an exception")
348 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
350 expression
="(objectSid=%s)" % fsid_str
,
352 self
.assertEqual(len(res
), 1)
353 self
.samdb
.delete(res
[0].dn
)
354 self
.samdb
.delete(dn
)
355 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
357 expression
="(objectSid=%s)" % fsid_str
,
359 self
.assertEqual(len(res
), 0)
361 def test_foreignSecurityPrincipal_member(self
):
362 return self
._test
_foreignSecurityPrincipal
(
365 def test_foreignSecurityPrincipal_MembersForAzRole(self
):
366 return self
._test
_foreignSecurityPrincipal
(
367 "msDS-AzRole", "msDS-MembersForAzRole")
369 def test_foreignSecurityPrincipal_NeverRevealGroup(self
):
370 return self
._test
_foreignSecurityPrincipal
(
371 "computer", "msDS-NeverRevealGroup")
373 def test_foreignSecurityPrincipal_RevealOnDemandGroup(self
):
374 return self
._test
_foreignSecurityPrincipal
(
375 "computer", "msDS-RevealOnDemandGroup")
377 def _test_fail_foreignSecurityPrincipal(self
, obj_class
, fpo_attr
,
378 msg_exp
, lerr_exp
, werr_exp
,
379 allow_reference
=True):
381 dom_sid
= self
.samdb
.get_domain_sid()
382 lsid_str
= str(dom_sid
) + "-4294967294"
383 bsid_str
= "S-1-5-32-4294967294"
384 fsid_str
= "S-1-5-4294967294"
385 basedn
= self
.samdb
.get_default_basedn()
386 cn1
= "dsdb_test_fpo1"
387 dn1_str
= "cn=%s,cn=Users,%s" % (cn1
, basedn
)
388 dn1
= ldb
.Dn(self
.samdb
, dn1_str
)
389 cn2
= "dsdb_test_fpo2"
390 dn2_str
= "cn=%s,cn=Users,%s" % (cn2
, basedn
)
391 dn2
= ldb
.Dn(self
.samdb
, dn2_str
)
393 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
395 expression
="(objectSid=%s)" % lsid_str
,
397 self
.assertEqual(len(res
), 0)
398 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
400 expression
="(objectSid=%s)" % bsid_str
,
402 self
.assertEqual(len(res
), 0)
403 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
405 expression
="(objectSid=%s)" % fsid_str
,
407 self
.assertEqual(len(res
), 0)
409 self
.addCleanup(delete_force
, self
.samdb
, dn1_str
)
410 self
.addCleanup(delete_force
, self
.samdb
, dn2_str
)
414 "objectClass": obj_class
})
418 "objectClass": obj_class
})
422 msg
[fpo_attr
] = ldb
.MessageElement("<SID=%s>" % lsid_str
,
426 self
.samdb
.modify(msg
)
427 self
.fail("No exception should get %s" % msg_exp
)
428 except ldb
.LdbError
as e
:
430 self
.assertEqual(code
, lerr_exp
, str(e
))
431 werr
= "%08X" % werr_exp
432 self
.assertTrue(werr
in msg
, msg
)
436 msg
[fpo_attr
] = ldb
.MessageElement("<SID=%s>" % bsid_str
,
440 self
.samdb
.modify(msg
)
441 self
.fail("No exception should get %s" % msg_exp
)
442 except ldb
.LdbError
as e
:
444 self
.assertEqual(code
, lerr_exp
, str(e
))
445 werr
= "%08X" % werr_exp
446 self
.assertTrue(werr
in msg
, msg
)
450 msg
[fpo_attr
] = ldb
.MessageElement("<SID=%s>" % fsid_str
,
454 self
.samdb
.modify(msg
)
455 self
.fail("No exception should get %s" % msg
)
456 except ldb
.LdbError
as e
:
458 self
.assertEqual(code
, lerr_exp
, str(e
))
459 werr
= "%08X" % werr_exp
460 self
.assertTrue(werr
in msg
, msg
)
464 msg
[fpo_attr
] = ldb
.MessageElement("%s" % dn2
,
468 self
.samdb
.modify(msg
)
469 if not allow_reference
:
470 sel
.fail("No exception should get %s" % msg_exp
)
471 except ldb
.LdbError
as e
:
473 self
.fail("Should have not raised an exception: %s" % e
)
475 self
.assertEqual(code
, lerr_exp
, str(e
))
476 werr
= "%08X" % werr_exp
477 self
.assertTrue(werr
in msg
, msg
)
479 self
.samdb
.delete(dn2
)
480 self
.samdb
.delete(dn1
)
482 def test_foreignSecurityPrincipal_NonMembers(self
):
483 return self
._test
_fail
_foreignSecurityPrincipal
(
484 "group", "msDS-NonMembers",
485 "LDB_ERR_UNWILLING_TO_PERFORM/WERR_NOT_SUPPORTED",
486 ldb
.ERR_UNWILLING_TO_PERFORM
, werror
.WERR_NOT_SUPPORTED
,
487 allow_reference
=False)
489 def test_foreignSecurityPrincipal_HostServiceAccount(self
):
490 return self
._test
_fail
_foreignSecurityPrincipal
(
491 "computer", "msDS-HostServiceAccount",
492 "LDB_ERR_CONSTRAINT_VIOLATION/WERR_DS_NAME_REFERENCE_INVALID",
493 ldb
.ERR_CONSTRAINT_VIOLATION
,
494 werror
.WERR_DS_NAME_REFERENCE_INVALID
)
496 def test_foreignSecurityPrincipal_manager(self
):
497 return self
._test
_fail
_foreignSecurityPrincipal
(
499 "LDB_ERR_CONSTRAINT_VIOLATION/WERR_DS_NAME_REFERENCE_INVALID",
500 ldb
.ERR_CONSTRAINT_VIOLATION
,
501 werror
.WERR_DS_NAME_REFERENCE_INVALID
)
504 # Duplicate objectSID's should not be permitted for sids in the local
505 # domain. The test sequence is add an object, delete it, then attempt to
506 # re-add it, this should fail with a constraint violation
508 def test_duplicate_objectSIDs_not_allowed_on_local_objects(self
):
510 dom_sid
= self
.samdb
.get_domain_sid()
511 rid
= self
.allocate_rid()
512 sid_str
= str(dom_sid
) + "-" + rid
513 sid
= ndr_pack(security
.dom_sid(sid_str
))
514 basedn
= self
.samdb
.get_default_basedn()
516 dn
= "cn=%s,cn=Users,%s" % (cn
, basedn
)
520 "objectClass": "user",
522 self
.samdb
.delete(dn
)
527 "objectClass": "user",
529 self
.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
530 except ldb
.LdbError
as e
:
532 if code
!= ldb
.ERR_CONSTRAINT_VIOLATION
:
533 self
.fail("Got %d - %s should have got "
534 "LDB_ERR_CONSTRAINT_VIOLATION"
537 def test_linked_vs_non_linked_reference(self
):
538 basedn
= self
.samdb
.get_default_basedn()
539 kept_dn_str
= "cn=reference_kept,cn=Users,%s" % (basedn
)
540 removed_dn_str
= "cn=reference_removed,cn=Users,%s" % (basedn
)
541 dom_sid
= self
.samdb
.get_domain_sid()
542 none_sid_str
= str(dom_sid
) + "-4294967294"
543 none_guid_str
= "afafafaf-fafa-afaf-fafa-afafafafafaf"
545 self
.addCleanup(delete_force
, self
.samdb
, kept_dn_str
)
546 self
.addCleanup(delete_force
, self
.samdb
, removed_dn_str
)
550 "objectClass": "user"})
551 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
553 attrs
=["objectGUID", "objectSID"])
554 self
.assertEqual(len(res
), 1)
555 kept_guid
= ndr_unpack(misc
.GUID
, res
[0]["objectGUID"][0])
556 kept_sid
= ndr_unpack(security
.dom_sid
, res
[0]["objectSid"][0])
560 "dn": removed_dn_str
,
561 "objectClass": "user"})
562 res
= self
.samdb
.search(scope
=ldb
.SCOPE_SUBTREE
,
564 attrs
=["objectGUID", "objectSID"])
565 self
.assertEqual(len(res
), 1)
566 removed_guid
= ndr_unpack(misc
.GUID
, res
[0]["objectGUID"][0])
567 removed_sid
= ndr_unpack(security
.dom_sid
, res
[0]["objectSid"][0])
568 self
.samdb
.delete(removed_dn_str
)
571 # First try the linked attribute 'manager'
577 msg
["manager"] = ldb
.MessageElement("<SID=%s>" % removed_sid
,
581 self
.samdb
.modify(msg
)
582 self
.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
583 except ldb
.LdbError
as e
:
585 self
.assertEqual(code
, ldb
.ERR_CONSTRAINT_VIOLATION
, str(e
))
586 werr
= "%08X" % werror
.WERR_DS_NAME_REFERENCE_INVALID
587 self
.assertTrue(werr
in msg
, msg
)
591 msg
["manager"] = ldb
.MessageElement("<GUID=%s>" % removed_guid
,
595 self
.samdb
.modify(msg
)
596 self
.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
597 except ldb
.LdbError
as e
:
599 self
.assertEqual(code
, ldb
.ERR_CONSTRAINT_VIOLATION
, str(e
))
600 werr
= "%08X" % werror
.WERR_DS_NAME_REFERENCE_INVALID
601 self
.assertTrue(werr
in msg
, msg
)
604 # Try the non-linked attribute 'assistant'
605 # by GUID and SID, which should work.
609 msg
["assistant"] = ldb
.MessageElement("<SID=%s>" % removed_sid
,
612 self
.samdb
.modify(msg
)
615 msg
["assistant"] = ldb
.MessageElement("<SID=%s>" % removed_sid
,
618 self
.samdb
.modify(msg
)
622 msg
["assistant"] = ldb
.MessageElement("<GUID=%s>" % removed_guid
,
625 self
.samdb
.modify(msg
)
628 msg
["assistant"] = ldb
.MessageElement("<GUID=%s>" % removed_guid
,
631 self
.samdb
.modify(msg
)
634 # Finally ry the non-linked attribute 'assistant'
635 # but with non existing GUID, SID, DN
639 msg
["assistant"] = ldb
.MessageElement("CN=NoneNone,%s" % (basedn
),
643 self
.samdb
.modify(msg
)
644 self
.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
645 except ldb
.LdbError
as e
:
647 self
.assertEqual(code
, ldb
.ERR_CONSTRAINT_VIOLATION
, str(e
))
648 werr
= "%08X" % werror
.WERR_DS_NAME_REFERENCE_INVALID
649 self
.assertTrue(werr
in msg
, msg
)
653 msg
["assistant"] = ldb
.MessageElement("<SID=%s>" % none_sid_str
,
657 self
.samdb
.modify(msg
)
658 self
.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
659 except ldb
.LdbError
as e
:
661 self
.assertEqual(code
, ldb
.ERR_CONSTRAINT_VIOLATION
, str(e
))
662 werr
= "%08X" % werror
.WERR_DS_NAME_REFERENCE_INVALID
663 self
.assertTrue(werr
in msg
, msg
)
667 msg
["assistant"] = ldb
.MessageElement("<GUID=%s>" % none_guid_str
,
671 self
.samdb
.modify(msg
)
672 self
.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
673 except ldb
.LdbError
as e
:
675 self
.assertEqual(code
, ldb
.ERR_CONSTRAINT_VIOLATION
, str(e
))
676 werr
= "%08X" % werror
.WERR_DS_NAME_REFERENCE_INVALID
677 self
.assertTrue(werr
in msg
, msg
)
679 self
.samdb
.delete(kept_dn
)
681 def test_normalize_dn_in_domain_full(self
):
682 domain_dn
= self
.samdb
.domain_dn()
684 part_dn
= ldb
.Dn(self
.samdb
, "CN=Users")
687 full_dn
.add_base(domain_dn
)
689 full_str
= str(full_dn
)
692 self
.assertEqual(full_dn
,
693 self
.samdb
.normalize_dn_in_domain(full_str
))
695 def test_normalize_dn_in_domain_part(self
):
696 domain_dn
= self
.samdb
.domain_dn()
698 part_str
= "CN=Users"
700 full_dn
= ldb
.Dn(self
.samdb
, part_str
)
701 full_dn
.add_base(domain_dn
)
703 # That is, the domain DN appended
704 self
.assertEqual(full_dn
,
705 self
.samdb
.normalize_dn_in_domain(part_str
))
707 def test_normalize_dn_in_domain_full_dn(self
):
708 domain_dn
= self
.samdb
.domain_dn()
710 part_dn
= ldb
.Dn(self
.samdb
, "CN=Users")
713 full_dn
.add_base(domain_dn
)
716 self
.assertEqual(full_dn
,
717 self
.samdb
.normalize_dn_in_domain(full_dn
))
719 def test_normalize_dn_in_domain_part_dn(self
):
720 domain_dn
= self
.samdb
.domain_dn()
722 part_dn
= ldb
.Dn(self
.samdb
, "CN=Users")
724 # That is, the domain DN appended
725 self
.assertEqual(ldb
.Dn(self
.samdb
,
726 str(part_dn
) + "," + str(domain_dn
)),
727 self
.samdb
.normalize_dn_in_domain(part_dn
))