s4:ldap.py - test for an invalid "objectCategory" attribute
[samba.git] / source4 / dsdb / tests / python / ldap.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 base64
9 import os
10
11 sys.path.append("bin/python")
12 import samba
13 samba.ensure_external_module("subunit", "subunit/python")
14 samba.ensure_external_module("testtools", "testtools")
15
16 import samba.getopt as options
17
18 from samba.auth import system_session
19 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
20 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
21 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
22 from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
23 from ldb import ERR_NO_SUCH_ATTRIBUTE
24 from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
25 from ldb import ERR_NAMING_VIOLATION, ERR_CONSTRAINT_VIOLATION
26 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
27 from ldb import Message, MessageElement, Dn
28 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
29 from samba import Ldb
30 from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT, 
31     UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE, ATYPE_NORMAL_ACCOUNT,
32     ATYPE_WORKSTATION_TRUST)
33
34 from subunit.run import SubunitTestRunner
35 import unittest
36
37 from samba.ndr import ndr_pack, ndr_unpack
38 from samba.dcerpc import security
39
40 parser = optparse.OptionParser("ldap [options] <host>")
41 sambaopts = options.SambaOptions(parser)
42 parser.add_option_group(sambaopts)
43 parser.add_option_group(options.VersionOptions(parser))
44 # use command line creds if available
45 credopts = options.CredentialsOptions(parser)
46 parser.add_option_group(credopts)
47 opts, args = parser.parse_args()
48
49 if len(args) < 1:
50     parser.print_usage()
51     sys.exit(1)
52
53 host = args[0]
54
55 lp = sambaopts.get_loadparm()
56 creds = credopts.get_credentials(lp)
57
58 class BasicTests(unittest.TestCase):
59
60     def delete_force(self, ldb, dn):
61         try:
62             ldb.delete(dn)
63         except LdbError, (num, _):
64             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
65
66     def find_basedn(self, ldb):
67         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
68                          attrs=["defaultNamingContext"])
69         self.assertEquals(len(res), 1)
70         return res[0]["defaultNamingContext"][0]
71
72     def find_configurationdn(self, ldb):
73         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["configurationNamingContext"])
74         self.assertEquals(len(res), 1)
75         return res[0]["configurationNamingContext"][0]
76
77     def find_schemadn(self, ldb):
78         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
79         self.assertEquals(len(res), 1)
80         return res[0]["schemaNamingContext"][0]
81
82     def find_domain_sid(self):
83         res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
84         return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
85
86     def setUp(self):
87         super(BasicTests, self).setUp()
88         self.ldb = ldb
89         self.gc_ldb = gc_ldb
90         self.base_dn = self.find_basedn(ldb)
91         self.configuration_dn = self.find_configurationdn(ldb)
92         self.schema_dn = self.find_schemadn(ldb)
93         self.domain_sid = self.find_domain_sid()
94
95         print "baseDN: %s\n" % self.base_dn
96
97         self.delete_force(self.ldb, "cn=posixuser,cn=users," + self.base_dn)
98         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
99         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
100         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
101         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
102         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
103         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
104         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
105         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
106         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
107         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
108         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
109         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
110         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn)
111         self.delete_force(self.ldb, "cn=entry1,cn=ldaptestcontainer," + self.base_dn)
112         self.delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn)
113         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
114         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
115         self.delete_force(self.ldb, "cn=parentguidtest,cn=users," + self.base_dn)
116         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
117         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
118         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
119         self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
120         self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
121         self.delete_force(self.ldb, "cn=testsecret,cn=system," + self.base_dn)
122
123     def test_objectclasses(self):
124         """Test objectClass behaviour"""
125         print "Test objectClass behaviour"""
126
127         # We cannot create LSA-specific objects (oc "secret" or "trustedDomain")
128         try:
129             self.ldb.add({
130                 "dn": "cn=testsecret,cn=system," + self.base_dn,
131                 "objectClass": "secret" })
132             self.fail()
133         except LdbError, (num, _):
134             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
135
136         # Invalid objectclass specified
137         try:
138             self.ldb.add({
139                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
140                 "objectClass": "X" })
141             self.fail()
142         except LdbError, (num, _):
143             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
144
145         # Invalid objectCategory specified
146         try:
147             self.ldb.add({
148                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
149                 "objectClass": "person",
150                 "objectCategory": self.base_dn })
151             self.fail()
152         except LdbError, (num, _):
153             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
154
155         # We cannot instanciate from an abstract objectclass
156         try:
157             self.ldb.add({
158                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
159                 "objectClass": "connectionPoint" })
160             self.fail()
161         except LdbError, (num, _):
162             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
163
164         self.ldb.add({
165              "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
166              "objectClass": "person" })
167
168         # We can remove derivation classes of the structural objectclass
169         # but they're going to be readded afterwards
170         m = Message()
171         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
172         m["objectClass"] = MessageElement("top", FLAG_MOD_DELETE,
173           "objectClass")
174         ldb.modify(m)
175
176         res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
177                          scope=SCOPE_BASE, attrs=["objectClass"])
178         self.assertTrue(len(res) == 1)
179         self.assertTrue("top" in res[0]["objectClass"])
180
181         # The top-most structural class cannot be deleted since there are
182         # attributes of it in use
183         m = Message()
184         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
185         m["objectClass"] = MessageElement("person", FLAG_MOD_DELETE,
186           "objectClass")
187         try:
188             ldb.modify(m)
189             self.fail()
190         except LdbError, (num, _):
191             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
192
193         # We cannot delete classes which weren't specified
194         m = Message()
195         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
196         m["objectClass"] = MessageElement("computer", FLAG_MOD_DELETE,
197           "objectClass")
198         try:
199             ldb.modify(m)
200             self.fail()
201         except LdbError, (num, _):
202             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
203
204         # An invalid class cannot be added
205         m = Message()
206         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
207         m["objectClass"] = MessageElement("X", FLAG_MOD_ADD,
208           "objectClass")
209         try:
210             ldb.modify(m)
211             self.fail()
212         except LdbError, (num, _):
213             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
214
215         # The top-most structural class cannot be changed by adding another
216         # structural one
217         m = Message()
218         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
219         m["objectClass"] = MessageElement("user", FLAG_MOD_ADD,
220           "objectClass")
221         try:
222             ldb.modify(m)
223             self.fail()
224         except LdbError, (num, _):
225             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
226
227         # An already specified objectclass cannot be added another time
228         m = Message()
229         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
230         m["objectClass"] = MessageElement("person", FLAG_MOD_ADD,
231           "objectClass")
232         try:
233             ldb.modify(m)
234             self.fail()
235         except LdbError, (num, _):
236             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
237
238         # Auxiliary classes can always be added
239         m = Message()
240         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
241         m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_ADD,
242           "objectClass")
243         ldb.modify(m)
244
245         # It's only possible to replace with the same objectclass combination.
246         # So the replace action on "objectClass" attributes is really useless.
247         m = Message()
248         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
249         m["objectClass"] = MessageElement(["top", "person", "bootableDevice"],
250           FLAG_MOD_REPLACE, "objectClass")
251         ldb.modify(m)
252
253         m = Message()
254         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
255         m["objectClass"] = MessageElement(["person", "bootableDevice"],
256           FLAG_MOD_REPLACE, "objectClass")
257         ldb.modify(m)
258
259         m = Message()
260         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
261         m["objectClass"] = MessageElement(["top", "person", "bootableDevice",
262           "connectionPoint"], FLAG_MOD_REPLACE, "objectClass")
263         try:
264             ldb.modify(m)
265             self.fail()
266         except LdbError, (num, _):
267             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
268
269         m = Message()
270         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
271         m["objectClass"] = MessageElement(["top", "computer"], FLAG_MOD_REPLACE,
272           "objectClass")
273         try:
274             ldb.modify(m)
275             self.fail()
276         except LdbError, (num, _):
277             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
278
279         # Classes can be removed unless attributes of them are used.
280         m = Message()
281         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
282         m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
283           "objectClass")
284         ldb.modify(m)
285
286         res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
287                          scope=SCOPE_BASE, attrs=["objectClass"])
288         self.assertTrue(len(res) == 1)
289         self.assertFalse("bootableDevice" in res[0]["objectClass"])
290
291         m = Message()
292         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
293         m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_ADD,
294           "objectClass")
295         ldb.modify(m)
296
297         # Add an attribute specific to the "bootableDevice" class
298         m = Message()
299         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
300         m["bootParameter"] = MessageElement("test", FLAG_MOD_ADD,
301           "bootParameter")
302         ldb.modify(m)
303
304         # Classes can be removed unless attributes of them are used. Now there
305         # exist such attributes on the entry.
306         m = Message()
307         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
308         m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
309           "objectClass")
310         try:
311             ldb.modify(m)
312             self.fail()
313         except LdbError, (num, _):
314             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
315
316         # Remove the previously specified attribute
317         m = Message()
318         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
319         m["bootParameter"] = MessageElement("test", FLAG_MOD_DELETE,
320           "bootParameter")
321         ldb.modify(m)
322
323         # Classes can be removed unless attributes of them are used.
324         m = Message()
325         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
326         m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
327           "objectClass")
328         ldb.modify(m)
329
330         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
331
332     def test_system_only(self):
333         """Test systemOnly objects"""
334         print "Test systemOnly objects"""
335
336         try:
337             self.ldb.add({
338                 "dn": "cn=ldaptestobject," + self.base_dn,
339                 "objectclass": "configuration"})
340             self.fail()
341         except LdbError, (num, _):
342             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
343
344         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
345         self.delete_force(self.ldb, "cn=testsecret,cn=system," + self.base_dn)
346
347     def test_invalid_parent(self):
348         """Test adding an object with invalid parent"""
349         print "Test adding an object with invalid parent"""
350
351         try:
352             self.ldb.add({
353                 "dn": "cn=ldaptestgroup,cn=thisdoesnotexist123,"
354                    + self.base_dn,
355                 "objectclass": "group"})
356             self.fail()
357         except LdbError, (num, _):
358             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
359
360         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=thisdoesnotexist123,"
361           + self.base_dn)
362
363         try:
364             self.ldb.add({
365                 "dn": "ou=testou,cn=users," + self.base_dn,
366                 "objectclass": "organizationalUnit"})
367             self.fail()
368         except LdbError, (num, _):
369             self.assertEquals(num, ERR_NAMING_VIOLATION)
370
371         self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
372
373     def test_invalid_attribute(self):
374         """Test invalid attributes on schema/objectclasses"""
375         print "Test invalid attributes on schema/objectclasses"""
376
377         # attributes not in schema test
378
379         # add operation
380
381         try:
382             self.ldb.add({
383                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
384                 "objectclass": "group",
385                 "thisdoesnotexist": "x"})
386             self.fail()
387         except LdbError, (num, _):
388             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
389
390         self.ldb.add({
391              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
392              "objectclass": "group"})
393
394         # modify operation
395
396         m = Message()
397         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
398         m["thisdoesnotexist"] = MessageElement("x", FLAG_MOD_REPLACE,
399           "thisdoesnotexist")
400         try:
401             ldb.modify(m)
402             self.fail()
403         except LdbError, (num, _):
404             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
405
406         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
407
408         # attributes not in objectclasses and mandatory attributes missing test
409         # Use here a non-SAM entry since it doesn't have special triggers
410         # associated which have an impact on the error results.
411
412         # add operations
413
414         # mandatory attribute missing
415         try:
416             self.ldb.add({
417                 "dn": "cn=ldaptestobject," + self.base_dn,
418                 "objectclass": "ipProtocol"})
419             self.fail()
420         except LdbError, (num, _):
421             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
422
423         # inadequate but schema-valid attribute specified
424         try:
425             self.ldb.add({
426                 "dn": "cn=ldaptestobject," + self.base_dn,
427                 "objectclass": "ipProtocol",
428                 "ipProtocolNumber": "1",
429                 "uid" : "0"})
430             self.fail()
431         except LdbError, (num, _):
432             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
433
434         self.ldb.add({
435             "dn": "cn=ldaptestobject," + self.base_dn,
436             "objectclass": "ipProtocol",
437             "ipProtocolNumber": "1"})
438
439         # modify operations
440
441         # inadequate but schema-valid attribute add trial
442         m = Message()
443         m.dn = Dn(ldb, "cn=ldaptestobject," + self.base_dn)
444         m["uid"] = MessageElement("0", FLAG_MOD_ADD, "uid")
445         try:
446             ldb.modify(m)
447             self.fail()
448         except LdbError, (num, _):
449             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
450
451         # mandatory attribute delete trial
452         m = Message()
453         m.dn = Dn(ldb, "cn=ldaptestobject," + self.base_dn)
454         m["ipProtocolNumber"] = MessageElement([], FLAG_MOD_DELETE,
455           "ipProtocolNumber")
456         try:
457             ldb.modify(m)
458             self.fail()
459         except LdbError, (num, _):
460             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
461
462         # mandatory attribute delete trial
463         m = Message()
464         m.dn = Dn(ldb, "cn=ldaptestobject," + self.base_dn)
465         m["ipProtocolNumber"] = MessageElement([], FLAG_MOD_REPLACE,
466           "ipProtocolNumber")
467         try:
468             ldb.modify(m)
469             self.fail()
470         except LdbError, (num, _):
471             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
472
473         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
474
475     def test_single_valued_attributes(self):
476         """Test single-valued attributes"""
477         print "Test single-valued attributes"""
478
479         try:
480             self.ldb.add({
481                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
482                 "objectclass": "group",
483                 "sAMAccountName": ["nam1", "nam2"]})
484             self.fail()
485         except LdbError, (num, _):
486             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
487
488         self.ldb.add({
489              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
490              "objectclass": "group"})
491
492         m = Message()
493         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
494         m["sAMAccountName"] = MessageElement(["nam1","nam2"], FLAG_MOD_REPLACE,
495           "sAMAccountName")
496         try:
497             ldb.modify(m)
498             self.fail()
499         except LdbError, (num, _):
500             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
501
502         m = Message()
503         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
504         m["sAMAccountName"] = MessageElement("testgroupXX", FLAG_MOD_REPLACE,
505           "sAMAccountName")
506         ldb.modify(m)
507
508         m = Message()
509         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
510         m["sAMAccountName"] = MessageElement("testgroupXX2", FLAG_MOD_ADD,
511           "sAMAccountName")
512         try:
513             ldb.modify(m)
514             self.fail()
515         except LdbError, (num, _):
516             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
517
518         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
519
520     def test_multi_valued_attributes(self):
521         """Test multi-valued attributes"""
522         print "Test multi-valued attributes"""
523
524 # TODO: In this test I added some special tests where I got very unusual
525 # results back from a real AD. s4 doesn't match them and I've no idea how to
526 # implement those error cases (maybe there exists a special trigger for
527 # "description" attributes which handle them)
528
529         self.ldb.add({
530             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
531             "description": "desc2",
532             "objectclass": "group",
533             "description": "desc1"})
534
535         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
536
537         self.ldb.add({
538             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
539             "objectclass": "group",
540             "description": ["desc1", "desc2"]})
541
542 #        m = Message()
543 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
544 #        m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
545 #          "description")
546 #        try:
547 #            ldb.modify(m)
548 #            self.fail()
549 #        except LdbError, (num, _):
550 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
551
552         m = Message()
553         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
554         m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
555           "description")
556         ldb.modify(m)
557
558 #        m = Message()
559 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
560 #        m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
561 #          "description")
562 #        try:
563 #            ldb.modify(m)
564 #            self.fail()
565 #        except LdbError, (num, _):
566 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
567
568         m = Message()
569         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
570         m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_DELETE,
571           "description")
572         try:
573             ldb.modify(m)
574             self.fail()
575         except LdbError, (num, _):
576             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
577
578         m = Message()
579         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
580         m["description"] = MessageElement("desc1", FLAG_MOD_DELETE,
581           "description")
582         ldb.modify(m)
583
584 #        m = Message()
585 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
586 #        m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
587 #          "description")
588 #        try:
589 #            ldb.modify(m)
590 #            self.fail()
591 #        except LdbError, (num, _):
592 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
593
594 #        m = Message()
595 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
596 #        m["description"] = MessageElement(["desc3", "desc4"], FLAG_MOD_ADD,
597 #          "description")
598 #        try:
599 #            ldb.modify(m)
600 #            self.fail()
601 #        except LdbError, (num, _):
602 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
603
604         m = Message()
605         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
606         m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
607           "description")
608         ldb.modify(m)
609
610         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
611
612     def test_empty_messages(self):
613         """Test empty messages"""
614         print "Test empty messages"""
615
616         m = Message()
617         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
618
619         try:
620             ldb.add(m)
621             self.fail()
622         except LdbError, (num, _):
623             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
624
625         try:
626             ldb.modify(m)
627             self.fail()
628         except LdbError, (num, _):
629             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
630
631         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
632
633     def test_empty_attributes(self):
634         """Test empty attributes"""
635         print "Test empty attributes"""
636
637         m = Message()
638         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
639         m["objectClass"] = MessageElement("group", FLAG_MOD_ADD, "objectClass")
640         m["description"] = MessageElement([], FLAG_MOD_ADD, "description")
641
642         try:
643             ldb.add(m)
644             self.fail()
645         except LdbError, (num, _):
646             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
647
648         self.ldb.add({
649             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
650             "objectclass": "group"})
651
652         m = Message()
653         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
654         m["description"] = MessageElement([], FLAG_MOD_ADD, "description")
655
656         try:
657             ldb.modify(m)
658             self.fail()
659         except LdbError, (num, _):
660             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
661
662         m = Message()
663         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
664         m["description"] = MessageElement([], FLAG_MOD_REPLACE, "description")
665         ldb.modify(m)
666
667         m = Message()
668         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
669         m["description"] = MessageElement([], FLAG_MOD_DELETE, "description")
670         try:
671             ldb.modify(m)
672             self.fail()
673         except LdbError, (num, _):
674             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
675
676         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
677
678     def test_instanceType(self):
679         """Tests the 'instanceType' attribute"""
680         print "Tests the 'instanceType' attribute"""
681
682         # The instance type is single-valued
683         try:
684             self.ldb.add({
685                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
686                 "objectclass": "group",
687                 "instanceType": ["0", "1"]})
688             self.fail()
689         except LdbError, (num, _):
690             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
691
692         # The head NC flag cannot be set without the write flag
693         try:
694             self.ldb.add({
695                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
696                 "objectclass": "group",
697                 "instanceType": "1" })
698             self.fail()
699         except LdbError, (num, _):
700             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
701
702         # We cannot manipulate NCs without the head NC flag
703         try:
704             self.ldb.add({
705                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
706                 "objectclass": "group",
707                 "instanceType": "32" })
708             self.fail()
709         except LdbError, (num, _):
710             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
711
712         self.ldb.add({
713              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
714              "objectclass": "group"})
715
716         m = Message()
717         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
718         m["instanceType"] = MessageElement("0", FLAG_MOD_REPLACE,
719           "instanceType")
720         try:
721             ldb.modify(m)
722             self.fail()
723         except LdbError, (num, _):
724             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
725
726         m = Message()
727         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
728         m["instanceType"] = MessageElement([], FLAG_MOD_REPLACE,
729           "instanceType")
730         try:
731             ldb.modify(m)
732             self.fail()
733         except LdbError, (num, _):
734             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
735
736         m = Message()
737         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
738         m["instanceType"] = MessageElement([], FLAG_MOD_DELETE, "instanceType")
739         try:
740             ldb.modify(m)
741             self.fail()
742         except LdbError, (num, _):
743             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
744
745         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
746
747     def test_distinguished_name(self):
748         """Tests the 'distinguishedName' attribute"""
749         print "Tests the 'distinguishedName' attribute"""
750
751         # a wrong "distinguishedName" attribute is obviously tolerated
752         self.ldb.add({
753               "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
754               "objectclass": "group",
755               "distinguishedName": "cn=ldaptest,cn=users," + self.base_dn})
756
757         # proof if the DN has been set correctly
758         res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
759                          scope=SCOPE_BASE, attrs=["distinguishedName"])
760         self.assertTrue(len(res) == 1)
761         self.assertTrue("distinguishedName" in res[0])
762         self.assertTrue(Dn(ldb, res[0]["distinguishedName"][0])
763            == Dn(ldb, "cn=ldaptestgroup, cn=users," + self.base_dn))
764
765         m = Message()
766         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
767         m["distinguishedName"] = MessageElement(
768           "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_ADD,
769           "distinguishedName")
770
771         try:
772             ldb.modify(m)
773             self.fail()
774         except LdbError, (num, _):
775             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
776
777         m = Message()
778         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
779         m["distinguishedName"] = MessageElement(
780           "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_REPLACE,
781           "distinguishedName")
782
783         try:
784             ldb.modify(m)
785             self.fail()
786         except LdbError, (num, _):
787             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
788
789         m = Message()
790         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
791         m["distinguishedName"] = MessageElement(
792           "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_DELETE,
793           "distinguishedName")
794
795         try:
796             ldb.modify(m)
797             self.fail()
798         except LdbError, (num, _):
799             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
800
801         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
802
803     def test_rdn_name(self):
804         """Tests the RDN"""
805         print "Tests the RDN"""
806
807         try:
808             self.ldb.add({
809                  "dn": "description=xyz,cn=users," + self.base_dn,
810                  "objectclass": "group"})
811             self.fail()
812         except LdbError, (num, _):
813             self.assertEquals(num, ERR_NAMING_VIOLATION)
814
815         self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
816
817         # a wrong "name" attribute is obviously tolerated
818         self.ldb.add({
819              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
820              "objectclass": "group",
821              "name": "ldaptestgroupx"})
822
823         # proof if the name has been set correctly
824         res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
825                          scope=SCOPE_BASE, attrs=["name"])
826         self.assertTrue(len(res) == 1)
827         self.assertTrue("name" in res[0])
828         self.assertTrue(res[0]["name"][0] == "ldaptestgroup")
829
830         m = Message()
831         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
832         m["name"] = MessageElement("cn=ldaptestuser", FLAG_MOD_REPLACE,
833           "name")
834         try:
835             ldb.modify(m)
836             self.fail()
837         except LdbError, (num, _):
838             self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN)
839
840         m = Message()
841         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
842         m["cn"] = MessageElement("ldaptestuser",
843           FLAG_MOD_REPLACE, "cn")
844         try:
845             ldb.modify(m)
846             self.fail()
847         except LdbError, (num, _):
848             self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN)
849
850         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
851
852
853         # this test needs to be disabled until we really understand
854         # what the rDN length constraints are
855     def DISABLED_test_largeRDN(self):
856         """Testing large rDN (limit 64 characters)"""
857         rdn = "CN=a012345678901234567890123456789012345678901234567890123456789012";
858         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
859         ldif = """
860 dn: %s,%s""" % (rdn,self.base_dn) + """
861 objectClass: container
862 """
863         self.ldb.add_ldif(ldif)
864         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
865
866         rdn = "CN=a0123456789012345678901234567890123456789012345678901234567890120";
867         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
868         try:
869             ldif = """
870 dn: %s,%s""" % (rdn,self.base_dn) + """
871 objectClass: container
872 """
873             self.ldb.add_ldif(ldif)
874             self.fail()
875         except LdbError, (num, _):
876             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
877         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
878
879     def test_rename(self):
880         """Tests the rename operation"""
881         print "Tests the rename operations"""
882
883         try:
884             # cannot rename to be a child of itself
885             ldb.rename(self.base_dn, "dc=test," + self.base_dn)
886             self.fail()
887         except LdbError, (num, _):
888             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
889
890         try:
891             # inexistent object
892             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
893             self.fail()
894         except LdbError, (num, _):
895             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
896
897         self.ldb.add({
898              "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
899              "objectclass": ["user", "person"] })
900
901         ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
902         ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
903         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestUSER3,cn=users," + self.base_dn)
904
905         try:
906             # containment problem: a user entry cannot contain user entries
907             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser4,cn=ldaptestuser3,cn=users," + self.base_dn)
908             self.fail()
909         except LdbError, (num, _):
910             self.assertEquals(num, ERR_NAMING_VIOLATION)
911
912         try:
913             # invalid parent
914             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=people,cn=users," + self.base_dn)
915             self.fail()
916         except LdbError, (num, _):
917             self.assertEquals(num, ERR_OTHER)
918
919         try:
920             # invalid target DN syntax
921             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, ",cn=users," + self.base_dn)
922             self.fail()
923         except LdbError, (num, _):
924             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
925
926         try:
927             # invalid RDN name
928             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "ou=ldaptestuser3,cn=users," + self.base_dn)
929             self.fail()
930         except LdbError, (num, _):
931             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
932
933         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
934
935         # Performs some "systemFlags" testing
936
937         # Move failing since no "SYSTEM_FLAG_CONFIG_ALLOW_MOVE"
938         try:
939             ldb.rename("CN=DisplaySpecifiers," + self.configuration_dn, "CN=DisplaySpecifiers,CN=Services," + self.configuration_dn)
940             self.fail()
941         except LdbError, (num, _):
942             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
943
944         # Limited move failing since no "SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE"
945         try:
946             ldb.rename("CN=Directory Service,CN=Windows NT,CN=Services," + self.configuration_dn, "CN=Directory Service,CN=RRAS,CN=Services," + self.configuration_dn)
947             self.fail()
948         except LdbError, (num, _):
949             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
950
951         # Rename failing since no "SYSTEM_FLAG_CONFIG_ALLOW_RENAME"
952         try:
953             ldb.rename("CN=DisplaySpecifiers," + self.configuration_dn, "CN=DisplaySpecifiers2," + self.configuration_dn)
954             self.fail()
955         except LdbError, (num, _):
956             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
957
958         # It's not really possible to test moves on the schema partition since
959         # there don't exist subcontainers on it.
960
961         # Rename failing since "SYSTEM_FLAG_SCHEMA_BASE_OBJECT"
962         try:
963             ldb.rename("CN=Top," + self.schema_dn, "CN=Top2," + self.schema_dn)
964             self.fail()
965         except LdbError, (num, _):
966             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
967
968         # Move failing since "SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE"
969         try:
970             ldb.rename("CN=Users," + self.base_dn, "CN=Users,CN=Computers," + self.base_dn)
971             self.fail()
972         except LdbError, (num, _):
973             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
974
975         # Rename failing since "SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME"
976         try:
977             ldb.rename("CN=Users," + self.base_dn, "CN=Users2," + self.base_dn)
978             self.fail()
979         except LdbError, (num, _):
980             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
981
982         # Performs some other constraints testing
983
984         try:
985             ldb.rename("CN=Policies,CN=System," + self.base_dn, "CN=Users2," + self.base_dn)
986             self.fail()
987         except LdbError, (num, _):
988             self.assertEquals(num, ERR_OTHER)
989
990     def test_rename_twice(self):
991         """Tests the rename operation twice - this corresponds to a past bug"""
992         print "Tests the rename twice operation"""
993
994         self.ldb.add({
995              "dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
996              "objectclass": ["user", "person"] })
997
998         ldb.rename("cn=ldaptestuser5,cn=users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
999         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
1000         self.ldb.add({
1001              "dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
1002              "objectclass": ["user", "person"] })
1003         ldb.rename("cn=ldaptestuser5,cn=Users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
1004         res = ldb.search(expression="cn=ldaptestuser5")
1005         print "Found %u records" % len(res)
1006         self.assertEquals(len(res), 1, "Wrong number of hits for cn=ldaptestuser5")
1007         res = ldb.search(expression="(&(cn=ldaptestuser5)(objectclass=user))")
1008         print "Found %u records" % len(res)
1009         self.assertEquals(len(res), 1, "Wrong number of hits for (&(cn=ldaptestuser5)(objectclass=user))")
1010         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
1011
1012     def test_parentGUID(self):
1013         """Test parentGUID behaviour"""
1014         print "Testing parentGUID behaviour\n"
1015
1016         # TODO: This seems to fail on Windows Server. Hidden attribute?
1017
1018         self.ldb.add({
1019             "dn": "cn=parentguidtest,cn=users," + self.base_dn,
1020             "objectclass":"user",
1021             "samaccountname":"parentguidtest"});
1022         res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE,
1023                           attrs=["parentGUID", "samaccountname"]);
1024         res2 = ldb.search(base="cn=users," + self.base_dn,scope=SCOPE_BASE,
1025                           attrs=["objectGUID"]);
1026         res3 = ldb.search(base=self.base_dn, scope=SCOPE_BASE,
1027                           attrs=["parentGUID"]);
1028
1029         """Check if the parentGUID is valid """
1030         self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]);
1031
1032         """Check if it returns nothing when there is no parent object"""
1033         has_parentGUID = False
1034         for key in res3[0].keys():
1035             if key == "parentGUID":
1036                 has_parentGUID = True
1037                 break
1038         self.assertFalse(has_parentGUID);
1039
1040         """Ensures that if you look for another object attribute after the constructed
1041             parentGUID, it will return correctly"""
1042         has_another_attribute = False
1043         for key in res1[0].keys():
1044             if key == "sAMAccountName":
1045                 has_another_attribute = True
1046                 break
1047         self.assertTrue(has_another_attribute)
1048         self.assertTrue(len(res1[0]["samaccountname"]) == 1)
1049         self.assertEquals(res1[0]["samaccountname"][0], "parentguidtest");
1050
1051         print "Testing parentGUID behaviour on rename\n"
1052
1053         self.ldb.add({
1054             "dn": "cn=testotherusers," + self.base_dn,
1055             "objectclass":"container"});
1056         res1 = ldb.search(base="cn=testotherusers," + self.base_dn,scope=SCOPE_BASE,
1057                           attrs=["objectGUID"]);
1058         ldb.rename("cn=parentguidtest,cn=users," + self.base_dn,
1059                    "cn=parentguidtest,cn=testotherusers," + self.base_dn);
1060         res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn,
1061                           scope=SCOPE_BASE,
1062                           attrs=["parentGUID"]);
1063         self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]);
1064
1065         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
1066         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
1067
1068     def test_groupType_int32(self):
1069         """Test groupType (int32) behaviour (should appear to be casted to a 32 bit signed integer before comparsion)"""
1070         print "Testing groupType (int32) behaviour\n"
1071
1072         res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
1073                           attrs=["groupType"], expression="groupType=2147483653");
1074
1075         res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
1076                           attrs=["groupType"], expression="groupType=-2147483643");
1077
1078         self.assertEquals(len(res1), len(res2))
1079
1080         self.assertTrue(res1.count > 0)
1081
1082         self.assertEquals(res1[0]["groupType"][0], "-2147483643")
1083
1084     def test_linked_attributes(self):
1085         """This tests the linked attribute behaviour"""
1086         print "Testing linked attribute behaviour\n"
1087
1088         ldb.add({
1089             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1090             "objectclass": "group"})
1091
1092         # This should not work since "memberOf" is linked to "member"
1093         try:
1094             ldb.add({
1095                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1096                 "objectclass": ["user", "person"],
1097                 "memberOf": "cn=ldaptestgroup,cn=users," + self.base_dn})
1098         except LdbError, (num, _):
1099             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1100
1101         ldb.add({
1102             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1103             "objectclass": ["user", "person"]})
1104
1105         m = Message()
1106         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1107         m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
1108           FLAG_MOD_ADD, "memberOf")
1109         try:
1110             ldb.modify(m)
1111             self.fail()
1112         except LdbError, (num, _):
1113             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1114
1115         m = Message()
1116         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1117         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1118           FLAG_MOD_ADD, "member")
1119         ldb.modify(m)
1120
1121         m = Message()
1122         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1123         m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
1124           FLAG_MOD_REPLACE, "memberOf")
1125         try:
1126             ldb.modify(m)
1127             self.fail()
1128         except LdbError, (num, _):
1129             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1130
1131         m = Message()
1132         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1133         m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
1134           FLAG_MOD_DELETE, "memberOf")
1135         try:
1136             ldb.modify(m)
1137             self.fail()
1138         except LdbError, (num, _):
1139             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1140
1141         m = Message()
1142         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1143         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1144           FLAG_MOD_DELETE, "member")
1145         ldb.modify(m)
1146
1147         # This should yield no results since the member attribute for
1148         # "ldaptestuser" should have been deleted
1149         res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
1150                           scope=SCOPE_BASE,
1151                           expression="(member=cn=ldaptestuser,cn=users," + self.base_dn + ")",
1152                           attrs=[])
1153         self.assertTrue(len(res1) == 0)
1154
1155         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1156
1157         ldb.add({
1158             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1159             "objectclass": "group",
1160             "member": "cn=ldaptestuser,cn=users," + self.base_dn})
1161
1162         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1163
1164         # Make sure that the "member" attribute for "ldaptestuser" has been
1165         # removed
1166         res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1167                           scope=SCOPE_BASE, attrs=["member"])
1168         self.assertTrue(len(res) == 1)
1169         self.assertFalse("member" in res[0])
1170
1171         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1172
1173     def test_groups(self):
1174         """This tests the group behaviour (setting, changing) of a user account"""
1175         print "Testing group behaviour\n"
1176
1177         ldb.add({
1178             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1179             "objectclass": "group"})
1180
1181         ldb.add({
1182             "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
1183             "objectclass": "group"})
1184
1185         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1186                           scope=SCOPE_BASE, attrs=["objectSID"])
1187         self.assertTrue(len(res1) == 1)
1188         group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
1189           res1[0]["objectSID"][0])).split()[1]
1190
1191         res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
1192                           scope=SCOPE_BASE, attrs=["objectSID"])
1193         self.assertTrue(len(res1) == 1)
1194         group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
1195           res1[0]["objectSID"][0])).split()[1]
1196
1197         # Try to create a user with an invalid primary group
1198         try:
1199             ldb.add({
1200                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1201                 "objectclass": ["user", "person"],
1202                 "primaryGroupID": "0"})
1203             self.fail()
1204         except LdbError, (num, _):
1205             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1206         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1207
1208         # Try to Create a user with a valid primary group
1209 # TODO Some more investigation needed here
1210 #        try:
1211 #            ldb.add({
1212 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1213 #                "objectclass": ["user", "person"],
1214 #                "primaryGroupID": str(group_rid_1)})
1215 #            self.fail()
1216 #        except LdbError, (num, _):
1217 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1218 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1219
1220         # Test to see how we should behave when the user account doesn't
1221         # exist
1222         m = Message()
1223         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1224         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
1225           "primaryGroupID")
1226         try:
1227             ldb.modify(m)
1228             self.fail()
1229         except LdbError, (num, _):
1230             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1231
1232         # Test to see how we should behave when the account isn't a user
1233         m = Message()
1234         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1235         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
1236           "primaryGroupID")
1237         try:
1238             ldb.modify(m)
1239             self.fail()
1240         except LdbError, (num, _):
1241             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
1242
1243         ldb.add({
1244             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1245             "objectclass": ["user", "person"]})
1246
1247         # We should be able to reset our actual primary group
1248         m = Message()
1249         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1250         m["primaryGroupID"] = MessageElement("513", FLAG_MOD_REPLACE,
1251           "primaryGroupID")
1252         ldb.modify(m)
1253
1254         # Try to add invalid primary group
1255         m = Message()
1256         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1257         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
1258           "primaryGroupID")
1259         try:
1260             ldb.modify(m)
1261             self.fail()
1262         except LdbError, (num, _):
1263             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1264
1265         # Try to make group 1 primary - should be denied since it is not yet
1266         # secondary
1267         m = Message()
1268         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1269         m["primaryGroupID"] = MessageElement(str(group_rid_1),
1270           FLAG_MOD_REPLACE, "primaryGroupID")
1271         try:
1272             ldb.modify(m)
1273             self.fail()
1274         except LdbError, (num, _):
1275             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1276
1277         # Make group 1 secondary
1278         m = Message()
1279         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1280         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1281                                      FLAG_MOD_REPLACE, "member")
1282         ldb.modify(m)
1283
1284         # Make group 1 primary
1285         m = Message()
1286         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1287         m["primaryGroupID"] = MessageElement(str(group_rid_1),
1288           FLAG_MOD_REPLACE, "primaryGroupID")
1289         ldb.modify(m)
1290
1291         # Try to delete group 1 - should be denied
1292         try:
1293             ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
1294             self.fail()
1295         except LdbError, (num, _):
1296             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1297
1298         # Try to add group 1 also as secondary - should be denied
1299         m = Message()
1300         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1301         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1302                                      FLAG_MOD_ADD, "member")
1303         try:
1304             ldb.modify(m)
1305             self.fail()
1306         except LdbError, (num, _):
1307             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1308
1309         # Try to add invalid member to group 1 - should be denied
1310         m = Message()
1311         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1312         m["member"] = MessageElement(
1313           "cn=ldaptestuser3,cn=users," + self.base_dn,
1314           FLAG_MOD_ADD, "member")
1315         try:
1316             ldb.modify(m)
1317             self.fail()
1318         except LdbError, (num, _):
1319             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1320
1321         # Make group 2 secondary
1322         m = Message()
1323         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1324         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1325                                      FLAG_MOD_ADD, "member")
1326         ldb.modify(m)
1327
1328         # Swap the groups
1329         m = Message()
1330         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1331         m["primaryGroupID"] = MessageElement(str(group_rid_2),
1332           FLAG_MOD_REPLACE, "primaryGroupID")
1333         ldb.modify(m)
1334
1335         # Old primary group should contain a "member" attribute for the user,
1336         # the new shouldn't contain anymore one
1337         res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
1338                           scope=SCOPE_BASE, attrs=["member"])
1339         self.assertTrue(len(res1) == 1)
1340         self.assertTrue(len(res1[0]["member"]) == 1)
1341         self.assertEquals(res1[0]["member"][0].lower(),
1342           ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
1343
1344         res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
1345                           scope=SCOPE_BASE, attrs=["member"])
1346         self.assertTrue(len(res1) == 1)
1347         self.assertFalse("member" in res1[0])
1348
1349         # Also this should be denied
1350         try:
1351             ldb.add({
1352               "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
1353               "objectclass": ["user", "person"],
1354               "primaryGroupID": "0"})
1355             self.fail()
1356         except LdbError, (num, _):
1357             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1358
1359         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1360         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1361         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1362
1363     def test_sam_attributes(self):
1364         """Test the behaviour of special attributes of SAM objects"""
1365         print "Testing the behaviour of special attributes of SAM objects\n"""
1366
1367         ldb.add({
1368             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1369             "objectclass": ["user", "person"]})
1370         ldb.add({
1371             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1372             "objectclass": "group"})
1373
1374         m = Message()
1375         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1376         m["groupType"] = MessageElement("0", FLAG_MOD_ADD,
1377           "groupType")
1378         try:
1379             ldb.modify(m)
1380             self.fail()
1381         except LdbError, (num, _):
1382             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1383
1384         m = Message()
1385         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1386         m["groupType"] = MessageElement([], FLAG_MOD_DELETE,
1387           "groupType")
1388         try:
1389             ldb.modify(m)
1390             self.fail()
1391         except LdbError, (num, _):
1392             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1393
1394         m = Message()
1395         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1396         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_ADD,
1397           "primaryGroupID")
1398         try:
1399             ldb.modify(m)
1400             self.fail()
1401         except LdbError, (num, _):
1402             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1403
1404         m = Message()
1405         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1406         m["primaryGroupID"] = MessageElement([], FLAG_MOD_DELETE,
1407           "primaryGroupID")
1408         try:
1409             ldb.modify(m)
1410             self.fail()
1411         except LdbError, (num, _):
1412             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1413
1414         m = Message()
1415         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1416         m["userAccountControl"] = MessageElement("0", FLAG_MOD_ADD,
1417           "userAccountControl")
1418         try:
1419             ldb.modify(m)
1420             self.fail()
1421         except LdbError, (num, _):
1422             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1423
1424         m = Message()
1425         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1426         m["userAccountControl"] = MessageElement([], FLAG_MOD_DELETE,
1427           "userAccountControl")
1428         try:
1429             ldb.modify(m)
1430             self.fail()
1431         except LdbError, (num, _):
1432             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1433
1434         m = Message()
1435         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1436         m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
1437           "sAMAccountType")
1438         try:
1439             ldb.modify(m)
1440             self.fail()
1441         except LdbError, (num, _):
1442             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1443
1444         m = Message()
1445         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1446         m["sAMAccountType"] = MessageElement([], FLAG_MOD_REPLACE,
1447           "sAMAccountType")
1448         try:
1449             ldb.modify(m)
1450             self.fail()
1451         except LdbError, (num, _):
1452             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1453
1454         m = Message()
1455         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1456         m["sAMAccountType"] = MessageElement([], FLAG_MOD_DELETE,
1457           "sAMAccountType")
1458         try:
1459             ldb.modify(m)
1460             self.fail()
1461         except LdbError, (num, _):
1462             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1463
1464         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1465         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1466
1467     def test_primary_group_token_constructed(self):
1468         """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
1469         print "Testing primary group token behaviour and other constructed attributes\n"
1470
1471         try:
1472             ldb.add({
1473                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1474                 "objectclass": "group",
1475                 "primaryGroupToken": "100"})
1476             self.fail()
1477         except LdbError, (num, _):
1478             self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
1479         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1480
1481         ldb.add({
1482             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1483             "objectclass": ["user", "person"]})
1484
1485         ldb.add({
1486             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1487             "objectclass": "group"})
1488
1489         # Testing for one invalid, and one valid operational attribute, but also the things they are built from
1490         res1 = ldb.search(self.base_dn,
1491                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
1492         self.assertTrue(len(res1) == 1)
1493         self.assertFalse("primaryGroupToken" in res1[0])
1494         self.assertTrue("canonicalName" in res1[0])
1495         self.assertTrue("objectClass" in res1[0])
1496         self.assertTrue("objectSid" in res1[0])
1497
1498         res1 = ldb.search(self.base_dn,
1499                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
1500         self.assertTrue(len(res1) == 1)
1501         self.assertFalse("primaryGroupToken" in res1[0])
1502         self.assertFalse("objectSid" in res1[0])
1503         self.assertFalse("objectClass" in res1[0])
1504         self.assertTrue("canonicalName" in res1[0])
1505
1506         res1 = ldb.search("cn=users,"+self.base_dn,
1507                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
1508         self.assertTrue(len(res1) == 1)
1509         self.assertFalse("primaryGroupToken" in res1[0])
1510
1511         res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
1512                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
1513         self.assertTrue(len(res1) == 1)
1514         self.assertFalse("primaryGroupToken" in res1[0])
1515
1516         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1517                           scope=SCOPE_BASE)
1518         self.assertTrue(len(res1) == 1)
1519         self.assertFalse("primaryGroupToken" in res1[0])
1520
1521         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1522                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
1523         self.assertTrue(len(res1) == 1)
1524         primary_group_token = int(res1[0]["primaryGroupToken"][0])
1525
1526         rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
1527         self.assertEquals(primary_group_token, rid)
1528
1529         m = Message()
1530         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1531         m["primaryGroupToken"] = "100"
1532         try:
1533             ldb.modify(m)
1534             self.fail()
1535         except LdbError, (num, _):
1536             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1537
1538         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1539         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1540
1541     def test_tokenGroups(self):
1542         """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
1543         print "Testing tokenGroups behaviour\n"
1544
1545         # The domain object shouldn't contain any "tokenGroups" entry
1546         res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
1547         self.assertTrue(len(res) == 1)
1548         self.assertFalse("tokenGroups" in res[0])
1549
1550         # The domain administrator should contain "tokenGroups" entries
1551         # (the exact number depends on the domain/forest function level and the
1552         # DC software versions)
1553         res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
1554                          scope=SCOPE_BASE, attrs=["tokenGroups"])
1555         self.assertTrue(len(res) == 1)
1556         self.assertTrue("tokenGroups" in res[0])
1557
1558         ldb.add({
1559             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1560             "objectclass": ["user", "person"]})
1561
1562         # This testuser should contain at least two "tokenGroups" entries
1563         # (exactly two on an unmodified "Domain Users" and "Users" group)
1564         res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1565                          scope=SCOPE_BASE, attrs=["tokenGroups"])
1566         self.assertTrue(len(res) == 1)
1567         self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
1568
1569         # one entry which we need to find should point to domains "Domain Users"
1570         # group and another entry should point to the builtin "Users"group
1571         domain_users_group_found = False
1572         users_group_found = False
1573         for sid in res[0]["tokenGroups"]:
1574             rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
1575             if rid == 513:
1576                 domain_users_group_found = True
1577             if rid == 545:
1578                 users_group_found = True
1579
1580         self.assertTrue(domain_users_group_found)
1581         self.assertTrue(users_group_found)
1582
1583         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1584
1585     def test_wkguid(self):
1586         """Test Well known GUID behaviours (including DN+Binary)"""
1587         print "Test Well known GUID behaviours (including DN+Binary)"""
1588
1589         res = self.ldb.search(base=("<WKGUID=ab1d30f3768811d1aded00c04fd8d5cd,%s>" % self.base_dn), scope=SCOPE_BASE, attrs=[])
1590         self.assertEquals(len(res), 1)
1591         
1592         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd:%s" % res[0].dn))
1593         self.assertEquals(len(res2), 1)
1594
1595         # Prove that the matching rule is over the whole DN+Binary
1596         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd"))
1597         self.assertEquals(len(res2), 0)
1598         # Prove that the matching rule is over the whole DN+Binary
1599         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=%s") % res[0].dn)
1600         self.assertEquals(len(res2), 0)
1601
1602     def test_subschemasubentry(self):
1603         """Test subSchemaSubEntry appears when requested, but not when not requested"""
1604         print "Test subSchemaSubEntry"""
1605
1606         res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["subSchemaSubEntry"])
1607         self.assertEquals(len(res), 1)
1608         self.assertEquals(res[0]["subSchemaSubEntry"][0], "CN=Aggregate,"+self.schema_dn)
1609
1610         res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["*"])
1611         self.assertEquals(len(res), 1)
1612         self.assertTrue("subScheamSubEntry" not in res[0])
1613
1614     def test_delete(self):
1615         """Tests the delete operation"""
1616         print "Tests the delete operations"""
1617
1618         ldb.add({
1619             "dn": "cn=ldaptestcontainer," + self.base_dn,
1620             "objectclass": "container"})
1621         ldb.add({
1622             "dn": "cn=entry1,cn=ldaptestcontainer," + self.base_dn,
1623             "objectclass": "container"})
1624         ldb.add({
1625             "dn": "cn=entry2,cn=ldaptestcontainer," + self.base_dn,
1626             "objectclass": "container"})
1627
1628         try:
1629             ldb.delete("cn=ldaptestcontainer," + self.base_dn)
1630             self.fail()
1631         except LdbError, (num, _):
1632             self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
1633
1634         ldb.delete("cn=ldaptestcontainer," + self.base_dn, ["tree_delete:0"])
1635
1636         try:
1637             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1638                              scope=SCOPE_BASE, attrs=[])
1639             self.fail()
1640         except LdbError, (num, _):
1641             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1642         try:
1643             res = ldb.search("cn=entry1,cn=ldaptestcontainer," + self.base_dn,
1644                              scope=SCOPE_BASE, attrs=[])
1645             self.fail()
1646         except LdbError, (num, _):
1647             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1648         try:
1649             res = ldb.search("cn=entry2,cn=ldaptestcontainer," + self.base_dn,
1650                              scope=SCOPE_BASE, attrs=[])
1651             self.fail()
1652         except LdbError, (num, _):
1653             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1654
1655         self.delete_force(self.ldb, "cn=entry1,cn=ldaptestcontainer," + self.base_dn)
1656         self.delete_force(self.ldb, "cn=entry2,cn=ldaptestcontainer," + self.base_dn)
1657         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
1658
1659         # Performs some protected object delete testing
1660
1661         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
1662                          attrs=["dsServiceName", "dNSHostName"])
1663         self.assertEquals(len(res), 1)
1664
1665         try:
1666             ldb.delete(res[0]["dsServiceName"][0])
1667             self.fail()
1668         except LdbError, (num, _):
1669             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1670
1671         res = ldb.search(self.base_dn, scope=SCOPE_SUBTREE,
1672                          attrs=["rIDSetReferences"],
1673                          expression="(&(objectClass=computer)(dNSHostName=" + res[0]["dNSHostName"][0] + "))")
1674         self.assertEquals(len(res), 1)
1675
1676         try:
1677             ldb.delete(res[0]["rIDSetReferences"][0])
1678             self.fail()
1679         except LdbError, (num, _):
1680             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1681
1682         try:
1683             ldb.delete("cn=Enterprise Schema,cn=Partitions," + self.configuration_dn)
1684             self.fail()
1685         except LdbError, (num, _):
1686             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1687
1688         try:
1689             ldb.delete("cn=Enterprise Configuration,cn=Partitions," + self.configuration_dn)
1690             self.fail()
1691         except LdbError, (num, _):
1692             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1693
1694         # Performs some "systemFlags" testing
1695
1696         # Delete failing since "SYSTEM_FLAG_DISALLOW_DELETE"
1697         try:
1698             ldb.delete("CN=Users," + self.base_dn)
1699             self.fail()
1700         except LdbError, (num, _):
1701             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1702
1703     def test_all(self):
1704         """Basic tests"""
1705
1706         print "Testing user add"
1707
1708         ldb.add({
1709             "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
1710             "objectclass": ["user", "person"],
1711             "cN": "LDAPtestUSER",
1712             "givenname": "ldap",
1713             "sn": "testy"})
1714
1715         ldb.add({
1716             "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
1717             "objectclass": "group",
1718             "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
1719
1720         ldb.add({
1721             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1722             "objectclass": "computer",
1723             "cN": "LDAPtestCOMPUTER"})
1724
1725         ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
1726             "objectClass": "computer",
1727             "cn": "LDAPtest2COMPUTER",
1728             "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT),
1729             "displayname": "ldap testy"})
1730
1731         try:
1732             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
1733                      "objectClass": "computer",
1734                      "cn": "LDAPtest2COMPUTER"
1735                      })
1736             self.fail()
1737         except LdbError, (num, _):
1738             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
1739
1740         try:
1741             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
1742                      "objectClass": "computer",
1743                      "cn": "ldaptestcomputer3",
1744                      "sAMAccountType": str(ATYPE_NORMAL_ACCOUNT)
1745                 })
1746             self.fail()
1747         except LdbError, (num, _):
1748             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1749
1750         ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
1751                  "objectClass": "computer",
1752                  "cn": "LDAPtestCOMPUTER3"
1753                  })
1754
1755         print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
1756         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
1757         self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
1758
1759         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn));
1760         self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3");
1761         self.assertEquals(res[0]["name"][0], "ldaptestcomputer3");
1762         self.assertEquals(res[0]["objectClass"][0], "top");
1763         self.assertEquals(res[0]["objectClass"][1], "person");
1764         self.assertEquals(res[0]["objectClass"][2], "organizationalPerson");
1765         self.assertEquals(res[0]["objectClass"][3], "user");
1766         self.assertEquals(res[0]["objectClass"][4], "computer");
1767         self.assertTrue("objectGUID" in res[0])
1768         self.assertTrue("whenCreated" in res[0])
1769         self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
1770         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
1771         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT);
1772         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE);
1773
1774         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
1775
1776         print "Testing attribute or value exists behaviour"
1777         try:
1778             ldb.modify_ldif("""
1779 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1780 changetype: modify
1781 replace: servicePrincipalName
1782 servicePrincipalName: host/ldaptest2computer
1783 servicePrincipalName: host/ldaptest2computer
1784 servicePrincipalName: cifs/ldaptest2computer
1785 """)
1786             self.fail()
1787         except LdbError, (num, msg):
1788             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1789
1790         ldb.modify_ldif("""
1791 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1792 changetype: modify
1793 replace: servicePrincipalName
1794 servicePrincipalName: host/ldaptest2computer
1795 servicePrincipalName: cifs/ldaptest2computer
1796 """)
1797         try:
1798             ldb.modify_ldif("""
1799 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1800 changetype: modify
1801 add: servicePrincipalName
1802 servicePrincipalName: host/ldaptest2computer
1803 """)
1804             self.fail()
1805         except LdbError, (num, msg):
1806             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1807
1808         print "Testing ranged results"
1809         ldb.modify_ldif("""
1810 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1811 changetype: modify
1812 replace: servicePrincipalName
1813 """)
1814
1815         ldb.modify_ldif("""
1816 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1817 changetype: modify
1818 add: servicePrincipalName
1819 servicePrincipalName: host/ldaptest2computer0
1820 servicePrincipalName: host/ldaptest2computer1
1821 servicePrincipalName: host/ldaptest2computer2
1822 servicePrincipalName: host/ldaptest2computer3
1823 servicePrincipalName: host/ldaptest2computer4
1824 servicePrincipalName: host/ldaptest2computer5
1825 servicePrincipalName: host/ldaptest2computer6
1826 servicePrincipalName: host/ldaptest2computer7
1827 servicePrincipalName: host/ldaptest2computer8
1828 servicePrincipalName: host/ldaptest2computer9
1829 servicePrincipalName: host/ldaptest2computer10
1830 servicePrincipalName: host/ldaptest2computer11
1831 servicePrincipalName: host/ldaptest2computer12
1832 servicePrincipalName: host/ldaptest2computer13
1833 servicePrincipalName: host/ldaptest2computer14
1834 servicePrincipalName: host/ldaptest2computer15
1835 servicePrincipalName: host/ldaptest2computer16
1836 servicePrincipalName: host/ldaptest2computer17
1837 servicePrincipalName: host/ldaptest2computer18
1838 servicePrincipalName: host/ldaptest2computer19
1839 servicePrincipalName: host/ldaptest2computer20
1840 servicePrincipalName: host/ldaptest2computer21
1841 servicePrincipalName: host/ldaptest2computer22
1842 servicePrincipalName: host/ldaptest2computer23
1843 servicePrincipalName: host/ldaptest2computer24
1844 servicePrincipalName: host/ldaptest2computer25
1845 servicePrincipalName: host/ldaptest2computer26
1846 servicePrincipalName: host/ldaptest2computer27
1847 servicePrincipalName: host/ldaptest2computer28
1848 servicePrincipalName: host/ldaptest2computer29
1849 """)
1850
1851         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
1852                          attrs=["servicePrincipalName;range=0-*"])
1853         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1854         #print len(res[0]["servicePrincipalName;range=0-*"])
1855         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1856
1857         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
1858         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1859             # print res[0]["servicePrincipalName;range=0-19"].length
1860         self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
1861
1862
1863         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
1864         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1865         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1866
1867         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
1868         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1869         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1870
1871         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
1872         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1873         self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
1874
1875
1876         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
1877         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1878         self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
1879         # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
1880
1881         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
1882         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1883         self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19)
1884             # print res[0]["servicePrincipalName;range=11-*"][18]
1885             # print pos_11
1886             # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
1887
1888         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
1889         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1890         self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5)
1891             # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
1892
1893         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
1894         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1895             # print res[0]["servicePrincipalName"][18]
1896             # print pos_11
1897         self.assertEquals(len(res[0]["servicePrincipalName"]), 30)
1898             # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11)
1899
1900         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1901         ldb.add({
1902             "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
1903             "objectClass": ["person", "user"],
1904             "cn": "LDAPtestUSER2",
1905             "givenname": "testy",
1906             "sn": "ldap user2"})
1907
1908         print "Testing Ambigious Name Resolution"
1909         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
1910         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
1911         self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
1912
1913         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1914         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1915         self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
1916
1917         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
1918         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
1919         self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
1920
1921         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
1922         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
1923         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
1924
1925         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1926         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1927         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1928
1929         # Testing ldb.search for (&(anr=testy)(objectClass=user))
1930         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
1931         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
1932
1933         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1934         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1935         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
1936
1937         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1938 # this test disabled for the moment, as anr with == tests are not understood
1939 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1940 #        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
1941
1942 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1943 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1944 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1945
1946         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1947 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1948 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
1949
1950 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1951 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1952 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1953
1954         # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
1955         res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
1956         self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
1957
1958         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1959         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1960         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1961
1962         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
1963 #        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
1964 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
1965
1966         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1967         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1968         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1969
1970         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
1971 #        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
1972 #        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
1973
1974         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1975         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1976         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1977
1978         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
1979 #        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
1980 #        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
1981
1982         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
1983         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
1984         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
1985
1986         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
1987 #        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
1988 #        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
1989
1990         print "Testing Renames"
1991
1992         attrs = ["objectGUID", "objectSid"]
1993         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
1994         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
1995         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
1996
1997         # Check rename works with extended/alternate DN forms
1998         ldb.rename("<SID=" + ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0]) + ">" , "cn=ldaptestUSER3,cn=users," + self.base_dn)
1999
2000         print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))"
2001         res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
2002         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
2003
2004         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2005         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
2006         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
2007
2008          #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
2009         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
2010         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
2011
2012         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2013         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
2014         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
2015
2016          #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
2017         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
2018         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
2019
2020         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2021         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
2022         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
2023
2024          #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
2025         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
2026         self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
2027
2028         # This is a Samba special, and does not exist in real AD
2029         #    print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
2030         #    res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
2031         #    if (res.error != 0 || len(res) != 1) {
2032         #        print "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
2033         #        self.assertEquals(len(res), 1)
2034         #    }
2035         #    self.assertEquals(res[0].dn, ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2036         #    self.assertEquals(res[0].cn, "ldaptestUSER3")
2037         #    self.assertEquals(res[0].name, "ldaptestUSER3")
2038
2039         print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
2040         res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
2041         self.assertEquals(len(res), 1, "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
2042         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2043         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
2044         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
2045
2046         # ensure we cannot add it again
2047         try:
2048             ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
2049                       "objectClass": ["person", "user"],
2050                       "cn": "LDAPtestUSER3"})
2051             self.fail()
2052         except LdbError, (num, _):
2053             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
2054
2055         # rename back
2056         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
2057
2058         # ensure we cannot rename it twice
2059         try:
2060             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
2061                        "cn=ldaptestuser2,cn=users," + self.base_dn)
2062             self.fail()
2063         except LdbError, (num, _):
2064             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
2065
2066         # ensure can now use that name
2067         ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
2068                       "objectClass": ["person", "user"],
2069                       "cn": "LDAPtestUSER3"})
2070
2071         # ensure we now cannot rename
2072         try:
2073             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
2074             self.fail()
2075         except LdbError, (num, _):
2076             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
2077         try:
2078             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
2079             self.fail()
2080         except LdbError, (num, _):
2081             self.assertTrue(num in (71, 64))
2082
2083         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
2084
2085         ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
2086
2087         self.delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
2088
2089         ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
2090
2091         print "Testing subtree renames"
2092
2093         ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
2094                  "objectClass": "container"})
2095
2096         ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
2097                  "objectClass": ["person", "user"],
2098                  "cn": "LDAPtestUSER4"})
2099
2100         ldb.modify_ldif("""
2101 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2102 changetype: modify
2103 add: member
2104 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
2105 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
2106 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
2107 """)
2108
2109         print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
2110         ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
2111
2112         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))"
2113         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
2114         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
2115
2116         print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
2117         try:
2118             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
2119                     expression="(&(cn=ldaptestuser4)(objectClass=user))",
2120                     scope=SCOPE_SUBTREE)
2121             self.fail(res)
2122         except LdbError, (num, _):
2123             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
2124
2125         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
2126         try:
2127             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
2128                     expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
2129             self.fail()
2130         except LdbError, (num, _):
2131             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
2132
2133         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
2134         res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
2135         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
2136
2137         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
2138         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2139
2140         time.sleep(4)
2141
2142         print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
2143         res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
2144         self.assertEquals(len(res), 1, "Could not find (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)), perhaps linked attributes are not consistant with subtree renames?")
2145
2146         print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
2147         try:
2148             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
2149             self.fail()
2150         except LdbError, (num, _):
2151             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
2152
2153         print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
2154         try:
2155             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
2156             self.fail()
2157         except LdbError, (num, _):
2158             self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER))
2159
2160         print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
2161         try:
2162             ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
2163             self.fail()
2164         except LdbError, (num, _):
2165             self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
2166
2167         print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
2168         res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
2169         self.assertEquals(len(res), 1)
2170         res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
2171         self.assertEquals(len(res), 0)
2172
2173         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
2174         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
2175         # FIXME: self.assertEquals(len(res), 0)
2176
2177         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
2178         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
2179         # FIXME: self.assertEquals(len(res), 0)
2180
2181         print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
2182         ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
2183         print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
2184         ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
2185
2186         ldb.add({"dn": "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
2187
2188         ldb.add({"dn": "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
2189
2190         print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
2191         res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
2192         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
2193
2194         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
2195         self.assertEquals(str(res[0]["cn"]), "ldaptestuser")
2196         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
2197         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user"]))
2198         self.assertTrue("objectGUID" in res[0])
2199         self.assertTrue("whenCreated" in res[0])
2200         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
2201         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
2202         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2203         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2204         self.assertEquals(len(res[0]["memberOf"]), 1)
2205
2206         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
2207         res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
2208         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
2209
2210         self.assertEquals(res[0].dn, res2[0].dn)
2211
2212         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
2213         res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
2214         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
2215
2216         self.assertEquals(res[0].dn, res3[0].dn)
2217
2218         if gc_ldb is not None:
2219             print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
2220             res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
2221             self.assertEquals(len(res3gc), 1)
2222
2223             self.assertEquals(res[0].dn, res3gc[0].dn)
2224
2225         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
2226
2227         if gc_ldb is not None:
2228             res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
2229             self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
2230
2231             self.assertEquals(res[0].dn, res3control[0].dn)
2232
2233         ldb.delete(res[0].dn)
2234
2235         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
2236         res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
2237         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
2238
2239         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
2240         self.assertEquals(str(res[0]["cn"]), "ldaptestcomputer")
2241         self.assertEquals(str(res[0]["name"]), "ldaptestcomputer")
2242         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user", "computer"]))
2243         self.assertTrue("objectGUID" in res[0])
2244         self.assertTrue("whenCreated" in res[0])
2245         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
2246         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
2247         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
2248         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2249         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2250         self.assertEquals(len(res[0]["memberOf"]), 1)
2251
2252         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
2253         res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
2254         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
2255
2256         self.assertEquals(res[0].dn, res2[0].dn)
2257
2258         if gc_ldb is not None:
2259             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
2260             res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
2261             self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
2262
2263             self.assertEquals(res[0].dn, res2gc[0].dn)
2264
2265         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
2266         res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
2267         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
2268
2269         self.assertEquals(res[0].dn, res3[0].dn)
2270
2271         if gc_ldb is not None:
2272             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
2273             res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
2274             self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
2275
2276             self.assertEquals(res[0].dn, res3gc[0].dn)
2277
2278         print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
2279         res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
2280         self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
2281
2282         self.assertEquals(res[0].dn, res4[0].dn)
2283
2284         print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
2285         res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
2286         self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
2287
2288         self.assertEquals(res[0].dn, res5[0].dn)
2289
2290         print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
2291         res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
2292         self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
2293
2294         self.assertEquals(res[0].dn, res6[0].dn)
2295
2296         ldb.delete("<GUID=" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + ">")
2297
2298         print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
2299         res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
2300         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
2301
2302         self.assertEquals(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn)
2303         self.assertEquals(str(res[0]["cn"]), "ldaptest2computer")
2304         self.assertEquals(str(res[0]["name"]), "ldaptest2computer")
2305         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user", "computer"])
2306         self.assertTrue("objectGUID" in res[0])
2307         self.assertTrue("whenCreated" in res[0])
2308         self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
2309         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
2310         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT)
2311
2312         ldb.delete("<SID=" + ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + ">")
2313
2314         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"]
2315         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
2316         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
2317         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
2318
2319         self.assertEquals(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2320         self.assertEquals(str(res_user[0]["cn"]), "ldaptestuser2")
2321         self.assertEquals(str(res_user[0]["name"]), "ldaptestuser2")
2322         self.assertEquals(list(res_user[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
2323         self.assertTrue("objectSid" in res_user[0])
2324         self.assertTrue("objectGUID" in res_user[0])
2325         self.assertTrue("whenCreated" in res_user[0])
2326         self.assertTrue("nTSecurityDescriptor" in res_user[0])
2327         self.assertTrue("allowedAttributes" in res_user[0])
2328         self.assertTrue("allowedAttributesEffective" in res_user[0])
2329         self.assertEquals(res_user[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2330
2331         ldaptestuser2_sid = res_user[0]["objectSid"][0]
2332         ldaptestuser2_guid = res_user[0]["objectGUID"][0]
2333
2334         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"]
2335         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
2336         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2337         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2338
2339         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2340         self.assertEquals(str(res[0]["cn"]), "ldaptestgroup2")
2341         self.assertEquals(str(res[0]["name"]), "ldaptestgroup2")
2342         self.assertEquals(list(res[0]["objectClass"]), ["top", "group"])
2343         self.assertTrue("objectGUID" in res[0])
2344         self.assertTrue("objectSid" in res[0])
2345         self.assertTrue("whenCreated" in res[0])
2346         self.assertTrue("nTSecurityDescriptor" in res[0])
2347         self.assertTrue("allowedAttributes" in res[0])
2348         self.assertTrue("allowedAttributesEffective" in res[0])
2349         memberUP = []
2350         for m in res[0]["member"]:
2351             memberUP.append(m.upper())
2352         self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
2353
2354         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"])
2355         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2356
2357         print res[0]["member"]
2358         memberUP = []
2359         for m in res[0]["member"]:
2360             memberUP.append(m.upper())
2361         print ("<GUID=" + ldb.schema_format_value("objectGUID", ldaptestuser2_guid) + ">;<SID=" + ldb.schema_format_value("objectSid", ldaptestuser2_sid) + ">;CN=ldaptestuser2,CN=Users," + self.base_dn).upper()
2362
2363         self.assertTrue(("<GUID=" + ldb.schema_format_value("objectGUID", ldaptestuser2_guid) + ">;<SID=" + ldb.schema_format_value("objectSid", ldaptestuser2_sid) + ">;CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
2364
2365         print "Quicktest for linked attributes"
2366         ldb.modify_ldif("""
2367 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2368 changetype: modify
2369 replace: member
2370 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
2371 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2372 """)
2373
2374         ldb.modify_ldif("""
2375 dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
2376 changetype: modify
2377 replace: member
2378 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2379 """)
2380
2381         ldb.modify_ldif("""
2382 dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
2383 changetype: modify
2384 delete: member
2385 """)
2386
2387         ldb.modify_ldif("""
2388 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2389 changetype: modify
2390 add: member
2391 member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
2392 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2393 """)
2394
2395         ldb.modify_ldif("""
2396 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2397 changetype: modify
2398 replace: member
2399 """)
2400
2401         ldb.modify_ldif("""
2402 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2403 changetype: modify
2404 add: member
2405 member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
2406 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2407 """)
2408
2409         ldb.modify_ldif("""
2410 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2411 changetype: modify
2412 delete: member
2413 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2414 """)
2415
2416         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2417         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2418
2419         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2420         self.assertEquals(res[0]["member"][0], ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2421         self.assertEquals(len(res[0]["member"]), 1)
2422
2423         ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
2424
2425         time.sleep(4)
2426
2427         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
2428         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
2429         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2430         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
2431
2432         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2433         self.assertTrue("member" not in res[0])
2434
2435         print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
2436 # TODO UTF8 users don't seem to work fully anymore
2437 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2438         res = ldb.search(expression="(&(cn=ldaptestutf8user èùéìòà)(objectclass=user))")
2439         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2440
2441         self.assertEquals(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
2442         self.assertEquals(str(res[0]["cn"]), "ldaptestutf8user èùéìòà")
2443         self.assertEquals(str(res[0]["name"]), "ldaptestutf8user èùéìòà")
2444         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
2445         self.assertTrue("objectGUID" in res[0])
2446         self.assertTrue("whenCreated" in res[0])
2447
2448         ldb.delete(res[0].dn)
2449
2450         print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
2451         res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
2452         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
2453
2454         ldb.delete(res[0].dn)
2455
2456         ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2457
2458         print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
2459 # TODO UTF8 users don't seem to work fully anymore
2460 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2461 #        self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2462
2463         print "Testing that we can't get at the configuration DN from the main search base"
2464         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2465         self.assertEquals(len(res), 0)
2466
2467         print "Testing that we can get at the configuration DN from the main search base on the LDAP port with the 'phantom root' search_options control"
2468         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
2469         self.assertTrue(len(res) > 0)
2470
2471         if gc_ldb is not None:
2472             print "Testing that we can get at the configuration DN from the main search base on the GC port with the search_options control == 0"
2473
2474             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
2475             self.assertTrue(len(res) > 0)
2476
2477             print "Testing that we do find configuration elements in the global catlog"
2478             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2479             self.assertTrue(len(res) > 0)
2480
2481             print "Testing that we do find configuration elements and user elements at the same time"
2482             res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
2483             self.assertTrue(len(res) > 0)
2484
2485             print "Testing that we do find configuration elements in the global catlog, with the configuration basedn"
2486             res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2487             self.assertTrue(len(res) > 0)
2488
2489         print "Testing that we can get at the configuration DN on the main LDAP port"
2490         res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2491         self.assertTrue(len(res) > 0)
2492
2493         print "Testing objectCategory canonacolisation"
2494         res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
2495         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
2496         self.assertTrue(len(res) != 0)
2497
2498         res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
2499         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
2500         self.assertTrue(len(res) != 0)
2501
2502         print "Testing objectClass attribute order on "+ self.base_dn
2503         res = ldb.search(expression="objectClass=domain", base=self.base_dn,
2504                          scope=SCOPE_BASE, attrs=["objectClass"])
2505         self.assertEquals(len(res), 1)
2506
2507         self.assertEquals(list(res[0]["objectClass"]), ["top", "domain", "domainDNS"])
2508
2509     #  check enumeration
2510
2511         print "Testing ldb.search for objectCategory=person"
2512         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
2513         self.assertTrue(len(res) > 0)
2514
2515         print "Testing ldb.search for objectCategory=person with domain scope control"
2516         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2517         self.assertTrue(len(res) > 0)
2518
2519         print "Testing ldb.search for objectCategory=user"
2520         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
2521         self.assertTrue(len(res) > 0)
2522
2523         print "Testing ldb.search for objectCategory=user with domain scope control"
2524         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2525         self.assertTrue(len(res) > 0)
2526
2527         print "Testing ldb.search for objectCategory=group"
2528         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
2529         self.assertTrue(len(res) > 0)
2530
2531         print "Testing ldb.search for objectCategory=group with domain scope control"
2532         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2533         self.assertTrue(len(res) > 0)
2534
2535         print "Testing creating a user with the posixAccount objectClass"
2536         self.ldb.add_ldif("""dn: cn=posixuser,CN=Users,%s
2537 objectClass: top
2538 objectClass: person
2539 objectClass: posixAccount
2540 objectClass: user
2541 objectClass: organizationalPerson
2542 cn: posixuser
2543 uid: posixuser
2544 sn: posixuser
2545 uidNumber: 10126
2546 gidNumber: 10126
2547 homeDirectory: /home/posixuser
2548 loginShell: /bin/bash
2549 gecos: Posix User;;;
2550 description: A POSIX user"""% (self.base_dn))
2551
2552         print "Testing removing the posixAccount objectClass from an existing user"
2553         self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
2554 changetype: modify
2555 delete: objectClass
2556 objectClass: posixAccount"""% (self.base_dn))
2557
2558         print "Testing adding the posixAccount objectClass to an existing user"
2559         self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
2560 changetype: modify
2561 add: objectClass
2562 objectClass: posixAccount"""% (self.base_dn))
2563
2564         self.delete_force(self.ldb, "cn=posixuser,cn=users," + self.base_dn)
2565         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2566         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2567         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
2568         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
2569         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
2570         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
2571         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
2572         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
2573         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2574         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
2575         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
2576         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
2577         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn)
2578         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
2579         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
2580
2581     def test_security_descriptor_add(self):
2582         """ Testing ldb.add_ldif() for nTSecurityDescriptor """
2583         user_name = "testdescriptoruser1"
2584         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2585         #
2586         # Test add_ldif() with SDDL security descriptor input
2587         #
2588         self.delete_force(self.ldb, user_dn)
2589         try:
2590             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2591             self.ldb.add_ldif("""
2592 dn: """ + user_dn + """
2593 objectclass: user
2594 sAMAccountName: """ + user_name + """
2595 nTSecurityDescriptor: """ + sddl)
2596             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2597             desc = res[0]["nTSecurityDescriptor"][0]
2598             desc = ndr_unpack( security.descriptor, desc )
2599             desc_sddl = desc.as_sddl( self.domain_sid )
2600             self.assertEqual(desc_sddl, sddl)
2601         finally:
2602             self.delete_force(self.ldb, user_dn)
2603         #
2604         # Test add_ldif() with BASE64 security descriptor
2605         #
2606         try:
2607             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2608             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
2609             desc_binary = ndr_pack(desc)
2610             desc_base64 = base64.b64encode(desc_binary)
2611             self.ldb.add_ldif("""
2612 dn: """ + user_dn + """
2613 objectclass: user
2614 sAMAccountName: """ + user_name + """
2615 nTSecurityDescriptor:: """ + desc_base64)
2616             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2617             desc = res[0]["nTSecurityDescriptor"][0]
2618             desc = ndr_unpack(security.descriptor, desc)
2619             desc_sddl = desc.as_sddl(self.domain_sid)
2620             self.assertEqual(desc_sddl, sddl)
2621         finally:
2622             self.delete_force(self.ldb, user_dn)
2623
2624     def test_security_descriptor_add_neg(self):
2625         """Test add_ldif() with BASE64 security descriptor input using WRONG domain SID
2626             Negative test
2627         """
2628         user_name = "testdescriptoruser1"
2629         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2630         self.delete_force(self.ldb, user_dn)
2631         try:
2632             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2633             desc = security.descriptor.from_sddl(sddl, security.dom_sid('S-1-5-21'))
2634             desc_base64 = base64.b64encode( ndr_pack(desc) )
2635             self.ldb.add_ldif("""
2636 dn: """ + user_dn + """
2637 objectclass: user
2638 sAMAccountName: """ + user_name + """
2639 nTSecurityDescriptor:: """ + desc_base64)
2640             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2641             self.assertTrue("nTSecurityDescriptor" in res[0])
2642         finally:
2643             self.delete_force(self.ldb, user_dn)
2644
2645     def test_security_descriptor_modify(self):
2646         """ Testing ldb.modify_ldif() for nTSecurityDescriptor """
2647         user_name = "testdescriptoruser2"
2648         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2649         #
2650         # Delete user object and test modify_ldif() with SDDL security descriptor input
2651         # Add ACE to the original descriptor test
2652         #
2653         try:
2654             self.delete_force(self.ldb, user_dn)
2655             self.ldb.add_ldif("""
2656 dn: """ + user_dn + """
2657 objectclass: user
2658 sAMAccountName: """ + user_name)
2659             # Modify descriptor
2660             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2661             desc = res[0]["nTSecurityDescriptor"][0]
2662             desc = ndr_unpack(security.descriptor, desc)
2663             desc_sddl = desc.as_sddl(self.domain_sid)
2664             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
2665             mod = """
2666 dn: """ + user_dn + """
2667 changetype: modify
2668 replace: nTSecurityDescriptor
2669 nTSecurityDescriptor: """ + sddl
2670             self.ldb.modify_ldif(mod)
2671             # Read modified descriptor
2672             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2673             desc = res[0]["nTSecurityDescriptor"][0]
2674             desc = ndr_unpack(security.descriptor, desc)
2675             desc_sddl = desc.as_sddl(self.domain_sid)
2676             self.assertEqual(desc_sddl, sddl)
2677         finally:
2678             self.delete_force(self.ldb, user_dn)
2679         #
2680         # Test modify_ldif() with SDDL security descriptor input
2681         # New desctiptor test
2682         #
2683         try:
2684             self.ldb.add_ldif("""
2685 dn: """ + user_dn + """
2686 objectclass: user
2687 sAMAccountName: """ + user_name)
2688             # Modify descriptor
2689             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2690             mod = """
2691 dn: """ + user_dn + """
2692 changetype: modify
2693 replace: nTSecurityDescriptor
2694 nTSecurityDescriptor: """ + sddl
2695             self.ldb.modify_ldif(mod)
2696             # Read modified descriptor
2697             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2698             desc = res[0]["nTSecurityDescriptor"][0]
2699             desc = ndr_unpack(security.descriptor, desc)
2700             desc_sddl = desc.as_sddl(self.domain_sid)
2701             self.assertEqual(desc_sddl, sddl)
2702         finally:
2703             self.delete_force(self.ldb, user_dn)
2704         #
2705         # Test modify_ldif() with BASE64 security descriptor input
2706         # Add ACE to the original descriptor test
2707         #
2708         try:
2709             self.ldb.add_ldif("""
2710 dn: """ + user_dn + """
2711 objectclass: user
2712 sAMAccountName: """ + user_name)
2713             # Modify descriptor
2714             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2715             desc = res[0]["nTSecurityDescriptor"][0]
2716             desc = ndr_unpack(security.descriptor, desc)
2717             desc_sddl = desc.as_sddl(self.domain_sid)
2718             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
2719             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
2720             desc_base64 = base64.b64encode(ndr_pack(desc))
2721             mod = """
2722 dn: """ + user_dn + """
2723 changetype: modify
2724 replace: nTSecurityDescriptor
2725 nTSecurityDescriptor:: """ + desc_base64
2726             self.ldb.modify_ldif(mod)
2727             # Read modified descriptor
2728             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2729             desc = res[0]["nTSecurityDescriptor"][0]
2730             desc = ndr_unpack(security.descriptor, desc)
2731             desc_sddl = desc.as_sddl(self.domain_sid)
2732             self.assertEqual(desc_sddl, sddl)
2733         finally:
2734             self.delete_force(self.ldb, user_dn)
2735         #
2736         # Test modify_ldif() with BASE64 security descriptor input
2737         # New descriptor test
2738         #
2739         try:
2740             self.delete_force(self.ldb, user_dn)
2741             self.ldb.add_ldif("""
2742 dn: """ + user_dn + """
2743 objectclass: user
2744 sAMAccountName: """ + user_name)
2745             # Modify descriptor
2746             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2747             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
2748             desc_base64 = base64.b64encode(ndr_pack(desc))
2749             mod = """
2750 dn: """ + user_dn + """
2751 changetype: modify
2752 replace: nTSecurityDescriptor
2753 nTSecurityDescriptor:: """ + desc_base64
2754             self.ldb.modify_ldif(mod)
2755             # Read modified descriptor
2756             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2757             desc = res[0]["nTSecurityDescriptor"][0]
2758             desc = ndr_unpack(security.descriptor, desc)
2759             desc_sddl = desc.as_sddl(self.domain_sid)
2760             self.assertEqual(desc_sddl, sddl)
2761         finally:
2762             self.delete_force(self.ldb, user_dn)
2763
2764
2765 class BaseDnTests(unittest.TestCase):
2766
2767     def setUp(self):
2768         super(BaseDnTests, self).setUp()
2769         self.ldb = ldb
2770
2771     def test_rootdse_attrs(self):
2772         """Testing for all rootDSE attributes"""
2773         res = self.ldb.search(scope=SCOPE_BASE, attrs=[])
2774         self.assertEquals(len(res), 1)
2775
2776     def test_highestcommittedusn(self):
2777         """Testing for highestCommittedUSN"""
2778         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
2779         self.assertEquals(len(res), 1)
2780         self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
2781
2782     def test_netlogon(self):
2783         """Testing for netlogon via LDAP"""
2784         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
2785         self.assertEquals(len(res), 0)
2786
2787     def test_netlogon_highestcommitted_usn(self):
2788         """Testing for netlogon and highestCommittedUSN via LDAP"""
2789         res = self.ldb.search("", scope=SCOPE_BASE,
2790                 attrs=["netlogon", "highestCommittedUSN"])
2791         self.assertEquals(len(res), 0)
2792
2793     def test_namingContexts(self):
2794         """Testing for namingContexts in rootDSE"""
2795         res = self.ldb.search("", scope=SCOPE_BASE,
2796                 attrs=["namingContexts", "defaultNamingContext", "schemaNamingContext", "configurationNamingContext"])
2797         self.assertEquals(len(res), 1)
2798         
2799         ncs = set([])
2800         for nc in res[0]["namingContexts"]:
2801             self.assertTrue(nc not in ncs)
2802             ncs.add(nc)
2803
2804         self.assertTrue(res[0]["defaultNamingContext"][0] in ncs)
2805         self.assertTrue(res[0]["configurationNamingContext"][0] in ncs)
2806         self.assertTrue(res[0]["schemaNamingContext"][0] in ncs)
2807
2808
2809 if not "://" in host:
2810     if os.path.isfile(host):
2811         host = "tdb://%s" % host
2812     else:
2813         host = "ldap://%s" % host
2814
2815 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
2816 if not "tdb://" in host:
2817     gc_ldb = Ldb("%s:3268" % host, credentials=creds,
2818                  session_info=system_session(), lp=lp)
2819 else:
2820     gc_ldb = None
2821
2822 runner = SubunitTestRunner()
2823 rc = 0
2824 if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
2825     rc = 1
2826 if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
2827     rc = 1
2828 sys.exit(rc)