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
34 class DsdbTests(TestCase):
37 super(DsdbTests, self).setUp()
38 self.lp = samba.tests.env_loadparm()
39 self.creds = Credentials()
40 self.creds.guess(self.lp)
41 self.session = system_session()
42 self.samdb = SamDB(session_info=self.session,
43 credentials=self.creds,
47 user_name = "dsdb-user-" + str(uuid.uuid4().hex[0:6])
48 user_pass = samba.generate_random_password(32, 32)
49 user_description = "Test user for dsdb test"
51 base_dn = self.samdb.domain_dn()
53 self.account_dn = "cn=" + user_name + ",cn=Users," + base_dn
54 self.samdb.newuser(username=user_name,
56 description=user_description)
58 self.addCleanup(delete_force, self.samdb, self.account_dn)
60 def test_get_oid_from_attrid(self):
61 oid = self.samdb.get_oid_from_attid(591614)
62 self.assertEquals(oid, "1.2.840.113556.1.4.1790")
64 def test_error_replpropertymetadata(self):
65 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
67 attrs=["replPropertyMetaData"])
68 repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
69 res[0]["replPropertyMetaData"][0])
72 # Search for Description
74 old_version = o.version
75 o.version = o.version + 1
76 replBlob = ndr_pack(repl)
79 msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData")
80 self.assertRaises(ldb.LdbError, self.samdb.modify, msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
82 def test_error_replpropertymetadata_nochange(self):
83 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
85 attrs=["replPropertyMetaData"])
86 repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
87 res[0]["replPropertyMetaData"][0])
88 replBlob = ndr_pack(repl)
91 msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData")
92 self.assertRaises(ldb.LdbError, self.samdb.modify, msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
94 def test_error_replpropertymetadata_allow_sort(self):
95 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
97 attrs=["replPropertyMetaData"])
98 repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
99 res[0]["replPropertyMetaData"][0])
100 replBlob = ndr_pack(repl)
103 msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData")
104 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"])
106 def test_twoatt_replpropertymetadata(self):
107 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
108 base=self.account_dn,
109 attrs=["replPropertyMetaData", "uSNChanged"])
110 repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
111 res[0]["replPropertyMetaData"][0])
114 # Search for Description
116 old_version = o.version
117 o.version = o.version + 1
118 o.local_usn = int(str(res[0]["uSNChanged"])) + 1
119 replBlob = ndr_pack(repl)
122 msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData")
123 msg["description"] = ldb.MessageElement("new val", ldb.FLAG_MOD_REPLACE, "description")
124 self.assertRaises(ldb.LdbError, self.samdb.modify, msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
126 def test_set_replpropertymetadata(self):
127 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
128 base=self.account_dn,
129 attrs=["replPropertyMetaData", "uSNChanged"])
130 repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob,
131 res[0]["replPropertyMetaData"][0])
134 # Search for Description
136 old_version = o.version
137 o.version = o.version + 1
138 o.local_usn = int(str(res[0]["uSNChanged"])) + 1
139 o.originating_usn = int(str(res[0]["uSNChanged"])) + 1
140 replBlob = ndr_pack(repl)
143 msg["replPropertyMetaData"] = ldb.MessageElement(replBlob, ldb.FLAG_MOD_REPLACE, "replPropertyMetaData")
144 self.samdb.modify(msg, ["local_oid:1.3.6.1.4.1.7165.4.3.14:0"])
146 def test_ok_get_attribute_from_attid(self):
147 self.assertEquals(self.samdb.get_attribute_from_attid(13), "description")
149 def test_ko_get_attribute_from_attid(self):
150 self.assertEquals(self.samdb.get_attribute_from_attid(11979), None)
152 def test_get_attribute_replmetadata_version(self):
153 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
154 base=self.account_dn,
156 self.assertEquals(len(res), 1)
158 self.assertEqual(self.samdb.get_attribute_replmetadata_version(dn, "unicodePwd"), 2)
160 def test_set_attribute_replmetadata_version(self):
161 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
162 base=self.account_dn,
164 self.assertEquals(len(res), 1)
166 version = self.samdb.get_attribute_replmetadata_version(dn, "description")
167 self.samdb.set_attribute_replmetadata_version(dn, "description", version + 2)
168 self.assertEqual(self.samdb.get_attribute_replmetadata_version(dn, "description"), version + 2)
170 def test_no_error_on_invalid_control(self):
172 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
173 base=self.account_dn,
174 attrs=["replPropertyMetaData"],
175 controls=["local_oid:%s:0"
176 % dsdb.DSDB_CONTROL_INVALID_NOT_IMPLEMENTED])
177 except ldb.LdbError as e:
178 self.fail("Should have not raised an exception")
180 def test_error_on_invalid_critical_control(self):
182 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
183 base=self.account_dn,
184 attrs=["replPropertyMetaData"],
185 controls=["local_oid:%s:1"
186 % dsdb.DSDB_CONTROL_INVALID_NOT_IMPLEMENTED])
187 except ldb.LdbError as e:
188 (errno, estr) = e.args
189 if errno != ldb.ERR_UNSUPPORTED_CRITICAL_EXTENSION:
190 self.fail("Got %s should have got ERR_UNSUPPORTED_CRITICAL_EXTENSION"
193 # Allocate a unique RID for use in the objectSID tests.
195 def allocate_rid(self):
196 self.samdb.transaction_start()
198 rid = self.samdb.allocate_rid()
200 self.samdb.transaction_cancel()
202 self.samdb.transaction_commit()
205 # Ensure that duplicate objectSID's are permitted for foreign security
208 def test_duplicate_objectSIDs_allowed_on_foreign_security_principals(self):
211 # We need to build a foreign security principal SID
212 # i.e a SID not in the current domain.
214 dom_sid = self.samdb.get_domain_sid()
215 if str(dom_sid).endswith("0"):
219 sid_str = str(dom_sid)[:-1] + c + "-1000"
220 sid = ndr_pack(security.dom_sid(sid_str))
221 basedn = self.samdb.get_default_basedn()
222 dn = "CN=%s,CN=ForeignSecurityPrincipals,%s" % (sid_str, basedn)
225 # First without control
231 "objectClass": "foreignSecurityPrincipal"})
232 self.fail("No exception should get ERR_OBJECT_CLASS_VIOLATION")
233 except ldb.LdbError as e:
235 self.assertEqual(code, ldb.ERR_OBJECT_CLASS_VIOLATION, str(e))
236 werr = "%08X" % werror.WERR_DS_MISSING_REQUIRED_ATT
237 self.assertTrue(werr in msg, msg)
242 "objectClass": "foreignSecurityPrincipal",
244 self.fail("No exception should get ERR_UNWILLING_TO_PERFORM")
245 except ldb.LdbError as e:
247 self.assertEqual(code, ldb.ERR_UNWILLING_TO_PERFORM, str(e))
248 werr = "%08X" % werror.WERR_DS_ILLEGAL_MOD_OPERATION
249 self.assertTrue(werr in msg, msg)
252 # We need to use the provision control
253 # in order to add foreignSecurityPrincipal
257 controls = ["provision:0"]
260 "objectClass": "foreignSecurityPrincipal"},
263 self.samdb.delete(dn)
268 "objectClass": "foreignSecurityPrincipal"},
270 except ldb.LdbError as e:
272 self.fail("Got unexpected exception %d - %s "
276 self.samdb.delete(dn)
278 def _test_foreignSecurityPrincipal(self, obj_class, fpo_attr):
280 dom_sid = self.samdb.get_domain_sid()
281 lsid_str = str(dom_sid) + "-4294967294"
282 bsid_str = "S-1-5-32-4294967294"
283 fsid_str = "S-1-5-4294967294"
284 basedn = self.samdb.get_default_basedn()
286 dn_str = "cn=%s,cn=Users,%s" % (cn, basedn)
287 dn = ldb.Dn(self.samdb, dn_str)
289 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
291 expression="(objectSid=%s)" % lsid_str,
293 self.assertEqual(len(res), 0)
294 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
296 expression="(objectSid=%s)" % bsid_str,
298 self.assertEqual(len(res), 0)
299 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
301 expression="(objectSid=%s)" % fsid_str,
303 self.assertEqual(len(res), 0)
305 self.addCleanup(delete_force, self.samdb, dn_str)
309 "objectClass": obj_class})
313 msg[fpo_attr] = ldb.MessageElement("<SID=%s>" % lsid_str,
317 self.samdb.modify(msg)
318 self.fail("No exception should get LDB_ERR_UNWILLING_TO_PERFORM")
319 except ldb.LdbError as e:
321 self.assertEqual(code, ldb.ERR_UNWILLING_TO_PERFORM, str(e))
322 werr = "%08X" % werror.WERR_DS_INVALID_GROUP_TYPE
323 self.assertTrue(werr in msg, msg)
327 msg[fpo_attr] = ldb.MessageElement("<SID=%s>" % bsid_str,
331 self.samdb.modify(msg)
332 self.fail("No exception should get LDB_ERR_NO_SUCH_OBJECT")
333 except ldb.LdbError as e:
335 self.assertEqual(code, ldb.ERR_NO_SUCH_OBJECT, str(e))
336 werr = "%08X" % werror.WERR_NO_SUCH_MEMBER
337 self.assertTrue(werr in msg, msg)
341 msg[fpo_attr] = ldb.MessageElement("<SID=%s>" % fsid_str,
345 self.samdb.modify(msg)
346 except ldb.LdbError as e:
347 self.fail("Should have not raised an exception")
349 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
351 expression="(objectSid=%s)" % fsid_str,
353 self.assertEqual(len(res), 1)
354 self.samdb.delete(res[0].dn)
355 self.samdb.delete(dn)
356 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
358 expression="(objectSid=%s)" % fsid_str,
360 self.assertEqual(len(res), 0)
362 def test_foreignSecurityPrincipal_member(self):
363 return self._test_foreignSecurityPrincipal(
366 def test_foreignSecurityPrincipal_MembersForAzRole(self):
367 return self._test_foreignSecurityPrincipal(
368 "msDS-AzRole", "msDS-MembersForAzRole")
370 def test_foreignSecurityPrincipal_NeverRevealGroup(self):
371 return self._test_foreignSecurityPrincipal(
372 "computer", "msDS-NeverRevealGroup")
374 def test_foreignSecurityPrincipal_RevealOnDemandGroup(self):
375 return self._test_foreignSecurityPrincipal(
376 "computer", "msDS-RevealOnDemandGroup")
378 def _test_fail_foreignSecurityPrincipal(self, obj_class, fpo_attr,
379 msg_exp, lerr_exp, werr_exp,
380 allow_reference=True):
382 dom_sid = self.samdb.get_domain_sid()
383 lsid_str = str(dom_sid) + "-4294967294"
384 bsid_str = "S-1-5-32-4294967294"
385 fsid_str = "S-1-5-4294967294"
386 basedn = self.samdb.get_default_basedn()
387 cn1 = "dsdb_test_fpo1"
388 dn1_str = "cn=%s,cn=Users,%s" % (cn1, basedn)
389 dn1 = ldb.Dn(self.samdb, dn1_str)
390 cn2 = "dsdb_test_fpo2"
391 dn2_str = "cn=%s,cn=Users,%s" % (cn2, basedn)
392 dn2 = ldb.Dn(self.samdb, dn2_str)
394 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
396 expression="(objectSid=%s)" % lsid_str,
398 self.assertEqual(len(res), 0)
399 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
401 expression="(objectSid=%s)" % bsid_str,
403 self.assertEqual(len(res), 0)
404 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
406 expression="(objectSid=%s)" % fsid_str,
408 self.assertEqual(len(res), 0)
410 self.addCleanup(delete_force, self.samdb, dn1_str)
411 self.addCleanup(delete_force, self.samdb, dn2_str)
415 "objectClass": obj_class})
419 "objectClass": obj_class})
423 msg[fpo_attr] = ldb.MessageElement("<SID=%s>" % lsid_str,
427 self.samdb.modify(msg)
428 self.fail("No exception should get %s" % msg_exp)
429 except ldb.LdbError as e:
431 self.assertEqual(code, lerr_exp, str(e))
432 werr = "%08X" % werr_exp
433 self.assertTrue(werr in msg, msg)
437 msg[fpo_attr] = ldb.MessageElement("<SID=%s>" % bsid_str,
441 self.samdb.modify(msg)
442 self.fail("No exception should get %s" % msg_exp)
443 except ldb.LdbError as e:
445 self.assertEqual(code, lerr_exp, str(e))
446 werr = "%08X" % werr_exp
447 self.assertTrue(werr in msg, msg)
451 msg[fpo_attr] = ldb.MessageElement("<SID=%s>" % fsid_str,
455 self.samdb.modify(msg)
456 self.fail("No exception should get %s" % msg)
457 except ldb.LdbError as e:
459 self.assertEqual(code, lerr_exp, str(e))
460 werr = "%08X" % werr_exp
461 self.assertTrue(werr in msg, msg)
465 msg[fpo_attr] = ldb.MessageElement("%s" % dn2,
469 self.samdb.modify(msg)
470 if not allow_reference:
471 sel.fail("No exception should get %s" % msg_exp)
472 except ldb.LdbError as e:
474 self.fail("Should have not raised an exception: %s" % e)
476 self.assertEqual(code, lerr_exp, str(e))
477 werr = "%08X" % werr_exp
478 self.assertTrue(werr in msg, msg)
480 self.samdb.delete(dn2)
481 self.samdb.delete(dn1)
483 def test_foreignSecurityPrincipal_NonMembers(self):
484 return self._test_fail_foreignSecurityPrincipal(
485 "group", "msDS-NonMembers",
486 "LDB_ERR_UNWILLING_TO_PERFORM/WERR_NOT_SUPPORTED",
487 ldb.ERR_UNWILLING_TO_PERFORM, werror.WERR_NOT_SUPPORTED,
488 allow_reference=False)
490 def test_foreignSecurityPrincipal_HostServiceAccount(self):
491 return self._test_fail_foreignSecurityPrincipal(
492 "computer", "msDS-HostServiceAccount",
493 "LDB_ERR_CONSTRAINT_VIOLATION/WERR_DS_NAME_REFERENCE_INVALID",
494 ldb.ERR_CONSTRAINT_VIOLATION,
495 werror.WERR_DS_NAME_REFERENCE_INVALID)
497 def test_foreignSecurityPrincipal_manager(self):
498 return self._test_fail_foreignSecurityPrincipal(
500 "LDB_ERR_CONSTRAINT_VIOLATION/WERR_DS_NAME_REFERENCE_INVALID",
501 ldb.ERR_CONSTRAINT_VIOLATION,
502 werror.WERR_DS_NAME_REFERENCE_INVALID)
505 # Duplicate objectSID's should not be permitted for sids in the local
506 # domain. The test sequence is add an object, delete it, then attempt to
507 # re-add it, this should fail with a constraint violation
509 def test_duplicate_objectSIDs_not_allowed_on_local_objects(self):
511 dom_sid = self.samdb.get_domain_sid()
512 rid = self.allocate_rid()
513 sid_str = str(dom_sid) + "-" + rid
514 sid = ndr_pack(security.dom_sid(sid_str))
515 basedn = self.samdb.get_default_basedn()
517 dn = "cn=%s,cn=Users,%s" % (cn, basedn)
521 "objectClass": "user",
523 self.samdb.delete(dn)
528 "objectClass": "user",
530 self.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
531 except ldb.LdbError as e:
533 if code != ldb.ERR_CONSTRAINT_VIOLATION:
534 self.fail("Got %d - %s should have got "
535 "LDB_ERR_CONSTRAINT_VIOLATION"
538 def test_linked_vs_non_linked_reference(self):
539 basedn = self.samdb.get_default_basedn()
540 kept_dn_str = "cn=reference_kept,cn=Users,%s" % (basedn)
541 removed_dn_str = "cn=reference_removed,cn=Users,%s" % (basedn)
542 dom_sid = self.samdb.get_domain_sid()
543 none_sid_str = str(dom_sid) + "-4294967294"
544 none_guid_str = "afafafaf-fafa-afaf-fafa-afafafafafaf"
546 self.addCleanup(delete_force, self.samdb, kept_dn_str)
547 self.addCleanup(delete_force, self.samdb, removed_dn_str)
551 "objectClass": "user"})
552 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
554 attrs=["objectGUID", "objectSID"])
555 self.assertEqual(len(res), 1)
556 kept_guid = ndr_unpack(misc.GUID, res[0]["objectGUID"][0])
557 kept_sid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0])
561 "dn": removed_dn_str,
562 "objectClass": "user"})
563 res = self.samdb.search(scope=ldb.SCOPE_SUBTREE,
565 attrs=["objectGUID", "objectSID"])
566 self.assertEqual(len(res), 1)
567 removed_guid = ndr_unpack(misc.GUID, res[0]["objectGUID"][0])
568 removed_sid = ndr_unpack(security.dom_sid, res[0]["objectSid"][0])
569 self.samdb.delete(removed_dn_str)
572 # First try the linked attribute 'manager'
578 msg["manager"] = ldb.MessageElement("<SID=%s>" % removed_sid,
582 self.samdb.modify(msg)
583 self.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
584 except ldb.LdbError as e:
586 self.assertEqual(code, ldb.ERR_CONSTRAINT_VIOLATION, str(e))
587 werr = "%08X" % werror.WERR_DS_NAME_REFERENCE_INVALID
588 self.assertTrue(werr in msg, msg)
592 msg["manager"] = ldb.MessageElement("<GUID=%s>" % removed_guid,
596 self.samdb.modify(msg)
597 self.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
598 except ldb.LdbError as e:
600 self.assertEqual(code, ldb.ERR_CONSTRAINT_VIOLATION, str(e))
601 werr = "%08X" % werror.WERR_DS_NAME_REFERENCE_INVALID
602 self.assertTrue(werr in msg, msg)
605 # Try the non-linked attribute 'assistant'
606 # by GUID and SID, which should work.
610 msg["assistant"] = ldb.MessageElement("<SID=%s>" % removed_sid,
613 self.samdb.modify(msg)
616 msg["assistant"] = ldb.MessageElement("<SID=%s>" % removed_sid,
619 self.samdb.modify(msg)
623 msg["assistant"] = ldb.MessageElement("<GUID=%s>" % removed_guid,
626 self.samdb.modify(msg)
629 msg["assistant"] = ldb.MessageElement("<GUID=%s>" % removed_guid,
632 self.samdb.modify(msg)
635 # Finally ry the non-linked attribute 'assistant'
636 # but with non existing GUID, SID, DN
640 msg["assistant"] = ldb.MessageElement("CN=NoneNone,%s" % (basedn),
644 self.samdb.modify(msg)
645 self.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
646 except ldb.LdbError as e:
648 self.assertEqual(code, ldb.ERR_CONSTRAINT_VIOLATION, str(e))
649 werr = "%08X" % werror.WERR_DS_NAME_REFERENCE_INVALID
650 self.assertTrue(werr in msg, msg)
654 msg["assistant"] = ldb.MessageElement("<SID=%s>" % none_sid_str,
658 self.samdb.modify(msg)
659 self.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
660 except ldb.LdbError as e:
662 self.assertEqual(code, ldb.ERR_CONSTRAINT_VIOLATION, str(e))
663 werr = "%08X" % werror.WERR_DS_NAME_REFERENCE_INVALID
664 self.assertTrue(werr in msg, msg)
668 msg["assistant"] = ldb.MessageElement("<GUID=%s>" % none_guid_str,
672 self.samdb.modify(msg)
673 self.fail("No exception should get LDB_ERR_CONSTRAINT_VIOLATION")
674 except ldb.LdbError as e:
676 self.assertEqual(code, ldb.ERR_CONSTRAINT_VIOLATION, str(e))
677 werr = "%08X" % werror.WERR_DS_NAME_REFERENCE_INVALID
678 self.assertTrue(werr in msg, msg)
680 self.samdb.delete(kept_dn)
682 def test_normalize_dn_in_domain_full(self):
683 domain_dn = self.samdb.domain_dn()
685 part_dn = ldb.Dn(self.samdb, "CN=Users")
688 full_dn.add_base(domain_dn)
690 full_str = str(full_dn)
693 self.assertEqual(full_dn,
694 self.samdb.normalize_dn_in_domain(full_str))
696 def test_normalize_dn_in_domain_part(self):
697 domain_dn = self.samdb.domain_dn()
699 part_str = "CN=Users"
701 full_dn = ldb.Dn(self.samdb, part_str)
702 full_dn.add_base(domain_dn)
704 # That is, the domain DN appended
705 self.assertEqual(full_dn,
706 self.samdb.normalize_dn_in_domain(part_str))
708 def test_normalize_dn_in_domain_full_dn(self):
709 domain_dn = self.samdb.domain_dn()
711 part_dn = ldb.Dn(self.samdb, "CN=Users")
714 full_dn.add_base(domain_dn)
717 self.assertEqual(full_dn,
718 self.samdb.normalize_dn_in_domain(full_dn))
720 def test_normalize_dn_in_domain_part_dn(self):
721 domain_dn = self.samdb.domain_dn()
723 part_dn = ldb.Dn(self.samdb, "CN=Users")
725 # That is, the domain DN appended
726 self.assertEqual(ldb.Dn(self.samdb,
727 str(part_dn) + "," + str(domain_dn)),
728 self.samdb.normalize_dn_in_domain(part_dn))
731 class DsdbFullScanTests(TestCase):
734 super(DsdbFullScanTests, self).setUp()
735 self.lp = samba.tests.env_loadparm()
736 self.creds = Credentials()
737 self.creds.guess(self.lp)
738 self.session = system_session()
741 def test_sam_ldb_open_no_full_scan(self):
743 self.samdb = SamDB(session_info=self.session,
744 credentials=self.creds,
746 options=["disable_full_db_scan_for_self_test:1"])
747 except LdbError as err:
749 self.fail("sam.ldb required a full scan to start up")