s4:dsdb python tests - use "ldb.domain_dn"
[kai/samba.git] / source4 / dsdb / tests / python / ldap_schema.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
4
5 import optparse
6 import sys
7 import time
8 import random
9 import os
10
11 sys.path.append("bin/python")
12 import samba
13 samba.ensure_external_module("testtools", "testtools")
14 samba.ensure_external_module("subunit", "subunit/python")
15
16 import samba.getopt as options
17
18 from samba.auth import system_session
19 from ldb import SCOPE_ONELEVEL, SCOPE_BASE, LdbError
20 from ldb import ERR_NO_SUCH_OBJECT
21 from ldb import ERR_UNWILLING_TO_PERFORM
22 from ldb import ERR_CONSTRAINT_VIOLATION
23 from ldb import Message, MessageElement, Dn
24 from ldb import FLAG_MOD_REPLACE
25 from samba.samdb import SamDB
26 from samba.dsdb import DS_DOMAIN_FUNCTION_2003
27
28 from subunit.run import SubunitTestRunner
29 import unittest
30
31 parser = optparse.OptionParser("ldap_schema.py [options] <host>")
32 sambaopts = options.SambaOptions(parser)
33 parser.add_option_group(sambaopts)
34 parser.add_option_group(options.VersionOptions(parser))
35 # use command line creds if available
36 credopts = options.CredentialsOptions(parser)
37 parser.add_option_group(credopts)
38 opts, args = parser.parse_args()
39
40 if len(args) < 1:
41     parser.print_usage()
42     sys.exit(1)
43
44 host = args[0]
45
46 lp = sambaopts.get_loadparm()
47 creds = credopts.get_credentials(lp)
48
49
50 class SchemaTests(unittest.TestCase):
51
52     def delete_force(self, ldb, dn):
53         try:
54             ldb.delete(dn)
55         except LdbError, (num, _):
56             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
57
58     def find_schemadn(self, ldb):
59         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
60         self.assertEquals(len(res), 1)
61         return res[0]["schemaNamingContext"][0]
62
63     def setUp(self):
64         super(SchemaTests, self).setUp()
65         self.ldb = ldb
66         self.base_dn = ldb.domain_dn()
67         self.schema_dn = self.find_schemadn(ldb)
68
69     def test_generated_schema(self):
70         """Testing we can read the generated schema via LDAP"""
71         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
72                 attrs=["objectClasses", "attributeTypes", "dITContentRules"])
73         self.assertEquals(len(res), 1)
74         self.assertTrue("dITContentRules" in res[0])
75         self.assertTrue("objectClasses" in res[0])
76         self.assertTrue("attributeTypes" in res[0])
77
78     def test_generated_schema_is_operational(self):
79         """Testing we don't get the generated schema via LDAP by default"""
80         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
81                 attrs=["*"])
82         self.assertEquals(len(res), 1)
83         self.assertFalse("dITContentRules" in res[0])
84         self.assertFalse("objectClasses" in res[0])
85         self.assertFalse("attributeTypes" in res[0])
86
87     def test_schemaUpdateNow(self):
88         """Testing schemaUpdateNow"""
89         attr_name = "test-Attr" + time.strftime("%s", time.gmtime())
90         attr_ldap_display_name = attr_name.replace("-", "")
91
92         ldif = """
93 dn: CN=%s,%s""" % (attr_name, self.schema_dn) + """
94 objectClass: top
95 objectClass: attributeSchema
96 adminDescription: """ + attr_name + """
97 adminDisplayName: """ + attr_name + """
98 cn: """ + attr_name + """
99 attributeId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9940
100 attributeSyntax: 2.5.5.12
101 omSyntax: 64
102 instanceType: 4
103 isSingleValued: TRUE
104 systemOnly: FALSE
105 """
106         self.ldb.add_ldif(ldif)
107
108         # Search for created attribute
109         res = []
110         res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
111         self.assertEquals(len(res), 1)
112         self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_display_name)
113         self.assertTrue("schemaIDGUID" in res[0])
114
115         class_name = "test-Class" + time.strftime("%s", time.gmtime())
116         class_ldap_display_name = class_name.replace("-", "")
117
118         # First try to create a class with a wrong "defaultObjectCategory"
119         ldif = """
120 dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
121 objectClass: top
122 objectClass: classSchema
123 defaultObjectCategory: CN=_
124 adminDescription: """ + class_name + """
125 adminDisplayName: """ + class_name + """
126 cn: """ + class_name + """
127 governsId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
128 instanceType: 4
129 objectClassCategory: 1
130 subClassOf: organizationalPerson
131 systemFlags: 16
132 rDNAttID: cn
133 systemMustContain: cn
134 systemMustContain: """ + attr_ldap_display_name + """
135 systemOnly: FALSE
136 """
137         try:
138                  self.ldb.add_ldif(ldif)
139                  self.fail()
140         except LdbError, (num, _):
141                  self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
142
143         ldif = """
144 dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
145 objectClass: top
146 objectClass: classSchema
147 adminDescription: """ + class_name + """
148 adminDisplayName: """ + class_name + """
149 cn: """ + class_name + """
150 governsId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
151 instanceType: 4
152 objectClassCategory: 1
153 subClassOf: organizationalPerson
154 systemFlags: 16
155 rDNAttID: cn
156 systemMustContain: cn
157 systemMustContain: """ + attr_ldap_display_name + """
158 systemOnly: FALSE
159 """
160         self.ldb.add_ldif(ldif)
161
162         # Search for created objectclass
163         res = []
164         res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
165         self.assertEquals(len(res), 1)
166         self.assertEquals(res[0]["lDAPDisplayName"][0], class_ldap_display_name)
167         self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0])
168         self.assertTrue("schemaIDGUID" in res[0])
169
170         ldif = """
171 dn:
172 changetype: modify
173 add: schemaUpdateNow
174 schemaUpdateNow: 1
175 """
176         self.ldb.modify_ldif(ldif)
177
178         object_name = "obj" + time.strftime("%s", time.gmtime())
179
180         ldif = """
181 dn: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
182 objectClass: organizationalPerson
183 objectClass: person
184 objectClass: """ + class_ldap_display_name + """
185 objectClass: top
186 cn: """ + object_name + """
187 instanceType: 4
188 objectCategory: CN=%s,%s"""% (class_name, self.schema_dn) + """
189 distinguishedName: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
190 name: """ + object_name + """
191 """ + attr_ldap_display_name + """: test
192 """
193         self.ldb.add_ldif(ldif)
194
195         # Search for created object
196         res = []
197         res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["*"])
198         self.assertEquals(len(res), 1)
199         # Delete the object
200         self.delete_force(self.ldb, "cn=%s,cn=Users,%s" % (object_name, self.base_dn))
201
202     def test_subClassOf(self):
203         """ Testing usage of custom child schamaClass
204         """
205
206         class_name = "my-Class" + time.strftime("%s", time.gmtime())
207         class_ldap_display_name = class_name.replace("-", "")
208
209         ldif = """
210 dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
211 objectClass: top
212 objectClass: classSchema
213 adminDescription: """ + class_name + """
214 adminDisplayName: """ + class_name + """
215 cn: """ + class_name + """
216 governsId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
217 instanceType: 4
218 objectClassCategory: 1
219 subClassOf: organizationalUnit
220 systemFlags: 16
221 systemOnly: FALSE
222 """
223         self.ldb.add_ldif(ldif)
224
225         # Search for created objectclass
226         res = []
227         res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
228         self.assertEquals(len(res), 1)
229         self.assertEquals(res[0]["lDAPDisplayName"][0], class_ldap_display_name)
230         self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0])
231         self.assertTrue("schemaIDGUID" in res[0])
232
233         ldif = """
234 dn:
235 changetype: modify
236 add: schemaUpdateNow
237 schemaUpdateNow: 1
238 """
239         self.ldb.modify_ldif(ldif)
240
241         object_name = "org" + time.strftime("%s", time.gmtime())
242
243         ldif = """
244 dn: OU=%s,%s""" % (object_name, self.base_dn) + """
245 objectClass: """ + class_ldap_display_name + """
246 ou: """ + object_name + """
247 instanceType: 4
248 """
249         self.ldb.add_ldif(ldif)
250
251         # Search for created object
252         res = []
253         res = self.ldb.search("ou=%s,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["*"])
254         self.assertEquals(len(res), 1)
255         # Delete the object
256         self.delete_force(self.ldb, "ou=%s,%s" % (object_name, self.base_dn))
257
258
259 class SchemaTests_msDS_IntId(unittest.TestCase):
260
261     def setUp(self):
262         super(SchemaTests_msDS_IntId, self).setUp()
263         self.ldb = ldb
264         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"])
265         self.assertEquals(len(res), 1)
266         self.schema_dn = res[0]["schemaNamingContext"][0]
267         self.base_dn = res[0]["defaultNamingContext"][0]
268         self.forest_level = int(res[0]["forestFunctionality"][0])
269
270     def _ldap_schemaUpdateNow(self):
271         ldif = """
272 dn:
273 changetype: modify
274 add: schemaUpdateNow
275 schemaUpdateNow: 1
276 """
277         self.ldb.modify_ldif(ldif)
278
279     def _make_obj_names(self, prefix):
280         class_name = prefix + time.strftime("%s", time.gmtime())
281         class_ldap_name = class_name.replace("-", "")
282         class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
283         return (class_name, class_ldap_name, class_dn)
284
285     def _is_schema_base_object(self, ldb_msg):
286         """Test systemFlags for SYSTEM_FLAG_SCHEMA_BASE_OBJECT (16)"""
287         systemFlags = 0
288         if "systemFlags" in ldb_msg:
289             systemFlags = int(ldb_msg["systemFlags"][0])
290         return (systemFlags & 16) != 0
291
292     def _make_attr_ldif(self, attr_name, attr_dn):
293         ldif = """
294 dn: """ + attr_dn + """
295 objectClass: top
296 objectClass: attributeSchema
297 adminDescription: """ + attr_name + """
298 adminDisplayName: """ + attr_name + """
299 cn: """ + attr_name + """
300 attributeId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9940
301 attributeSyntax: 2.5.5.12
302 omSyntax: 64
303 instanceType: 4
304 isSingleValued: TRUE
305 systemOnly: FALSE
306 """
307         return ldif
308
309     def test_msDS_IntId_on_attr(self):
310         """Testing msDs-IntId creation for Attributes.
311         See MS-ADTS - 3.1.1.Attributes
312
313         This test should verify that:
314         - Creating attribute with 'msDS-IntId' fails with ERR_UNWILLING_TO_PERFORM
315         - Adding 'msDS-IntId' on existing attribute fails with ERR_CONSTRAINT_VIOLATION
316         - Creating attribute with 'msDS-IntId' set and FLAG_SCHEMA_BASE_OBJECT flag
317           set fails with ERR_UNWILLING_TO_PERFORM
318         - Attributes created with FLAG_SCHEMA_BASE_OBJECT not set have
319           'msDS-IntId' attribute added internally
320         """
321
322         # 1. Create attribute without systemFlags
323         # msDS-IntId should be created if forest functional
324         # level is >= DS_DOMAIN_FUNCTION_2003
325         # and missing otherwise
326         (attr_name, attr_ldap_name, attr_dn) = self._make_obj_names("msDS-IntId-Attr-1-")
327         ldif = self._make_attr_ldif(attr_name, attr_dn)
328
329         # try to add msDS-IntId during Attribute creation
330         ldif_fail = ldif + "msDS-IntId: -1993108831\n"
331         try:
332             self.ldb.add_ldif(ldif_fail)
333             self.fail("Adding attribute with preset msDS-IntId should fail")
334         except LdbError, (num, _):
335             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
336
337         # add the new attribute and update schema
338         self.ldb.add_ldif(ldif)
339         self._ldap_schemaUpdateNow()
340
341         # Search for created attribute
342         res = []
343         res = self.ldb.search(attr_dn, scope=SCOPE_BASE, attrs=["*"])
344         self.assertEquals(len(res), 1)
345         self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_name)
346         if self.forest_level >= DS_DOMAIN_FUNCTION_2003:
347             if self._is_schema_base_object(res[0]):
348                 self.assertTrue("msDS-IntId" not in res[0])
349             else:
350                 self.assertTrue("msDS-IntId" in res[0])
351         else:
352             self.assertTrue("msDS-IntId" not in res[0])
353
354         msg = Message()
355         msg.dn = Dn(self.ldb, attr_dn)
356         msg["msDS-IntId"] = MessageElement("-1993108831", FLAG_MOD_REPLACE, "msDS-IntId")
357         try:
358             self.ldb.modify(msg)
359             self.fail("Modifying msDS-IntId should return error")
360         except LdbError, (num, _):
361             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
362
363         # 2. Create attribute with systemFlags = FLAG_SCHEMA_BASE_OBJECT
364         # msDS-IntId should be created if forest functional
365         # level is >= DS_DOMAIN_FUNCTION_2003
366         # and missing otherwise
367         (attr_name, attr_ldap_name, attr_dn) = self._make_obj_names("msDS-IntId-Attr-2-")
368         ldif = self._make_attr_ldif(attr_name, attr_dn)
369         ldif += "systemFlags: 16\n"
370
371         # try to add msDS-IntId during Attribute creation
372         ldif_fail = ldif + "msDS-IntId: -1993108831\n"
373         try:
374             self.ldb.add_ldif(ldif_fail)
375             self.fail("Adding attribute with preset msDS-IntId should fail")
376         except LdbError, (num, _):
377             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
378
379         # add the new attribute and update schema
380         self.ldb.add_ldif(ldif)
381         self._ldap_schemaUpdateNow()
382
383         # Search for created attribute
384         res = []
385         res = self.ldb.search(attr_dn, scope=SCOPE_BASE, attrs=["*"])
386         self.assertEquals(len(res), 1)
387         self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_name)
388         if self.forest_level >= DS_DOMAIN_FUNCTION_2003:
389             if self._is_schema_base_object(res[0]):
390                 self.assertTrue("msDS-IntId" not in res[0])
391             else:
392                 self.assertTrue("msDS-IntId" in res[0])
393         else:
394             self.assertTrue("msDS-IntId" not in res[0])
395
396         msg = Message()
397         msg.dn = Dn(self.ldb, attr_dn)
398         msg["msDS-IntId"] = MessageElement("-1993108831", FLAG_MOD_REPLACE, "msDS-IntId")
399         try:
400             self.ldb.modify(msg)
401             self.fail("Modifying msDS-IntId should return error")
402         except LdbError, (num, _):
403             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
404
405
406     def _make_class_ldif(self, class_dn, class_name):
407         ldif = """
408 dn: """ + class_dn + """
409 objectClass: top
410 objectClass: classSchema
411 adminDescription: """ + class_name + """
412 adminDisplayName: """ + class_name + """
413 cn: """ + class_name + """
414 governsId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
415 instanceType: 4
416 objectClassCategory: 1
417 subClassOf: organizationalPerson
418 rDNAttID: cn
419 systemMustContain: cn
420 systemOnly: FALSE
421 """
422         return ldif
423
424     def test_msDS_IntId_on_class(self):
425         """Testing msDs-IntId creation for Class
426            Reference: MS-ADTS - 3.1.1.2.4.8 Class classSchema"""
427
428         # 1. Create Class without systemFlags
429         # msDS-IntId should be created if forest functional
430         # level is >= DS_DOMAIN_FUNCTION_2003
431         # and missing otherwise
432         (class_name, class_ldap_name, class_dn) = self._make_obj_names("msDS-IntId-Class-1-")
433         ldif = self._make_class_ldif(class_dn, class_name)
434
435         # try to add msDS-IntId during Class creation
436         ldif_add = ldif + "msDS-IntId: -1993108831\n"
437         self.ldb.add_ldif(ldif_add)
438         self._ldap_schemaUpdateNow()
439
440         res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["*"])
441         self.assertEquals(len(res), 1)
442         self.assertEquals(res[0]["msDS-IntId"][0], "-1993108831")
443
444         # add a new Class and update schema
445         (class_name, class_ldap_name, class_dn) = self._make_obj_names("msDS-IntId-Class-2-")
446         ldif = self._make_class_ldif(class_dn, class_name)
447
448         self.ldb.add_ldif(ldif)
449         self._ldap_schemaUpdateNow()
450
451         # Search for created Class
452         res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["*"])
453         self.assertEquals(len(res), 1)
454         self.assertFalse("msDS-IntId" in res[0])
455
456         msg = Message()
457         msg.dn = Dn(self.ldb, class_dn)
458         msg["msDS-IntId"] = MessageElement("-1993108831", FLAG_MOD_REPLACE, "msDS-IntId")
459         try:
460             self.ldb.modify(msg)
461             self.fail("Modifying msDS-IntId should return error")
462         except LdbError, (num, _):
463             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
464
465         # 2. Create Class with systemFlags = FLAG_SCHEMA_BASE_OBJECT
466         # msDS-IntId should be created if forest functional
467         # level is >= DS_DOMAIN_FUNCTION_2003
468         # and missing otherwise
469         (class_name, class_ldap_name, class_dn) = self._make_obj_names("msDS-IntId-Class-3-")
470         ldif = self._make_class_ldif(class_dn, class_name)
471         ldif += "systemFlags: 16\n"
472
473         # try to add msDS-IntId during Class creation
474         ldif_add = ldif + "msDS-IntId: -1993108831\n"
475         self.ldb.add_ldif(ldif_add)
476
477         res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["*"])
478         self.assertEquals(len(res), 1)
479         self.assertEquals(res[0]["msDS-IntId"][0], "-1993108831")
480
481         # add the new Class and update schema
482         (class_name, class_ldap_name, class_dn) = self._make_obj_names("msDS-IntId-Class-4-")
483         ldif = self._make_class_ldif(class_dn, class_name)
484         ldif += "systemFlags: 16\n"
485
486         self.ldb.add_ldif(ldif)
487         self._ldap_schemaUpdateNow()
488
489         # Search for created Class
490         res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["*"])
491         self.assertEquals(len(res), 1)
492         self.assertFalse("msDS-IntId" in res[0])
493
494         msg = Message()
495         msg.dn = Dn(self.ldb, class_dn)
496         msg["msDS-IntId"] = MessageElement("-1993108831", FLAG_MOD_REPLACE, "msDS-IntId")
497         try:
498             self.ldb.modify(msg)
499             self.fail("Modifying msDS-IntId should return error")
500         except LdbError, (num, _):
501             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
502         res = self.ldb.search(class_dn, scope=SCOPE_BASE, attrs=["*"])
503         self.assertEquals(len(res), 1)
504         self.assertFalse("msDS-IntId" in res[0])
505
506
507     def test_verify_msDS_IntId(self):
508         """Verify msDS-IntId exists only on attributes without FLAG_SCHEMA_BASE_OBJECT flag set"""
509         count = 0
510         res = self.ldb.search(self.schema_dn, scope=SCOPE_ONELEVEL,
511                               expression="objectClass=attributeSchema",
512                               attrs=["systemFlags", "msDS-IntId", "attributeID", "cn"])
513         self.assertTrue(len(res) > 1)
514         for ldb_msg in res:
515             if self.forest_level >= DS_DOMAIN_FUNCTION_2003:
516                 if self._is_schema_base_object(ldb_msg):
517                     self.assertTrue("msDS-IntId" not in ldb_msg)
518                 else:
519                     # don't assert here as there are plenty of
520                     # attributes under w2k8 that are not part of
521                     # Base Schema (SYSTEM_FLAG_SCHEMA_BASE_OBJECT flag not set)
522                     # has not msDS-IntId attribute set
523                     #self.assertTrue("msDS-IntId" in ldb_msg, "msDS-IntId expected on: %s" % ldb_msg.dn)
524                     if "msDS-IntId" not in ldb_msg:
525                         count = count + 1
526                         print "%3d warning: msDS-IntId expected on: %-30s %s" % (count, ldb_msg["attributeID"], ldb_msg["cn"])
527             else:
528                 self.assertTrue("msDS-IntId" not in ldb_msg)
529
530
531 class SchemaTests_msDS_isRODC(unittest.TestCase):
532
533     def setUp(self):
534         super(SchemaTests_msDS_isRODC, self).setUp()
535         self.ldb = ldb
536         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["*"])
537         self.assertEquals(len(res), 1)
538         self.base_dn = res[0]["defaultNamingContext"][0]
539
540     def test_objectClass_ntdsdsa(self):
541         res = self.ldb.search(self.base_dn, expression="objectClass=nTDSDSA",
542                               attrs=["msDS-isRODC"], controls=["search_options:1:2"])
543         for ldb_msg in res:
544             self.assertTrue("msDS-isRODC" in ldb_msg)
545
546     def test_objectClass_server(self):
547         res = self.ldb.search(self.base_dn, expression="objectClass=server",
548                               attrs=["msDS-isRODC"], controls=["search_options:1:2"])
549         for ldb_msg in res:
550             ntds_search_dn = "CN=NTDS Settings,%s" % ldb_msg['dn']
551             try:
552                 res_check = self.ldb.search(ntds_search_dn, attrs=["objectCategory"])
553             except LdbError, (num, _):
554                 self.assertEquals(num, ERR_NO_SUCH_OBJECT)
555                 print("Server entry %s doesn't have a NTDS settings object" % res[0]['dn'])
556             else:
557                 self.assertTrue("objectCategory" in res_check[0])
558                 self.assertTrue("msDS-isRODC" in ldb_msg)
559
560     def test_objectClass_computer(self):
561         res = self.ldb.search(self.base_dn, expression="objectClass=computer",
562                               attrs=["serverReferenceBL","msDS-isRODC"], controls=["search_options:1:2"])
563         for ldb_msg in res:
564             if "serverReferenceBL" not in ldb_msg:
565                 print("Computer entry %s doesn't have a serverReferenceBL attribute" % ldb_msg['dn'])
566             else:
567                 self.assertTrue("msDS-isRODC" in ldb_msg)
568
569 if not "://" in host:
570     if os.path.isfile(host):
571         host = "tdb://%s" % host
572     else:
573         host = "ldap://%s" % host
574
575 ldb_options = []
576 if host.startswith("ldap://"):
577     # user 'paged_search' module when connecting remotely
578     ldb_options = ["modules:paged_searches"]
579
580 ldb = SamDB(host, credentials=creds, session_info=system_session(), lp=lp, options=ldb_options)
581
582 runner = SubunitTestRunner()
583 rc = 0
584 if not runner.run(unittest.makeSuite(SchemaTests)).wasSuccessful():
585     rc = 1
586 if not runner.run(unittest.makeSuite(SchemaTests_msDS_IntId)).wasSuccessful():
587     rc = 1
588 if not runner.run(unittest.makeSuite(SchemaTests_msDS_isRODC)).wasSuccessful():
589     rc = 1
590
591 sys.exit(rc)