python: use '#!/usr/bin/env python' to cope with varying install locations
[kai/samba-autobuild/.git] / source4 / lib / ldb / 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
13 import samba.getopt as options
14
15 from samba.auth import system_session
16 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
17 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
18 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
19 from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
20 from ldb import ERR_NO_SUCH_ATTRIBUTE
21 from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
22 from ldb import ERR_NAMING_VIOLATION, ERR_CONSTRAINT_VIOLATION
23 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
24 from ldb import Message, MessageElement, Dn
25 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
26 from samba import Ldb
27 from samba import UF_NORMAL_ACCOUNT
28 from samba import UF_WORKSTATION_TRUST_ACCOUNT
29 from samba import UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE
30 from samba import ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST
31
32 from subunit.run import SubunitTestRunner
33 import unittest
34
35 from samba.ndr import ndr_pack, ndr_unpack
36 from samba.dcerpc import security
37
38 parser = optparse.OptionParser("ldap [options] <host>")
39 sambaopts = options.SambaOptions(parser)
40 parser.add_option_group(sambaopts)
41 parser.add_option_group(options.VersionOptions(parser))
42 # use command line creds if available
43 credopts = options.CredentialsOptions(parser)
44 parser.add_option_group(credopts)
45 opts, args = parser.parse_args()
46
47 if len(args) < 1:
48     parser.print_usage()
49     sys.exit(1)
50
51 host = args[0]
52
53 lp = sambaopts.get_loadparm()
54 creds = credopts.get_credentials(lp)
55
56 class BasicTests(unittest.TestCase):
57     def delete_force(self, ldb, dn):
58         try:
59             ldb.delete(dn)
60         except LdbError, (num, _):
61             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
62
63     def find_basedn(self, ldb):
64         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
65                          attrs=["defaultNamingContext"])
66         self.assertEquals(len(res), 1)
67         return res[0]["defaultNamingContext"][0]
68
69     def find_configurationdn(self, ldb):
70         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["configurationNamingContext"])
71         self.assertEquals(len(res), 1)
72         return res[0]["configurationNamingContext"][0]
73
74     def find_schemadn(self, ldb):
75         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
76         self.assertEquals(len(res), 1)
77         return res[0]["schemaNamingContext"][0]
78
79     def find_domain_sid(self):
80         res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
81         return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
82
83     def setUp(self):
84         self.ldb = ldb
85         self.gc_ldb = gc_ldb
86         self.base_dn = self.find_basedn(ldb)
87         self.configuration_dn = self.find_configurationdn(ldb)
88         self.schema_dn = self.find_schemadn(ldb)
89         self.domain_sid = self.find_domain_sid()
90
91         print "baseDN: %s\n" % self.base_dn
92
93         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
94         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
95         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
96         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
97         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
98         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
99         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
100         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
101         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
102         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
103         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
104         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
105         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn)
106         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
107         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
108         self.delete_force(self.ldb, "cn=parentguidtest,cn=users," + self.base_dn)
109         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
110         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
111         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
112         self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
113         self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
114
115     def test_system_only(self):
116         """Test systemOnly objects"""
117         print "Test systemOnly objects"""
118
119         try:
120             self.ldb.add({
121                 "dn": "cn=ldaptestobject," + self.base_dn,
122                 "objectclass": "configuration"})
123             self.fail()
124         except LdbError, (num, _):
125             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
126
127         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
128
129     def test_invalid_parent(self):
130         """Test adding an object with invalid parent"""
131         print "Test adding an object with invalid parent"""
132
133         try:
134             self.ldb.add({
135                 "dn": "cn=ldaptestgroup,cn=thisdoesnotexist123,"
136                    + self.base_dn,
137                 "objectclass": "group"})
138             self.fail()
139         except LdbError, (num, _):
140             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
141
142         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=thisdoesnotexist123,"
143           + self.base_dn)
144
145         try:
146             self.ldb.add({
147                 "dn": "ou=testou,cn=users," + self.base_dn,
148                 "objectclass": "organizationalUnit"})
149             self.fail()
150         except LdbError, (num, _):
151             self.assertEquals(num, ERR_NAMING_VIOLATION)
152
153         self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
154
155     def test_invalid_attribute(self):
156         """Test adding invalid attributes (not in schema)"""
157         print "Test adding invalid attributes (not in schema)"""
158
159         try:
160             self.ldb.add({
161                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
162                 "objectclass": "group",
163                 "thisdoesnotexist": "x"})
164             self.fail()
165         except LdbError, (num, _):
166             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
167
168         self.ldb.add({
169              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
170              "objectclass": "group"})
171
172         m = Message()
173         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
174         m["thisdoesnotexist"] = MessageElement("x", FLAG_MOD_REPLACE,
175           "thisdoesnotexist")
176         try:
177             ldb.modify(m)
178             self.fail()
179         except LdbError, (num, _):
180             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
181
182         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
183
184     def test_single_valued_attributes(self):
185         """Test single-valued attributes"""
186         print "Test single-valued attributes"""
187
188         try:
189             self.ldb.add({
190                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
191                 "objectclass": "group",
192                 "sAMAccountName": ["nam1", "nam2"]})
193             self.fail()
194         except LdbError, (num, _):
195             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
196
197         self.ldb.add({
198              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
199              "objectclass": "group"})
200
201         m = Message()
202         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
203         m["sAMAccountName"] = MessageElement(["nam1","nam2"], FLAG_MOD_REPLACE,
204           "sAMAccountName")
205         try:
206             ldb.modify(m)
207             self.fail()
208         except LdbError, (num, _):
209             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
210
211         m = Message()
212         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
213         m["sAMAccountName"] = MessageElement("testgroupXX", FLAG_MOD_REPLACE,
214           "sAMAccountName")
215         ldb.modify(m)
216
217         m = Message()
218         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
219         m["sAMAccountName"] = MessageElement("testgroupXX2", FLAG_MOD_ADD,
220           "sAMAccountName")
221         try:
222             ldb.modify(m)
223             self.fail()
224         except LdbError, (num, _):
225             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
226
227         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
228
229     def test_multi_valued_attributes(self):
230         """Test multi-valued attributes"""
231         print "Test multi-valued attributes"""
232
233 # TODO: In this test I added some special tests where I got very unusual
234 # results back from a real AD. s4 doesn't match them and I've no idea how to
235 # implement those error cases (maybe there exists a special trigger for
236 # "description" attributes which handle them)
237
238         self.ldb.add({
239             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
240             "description": "desc2",
241             "objectclass": "group",
242             "description": "desc1"})
243
244         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
245
246         self.ldb.add({
247             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
248             "objectclass": "group",
249             "description": ["desc1", "desc2"]})
250
251 #        m = Message()
252 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
253 #        m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
254 #          "description")
255 #        try:
256 #            ldb.modify(m)
257 #            self.fail()
258 #        except LdbError, (num, _):
259 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
260
261         m = Message()
262         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
263         m["description"] = MessageElement("desc1", FLAG_MOD_REPLACE,
264           "description")
265         ldb.modify(m)
266
267 #        m = Message()
268 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
269 #        m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
270 #          "description")
271 #        try:
272 #            ldb.modify(m)
273 #            self.fail()
274 #        except LdbError, (num, _):
275 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
276
277         m = Message()
278         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
279         m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_DELETE,
280           "description")
281         try:
282             ldb.modify(m)
283             self.fail()
284         except LdbError, (num, _):
285             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
286
287         m = Message()
288         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
289         m["description"] = MessageElement("desc1", FLAG_MOD_DELETE,
290           "description")
291         ldb.modify(m)
292
293 #        m = Message()
294 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
295 #        m["description"] = MessageElement(["desc1","desc2"], FLAG_MOD_REPLACE,
296 #          "description")
297 #        try:
298 #            ldb.modify(m)
299 #            self.fail()
300 #        except LdbError, (num, _):
301 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
302
303 #        m = Message()
304 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
305 #        m["description"] = MessageElement(["desc3", "desc4"], FLAG_MOD_ADD,
306 #          "description")
307 #        try:
308 #            ldb.modify(m)
309 #            self.fail()
310 #        except LdbError, (num, _):
311 #            self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
312
313         m = Message()
314         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
315         m["description"] = MessageElement("desc3", FLAG_MOD_ADD,
316           "description")
317         ldb.modify(m)
318
319         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
320
321     def test_empty_messages(self):
322         """Test empty messages"""
323         print "Test empty messages"""
324
325         m = Message()
326         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
327
328         try:
329             ldb.add(m)
330             self.fail()
331         except LdbError, (num, _):
332             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
333
334         try:
335             ldb.modify(m)
336             self.fail()
337         except LdbError, (num, _):
338             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
339
340         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
341
342     def test_empty_attributes(self):
343         """Test empty attributes"""
344         print "Test empty attributes"""
345
346         m = Message()
347         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
348         m["objectClass"] = MessageElement("group", FLAG_MOD_ADD, "objectClass")
349         m["description"] = MessageElement([], FLAG_MOD_ADD, "description")
350
351         try:
352             ldb.add(m)
353             self.fail()
354         except LdbError, (num, _):
355             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
356
357         self.ldb.add({
358             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
359             "objectclass": "group"})
360
361         m = Message()
362         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
363         m["description"] = MessageElement([], FLAG_MOD_ADD, "description")
364
365         try:
366             ldb.modify(m)
367             self.fail()
368         except LdbError, (num, _):
369             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
370
371         m = Message()
372         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
373         m["description"] = MessageElement([], FLAG_MOD_REPLACE, "description")
374         ldb.modify(m)
375
376         m = Message()
377         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
378         m["description"] = MessageElement([], FLAG_MOD_DELETE, "description")
379         try:
380             ldb.modify(m)
381             self.fail()
382         except LdbError, (num, _):
383             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
384
385         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
386
387     def test_distinguished_name(self):
388         """Tests the 'distinguishedName' attribute"""
389         print "Tests the 'distinguishedName' attribute"""
390
391         self.ldb.add({
392              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
393              "objectclass": "group"})
394
395         m = Message()
396         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
397         m["distinguishedName"] = MessageElement(
398           "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_ADD,
399           "distinguishedName")
400
401         try:
402             ldb.modify(m)
403             self.fail()
404         except LdbError, (num, _):
405             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
406
407         m = Message()
408         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
409         m["distinguishedName"] = MessageElement(
410           "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_REPLACE,
411           "distinguishedName")
412
413         try:
414             ldb.modify(m)
415             self.fail()
416         except LdbError, (num, _):
417             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
418
419         m = Message()
420         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
421         m["distinguishedName"] = MessageElement(
422           "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_DELETE,
423           "distinguishedName")
424
425         try:
426             ldb.modify(m)
427             self.fail()
428         except LdbError, (num, _):
429             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
430
431         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
432
433     def test_rdn_name(self):
434         """Tests the RDN"""
435         print "Tests the RDN"""
436
437         try:
438             self.ldb.add({
439                  "dn": "description=xyz,cn=users," + self.base_dn,
440                  "objectclass": "group"})
441             self.fail()
442         except LdbError, (num, _):
443             self.assertEquals(num, ERR_NAMING_VIOLATION)
444
445         self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
446
447         self.ldb.add({
448              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
449              "objectclass": "group"})
450
451         m = Message()
452         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
453         m["name"] = MessageElement("cn=ldaptestuser", FLAG_MOD_REPLACE,
454           "name")
455
456         try:
457             ldb.modify(m)
458             self.fail()
459         except LdbError, (num, _):
460             self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN)
461
462         m = Message()
463         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
464         m["cn"] = MessageElement("ldaptestuser",
465           FLAG_MOD_REPLACE, "cn")
466
467         try:
468             ldb.modify(m)
469             self.fail()
470         except LdbError, (num, _):
471             self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN)
472
473         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
474
475
476         # this test needs to be disabled until we really understand
477         # what the rDN length constraints are
478     def DISABLED_test_largeRDN(self):
479         """Testing large rDN (limit 64 characters)"""
480         rdn = "CN=a012345678901234567890123456789012345678901234567890123456789012";
481         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
482         ldif = """
483 dn: %s,%s""" % (rdn,self.base_dn) + """
484 objectClass: container
485 """
486         self.ldb.add_ldif(ldif)
487         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
488
489         rdn = "CN=a0123456789012345678901234567890123456789012345678901234567890120";
490         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
491         try:
492             ldif = """
493 dn: %s,%s""" % (rdn,self.base_dn) + """
494 objectClass: container
495 """
496             self.ldb.add_ldif(ldif)
497             self.fail()
498         except LdbError, (num, _):
499             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
500         self.delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
501
502     def test_rename(self):
503         """Tests the rename operation"""
504         print "Tests the rename operations"""
505
506         self.ldb.add({
507              "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
508              "objectclass": ["user", "person"] })
509
510         ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
511         ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
512         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestUSER3,cn=users," + self.base_dn)
513         try:
514             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, ",cn=users," + self.base_dn)
515             self.fail()
516         except LdbError, (num, _):
517             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
518
519         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
520
521     def test_rename_twice(self):
522         """Tests the rename operation twice - this corresponds to a past bug"""
523         print "Tests the rename twice operation"""
524
525         self.ldb.add({
526              "dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
527              "objectclass": ["user", "person"] })
528
529         ldb.rename("cn=ldaptestuser5,cn=users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
530         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
531         self.ldb.add({
532              "dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
533              "objectclass": ["user", "person"] })
534         ldb.rename("cn=ldaptestuser5,cn=Users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
535         res = ldb.search(expression="cn=ldaptestuser5")
536         print "Found %u records" % len(res)
537         self.assertEquals(len(res), 1, "Wrong number of hits for cn=ldaptestuser5")
538         res = ldb.search(expression="(&(cn=ldaptestuser5)(objectclass=user))")
539         print "Found %u records" % len(res)
540         self.assertEquals(len(res), 1, "Wrong number of hits for (&(cn=ldaptestuser5)(objectclass=user))")
541         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
542
543     def test_parentGUID(self):
544         """Test parentGUID behaviour"""
545         print "Testing parentGUID behaviour\n"
546
547         # TODO: This seems to fail on Windows Server. Hidden attribute?
548
549         self.ldb.add({
550             "dn": "cn=parentguidtest,cn=users," + self.base_dn,
551             "objectclass":"user",
552             "samaccountname":"parentguidtest"});
553         res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE,
554                           attrs=["parentGUID", "samaccountname"]);
555         res2 = ldb.search(base="cn=users," + self.base_dn,scope=SCOPE_BASE,
556                           attrs=["objectGUID"]);
557         res3 = ldb.search(base=self.base_dn, scope=SCOPE_BASE,
558                           attrs=["parentGUID"]);
559
560         """Check if the parentGUID is valid """
561         self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]);
562
563         """Check if it returns nothing when there is no parent object"""
564         has_parentGUID = False
565         for key in res3[0].keys():
566             if key == "parentGUID":
567                 has_parentGUID = True
568                 break
569         self.assertFalse(has_parentGUID);
570
571         """Ensures that if you look for another object attribute after the constructed
572             parentGUID, it will return correctly"""
573         has_another_attribute = False
574         for key in res1[0].keys():
575             if key == "sAMAccountName":
576                 has_another_attribute = True
577                 break
578         self.assertTrue(has_another_attribute)
579         self.assertTrue(len(res1[0]["samaccountname"]) == 1)
580         self.assertEquals(res1[0]["samaccountname"][0], "parentguidtest");
581
582         print "Testing parentGUID behaviour on rename\n"
583
584         self.ldb.add({
585             "dn": "cn=testotherusers," + self.base_dn,
586             "objectclass":"container"});
587         res1 = ldb.search(base="cn=testotherusers," + self.base_dn,scope=SCOPE_BASE,
588                           attrs=["objectGUID"]);
589         ldb.rename("cn=parentguidtest,cn=users," + self.base_dn,
590                    "cn=parentguidtest,cn=testotherusers," + self.base_dn);
591         res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn,
592                           scope=SCOPE_BASE,
593                           attrs=["parentGUID"]);
594         self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]);
595
596         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
597         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
598
599     def test_groupType_int32(self):
600         """Test groupType (int32) behaviour (should appear to be casted to a 32 bit signed integer before comparsion)"""
601         print "Testing groupType (int32) behaviour\n"
602
603         res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
604                           attrs=["groupType"], expression="groupType=2147483653");
605
606         res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
607                           attrs=["groupType"], expression="groupType=-2147483643");
608
609         self.assertEquals(len(res1), len(res2))
610
611         self.assertTrue(res1.count > 0)
612
613         self.assertEquals(res1[0]["groupType"][0], "-2147483643")
614
615     def test_groups(self):
616         """This tests the group behaviour (setting, changing) of a user account"""
617         print "Testing group behaviour\n"
618
619         ldb.add({
620             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
621             "objectclass": "group"})
622
623         ldb.add({
624             "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
625             "objectclass": "group"})
626
627         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
628                           scope=SCOPE_BASE, attrs=["objectSID"])
629         self.assertTrue(len(res1) == 1)
630         group_rid_1 = security.dom_sid(ldb.schema_format_value("objectSID",
631           res1[0]["objectSID"][0])).split()[1]
632
633         res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
634                           scope=SCOPE_BASE, attrs=["objectSID"])
635         self.assertTrue(len(res1) == 1)
636         group_rid_2 = security.dom_sid(ldb.schema_format_value("objectSID",
637           res1[0]["objectSID"][0])).split()[1]
638
639         # Try to create a user with an invalid primary group
640         try:
641             ldb.add({
642                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
643                 "objectclass": ["user", "person"],
644                 "primaryGroupID": "0"})
645             self.fail()
646         except LdbError, (num, _):
647             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
648         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
649
650         # Try to Create a user with a valid primary group
651 # TODO Some more investigation needed here
652 #        try:
653 #            ldb.add({
654 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
655 #                "objectclass": ["user", "person"],
656 #                "primaryGroupID": str(group_rid_1)})
657 #            self.fail()
658 #        except LdbError, (num, _):
659 #            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
660 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
661
662         ldb.add({
663             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
664             "objectclass": ["user", "person"]})
665
666         # Try to add invalid primary group
667         m = Message()
668         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
669         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
670           "primaryGroupID")
671         try:
672             ldb.modify(m)
673             self.fail()
674         except LdbError, (num, _):
675             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
676
677         # Try to make group 1 primary - should be denied since it is not yet
678         # secondary
679         m = Message()
680         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
681         m["primaryGroupID"] = MessageElement(str(group_rid_1),
682           FLAG_MOD_REPLACE, "primaryGroupID")
683         try:
684             ldb.modify(m)
685             self.fail()
686         except LdbError, (num, _):
687             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
688
689         # Make group 1 secondary
690         m = Message()
691         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
692         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
693                                      FLAG_MOD_REPLACE, "member")
694         ldb.modify(m)
695
696         # Make group 1 primary
697         m = Message()
698         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
699         m["primaryGroupID"] = MessageElement(str(group_rid_1),
700           FLAG_MOD_REPLACE, "primaryGroupID")
701         ldb.modify(m)
702
703         # Try to delete group 1 - should be denied
704         try:
705             ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
706             self.fail()
707         except LdbError, (num, _):
708             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
709
710         # Try to add group 1 also as secondary - should be denied
711         m = Message()
712         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
713         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
714                                      FLAG_MOD_ADD, "member")
715         try:
716             ldb.modify(m)
717             self.fail()
718         except LdbError, (num, _):
719             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
720
721         # Try to add invalid member to group 1 - should be denied
722         m = Message()
723         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
724         m["member"] = MessageElement(
725           "cn=ldaptestuser3,cn=users," + self.base_dn,
726           FLAG_MOD_ADD, "member")
727         try:
728             ldb.modify(m)
729             self.fail()
730         except LdbError, (num, _):
731             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
732
733         # Make group 2 secondary
734         m = Message()
735         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
736         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
737                                      FLAG_MOD_ADD, "member")
738         ldb.modify(m)
739
740         # Swap the groups
741         m = Message()
742         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
743         m["primaryGroupID"] = MessageElement(str(group_rid_2),
744           FLAG_MOD_REPLACE, "primaryGroupID")
745         ldb.modify(m)
746
747         # Old primary group should contain a "member" attribute for the user,
748         # the new shouldn't contain anymore one
749         res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
750                           scope=SCOPE_BASE, attrs=["member"])
751         self.assertTrue(len(res1) == 1)
752         self.assertTrue(len(res1[0]["member"]) == 1)
753         self.assertEquals(res1[0]["member"][0].lower(),
754           ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
755
756         res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
757                           scope=SCOPE_BASE, attrs=["member"])
758         self.assertTrue(len(res1) == 1)
759         self.assertFalse("member" in res1[0])
760
761         # Also this should be denied
762         try:
763             ldb.add({
764               "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
765               "objectclass": ["user", "person"],
766               "primaryGroupID": "0"})
767             self.fail()
768         except LdbError, (num, _):
769             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
770
771         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
772         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
773         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
774
775     def test_primary_group_token_constructed(self):
776         """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
777         print "Testing primary group token behaviour and other constructed attributes\n"
778
779         try:
780             ldb.add({
781                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
782                 "objectclass": "group",
783                 "primaryGroupToken": "100"})
784             self.fail()
785         except LdbError, (num, _):
786             self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
787         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
788
789         ldb.add({
790             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
791             "objectclass": ["user", "person"]})
792
793         ldb.add({
794             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
795             "objectclass": "group"})
796
797         # Testing for one invalid, and one valid operational attribute, but also the things they are built from
798         res1 = ldb.search(self.base_dn,
799                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
800         self.assertTrue(len(res1) == 1)
801         self.assertFalse("primaryGroupToken" in res1[0])
802         self.assertTrue("canonicalName" in res1[0])
803         self.assertTrue("objectClass" in res1[0])
804         self.assertTrue("objectSid" in res1[0])
805
806         res1 = ldb.search(self.base_dn,
807                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
808         self.assertTrue(len(res1) == 1)
809         self.assertFalse("primaryGroupToken" in res1[0])
810         self.assertFalse("objectSid" in res1[0])
811         self.assertFalse("objectClass" in res1[0])
812         self.assertTrue("canonicalName" in res1[0])
813
814         res1 = ldb.search("cn=users,"+self.base_dn,
815                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
816         self.assertTrue(len(res1) == 1)
817         self.assertFalse("primaryGroupToken" in res1[0])
818
819         res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
820                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
821         self.assertTrue(len(res1) == 1)
822         self.assertFalse("primaryGroupToken" in res1[0])
823
824         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
825                           scope=SCOPE_BASE)
826         self.assertTrue(len(res1) == 1)
827         self.assertFalse("primaryGroupToken" in res1[0])
828
829         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
830                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
831         self.assertTrue(len(res1) == 1)
832         primary_group_token = int(res1[0]["primaryGroupToken"][0])
833
834         rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
835         self.assertEquals(primary_group_token, rid)
836
837         m = Message()
838         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
839         m["primaryGroupToken"] = "100"
840         try:
841             ldb.modify(m)
842             self.fail()
843         except LdbError, (num, _):
844             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
845
846         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
847         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
848
849     def test_tokenGroups(self):
850         """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
851         print "Testing tokenGroups behaviour\n"
852
853         # The domain object shouldn't contain any "tokenGroups" entry
854         res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
855         self.assertTrue(len(res) == 1)
856         self.assertFalse("tokenGroups" in res[0])
857
858         # The domain administrator should contain "tokenGroups" entries
859         # (the exact number depends on the domain/forest function level and the
860         # DC software versions)
861         res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
862                          scope=SCOPE_BASE, attrs=["tokenGroups"])
863         self.assertTrue(len(res) == 1)
864         self.assertTrue("tokenGroups" in res[0])
865
866         ldb.add({
867             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
868             "objectclass": ["user", "person"]})
869
870         # This testuser should contain at least two "tokenGroups" entries
871         # (exactly two on an unmodified "Domain Users" and "Users" group)
872         res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
873                          scope=SCOPE_BASE, attrs=["tokenGroups"])
874         self.assertTrue(len(res) == 1)
875         self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
876
877         # one entry which we need to find should point to domains "Domain Users"
878         # group and another entry should point to the builtin "Users"group
879         domain_users_group_found = False
880         users_group_found = False
881         for sid in res[0]["tokenGroups"]:
882             rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
883             if rid == 513:
884                 domain_users_group_found = True
885             if rid == 545:
886                 users_group_found = True
887
888         self.assertTrue(domain_users_group_found)
889         self.assertTrue(users_group_found)
890
891         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
892
893     def test_wkguid(self):
894         """Test Well known GUID behaviours (including DN+Binary)"""
895         print "Test Well known GUID behaviours (including DN+Binary)"""
896
897         res = self.ldb.search(base=("<WKGUID=ab1d30f3768811d1aded00c04fd8d5cd,%s>" % self.base_dn), scope=SCOPE_BASE, attrs=[])
898         self.assertEquals(len(res), 1)
899         
900         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd:%s" % res[0].dn))
901         self.assertEquals(len(res2), 1)
902
903         # Prove that the matching rule is over the whole DN+Binary
904         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd"))
905         self.assertEquals(len(res2), 0)
906         # Prove that the matching rule is over the whole DN+Binary
907         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=%s") % res[0].dn)
908         self.assertEquals(len(res2), 0)
909
910     def test_subschemasubentry(self):
911         """Test subSchemaSubEntry appears when requested, but not when not requested"""
912         print "Test subSchemaSubEntry"""
913
914         res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["subSchemaSubEntry"])
915         self.assertEquals(len(res), 1)
916         self.assertEquals(res[0]["subSchemaSubEntry"][0], "CN=Aggregate,"+self.schema_dn)
917
918         res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["*"])
919         self.assertEquals(len(res), 1)
920         self.assertTrue("subScheamSubEntry" not in res[0])
921
922     def test_all(self):
923         """Basic tests"""
924
925         print "Testing user add"
926
927         ldb.add({
928             "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
929             "objectclass": ["user", "person"],
930             "cN": "LDAPtestUSER",
931             "givenname": "ldap",
932             "sn": "testy"})
933
934         ldb.add({
935             "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
936             "objectclass": "group",
937             "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
938
939         ldb.add({
940             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
941             "objectclass": "computer",
942             "cN": "LDAPtestCOMPUTER"})
943
944         ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
945             "objectClass": "computer",
946             "cn": "LDAPtest2COMPUTER",
947             "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT),
948             "displayname": "ldap testy"})
949
950         try:
951             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
952                      "objectClass": "computer",
953                      "cn": "LDAPtest2COMPUTER"
954                      })
955             self.fail()
956         except LdbError, (num, _):
957             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
958
959         try:
960             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
961                      "objectClass": "computer",
962                      "cn": "ldaptestcomputer3",
963                      "sAMAccountType": str(ATYPE_NORMAL_ACCOUNT)
964                 })
965             self.fail()
966         except LdbError, (num, _):
967             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
968
969         ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
970                  "objectClass": "computer",
971                  "cn": "LDAPtestCOMPUTER3"
972                  })
973
974         print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
975         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
976         self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
977
978         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn));
979         self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3");
980         self.assertEquals(res[0]["name"][0], "ldaptestcomputer3");
981         self.assertEquals(res[0]["objectClass"][0], "top");
982         self.assertEquals(res[0]["objectClass"][1], "person");
983         self.assertEquals(res[0]["objectClass"][2], "organizationalPerson");
984         self.assertEquals(res[0]["objectClass"][3], "user");
985         self.assertEquals(res[0]["objectClass"][4], "computer");
986         self.assertTrue("objectGUID" in res[0])
987         self.assertTrue("whenCreated" in res[0])
988         self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
989         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
990         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT);
991         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE);
992
993         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
994
995         print "Testing attribute or value exists behaviour"
996         try:
997             ldb.modify_ldif("""
998 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
999 changetype: modify
1000 replace: servicePrincipalName
1001 servicePrincipalName: host/ldaptest2computer
1002 servicePrincipalName: host/ldaptest2computer
1003 servicePrincipalName: cifs/ldaptest2computer
1004 """)
1005             self.fail()
1006         except LdbError, (num, msg):
1007             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1008
1009         ldb.modify_ldif("""
1010 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1011 changetype: modify
1012 replace: servicePrincipalName
1013 servicePrincipalName: host/ldaptest2computer
1014 servicePrincipalName: cifs/ldaptest2computer
1015 """)
1016         try:
1017             ldb.modify_ldif("""
1018 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1019 changetype: modify
1020 add: servicePrincipalName
1021 servicePrincipalName: host/ldaptest2computer
1022 """)
1023             self.fail()
1024         except LdbError, (num, msg):
1025             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1026
1027         print "Testing ranged results"
1028         ldb.modify_ldif("""
1029 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1030 changetype: modify
1031 replace: servicePrincipalName
1032 """)
1033
1034         ldb.modify_ldif("""
1035 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1036 changetype: modify
1037 add: servicePrincipalName
1038 servicePrincipalName: host/ldaptest2computer0
1039 servicePrincipalName: host/ldaptest2computer1
1040 servicePrincipalName: host/ldaptest2computer2
1041 servicePrincipalName: host/ldaptest2computer3
1042 servicePrincipalName: host/ldaptest2computer4
1043 servicePrincipalName: host/ldaptest2computer5
1044 servicePrincipalName: host/ldaptest2computer6
1045 servicePrincipalName: host/ldaptest2computer7
1046 servicePrincipalName: host/ldaptest2computer8
1047 servicePrincipalName: host/ldaptest2computer9
1048 servicePrincipalName: host/ldaptest2computer10
1049 servicePrincipalName: host/ldaptest2computer11
1050 servicePrincipalName: host/ldaptest2computer12
1051 servicePrincipalName: host/ldaptest2computer13
1052 servicePrincipalName: host/ldaptest2computer14
1053 servicePrincipalName: host/ldaptest2computer15
1054 servicePrincipalName: host/ldaptest2computer16
1055 servicePrincipalName: host/ldaptest2computer17
1056 servicePrincipalName: host/ldaptest2computer18
1057 servicePrincipalName: host/ldaptest2computer19
1058 servicePrincipalName: host/ldaptest2computer20
1059 servicePrincipalName: host/ldaptest2computer21
1060 servicePrincipalName: host/ldaptest2computer22
1061 servicePrincipalName: host/ldaptest2computer23
1062 servicePrincipalName: host/ldaptest2computer24
1063 servicePrincipalName: host/ldaptest2computer25
1064 servicePrincipalName: host/ldaptest2computer26
1065 servicePrincipalName: host/ldaptest2computer27
1066 servicePrincipalName: host/ldaptest2computer28
1067 servicePrincipalName: host/ldaptest2computer29
1068 """)
1069
1070         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
1071                          attrs=["servicePrincipalName;range=0-*"])
1072         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1073         #print len(res[0]["servicePrincipalName;range=0-*"])
1074         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1075
1076         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
1077         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1078             # print res[0]["servicePrincipalName;range=0-19"].length
1079         self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
1080
1081
1082         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
1083         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1084         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1085
1086         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
1087         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1088         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1089
1090         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
1091         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1092         self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
1093
1094
1095         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
1096         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1097         self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
1098         # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
1099
1100         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
1101         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1102         self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19)
1103             # print res[0]["servicePrincipalName;range=11-*"][18]
1104             # print pos_11
1105             # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
1106
1107         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
1108         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1109         self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5)
1110             # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
1111
1112         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
1113         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1114             # print res[0]["servicePrincipalName"][18]
1115             # print pos_11
1116         self.assertEquals(len(res[0]["servicePrincipalName"]), 30)
1117             # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11)
1118
1119         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1120         ldb.add({
1121             "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
1122             "objectClass": ["person", "user"],
1123             "cn": "LDAPtestUSER2",
1124             "givenname": "testy",
1125             "sn": "ldap user2"})
1126
1127         print "Testing Ambigious Name Resolution"
1128         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
1129         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
1130         self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
1131
1132         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1133         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1134         self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
1135
1136         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
1137         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
1138         self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
1139
1140         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
1141         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
1142         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
1143
1144         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1145         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1146         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1147
1148         # Testing ldb.search for (&(anr=testy)(objectClass=user))
1149         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
1150         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
1151
1152         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1153         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1154         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
1155
1156         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1157 # this test disabled for the moment, as anr with == tests are not understood
1158 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1159 #        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
1160
1161 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1162 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1163 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1164
1165         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1166 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1167 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
1168
1169 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1170 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1171 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1172
1173         # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
1174         res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
1175         self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
1176
1177         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1178         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1179         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1180
1181         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
1182 #        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
1183 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
1184
1185         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1186         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1187         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1188
1189         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
1190 #        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
1191 #        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
1192
1193         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1194         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1195         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1196
1197         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
1198 #        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
1199 #        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
1200
1201         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
1202         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
1203         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
1204
1205         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
1206 #        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
1207 #        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
1208
1209         print "Testing Renames"
1210
1211         attrs = ["objectGUID", "objectSid"]
1212         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
1213         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
1214         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
1215
1216         # Check rename works with extended/alternate DN forms
1217         ldb.rename("<SID=" + ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0]) + ">" , "cn=ldaptestUSER3,cn=users," + self.base_dn)
1218
1219         print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))"
1220         res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
1221         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
1222
1223         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1224         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1225         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1226
1227         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
1228         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
1229         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
1230
1231         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1232         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1233         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1234
1235         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
1236         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
1237         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
1238
1239         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1240         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1241         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1242
1243         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
1244         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
1245         self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
1246
1247         # This is a Samba special, and does not exist in real AD
1248         #    print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1249         #    res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1250         #    if (res.error != 0 || len(res) != 1) {
1251         #        print "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1252         #        self.assertEquals(len(res), 1)
1253         #    }
1254         #    self.assertEquals(res[0].dn, ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1255         #    self.assertEquals(res[0].cn, "ldaptestUSER3")
1256         #    self.assertEquals(res[0].name, "ldaptestUSER3")
1257
1258         print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1259         res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1260         self.assertEquals(len(res), 1, "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1261         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1262         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1263         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1264
1265         # ensure we cannot add it again
1266         try:
1267             ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
1268                       "objectClass": ["person", "user"],
1269                       "cn": "LDAPtestUSER3"})
1270             self.fail()
1271         except LdbError, (num, _):
1272             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1273
1274         # rename back
1275         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
1276
1277         # ensure we cannot rename it twice
1278         try:
1279             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
1280                        "cn=ldaptestuser2,cn=users," + self.base_dn)
1281             self.fail()
1282         except LdbError, (num, _):
1283             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1284
1285         # ensure can now use that name
1286         ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
1287                       "objectClass": ["person", "user"],
1288                       "cn": "LDAPtestUSER3"})
1289
1290         # ensure we now cannot rename
1291         try:
1292             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
1293             self.fail()
1294         except LdbError, (num, _):
1295             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1296         try:
1297             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
1298             self.fail()
1299         except LdbError, (num, _):
1300             self.assertTrue(num in (71, 64))
1301
1302         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
1303
1304         ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
1305
1306         self.delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1307
1308         ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1309
1310         print "Testing subtree renames"
1311
1312         ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
1313                  "objectClass": "container"})
1314
1315         ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
1316                  "objectClass": ["person", "user"],
1317                  "cn": "LDAPtestUSER4"})
1318
1319         ldb.modify_ldif("""
1320 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1321 changetype: modify
1322 add: member
1323 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
1324 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
1325 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
1326 """)
1327
1328         print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
1329         ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
1330
1331         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))"
1332         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
1333         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
1334
1335         print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
1336         try:
1337             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1338                     expression="(&(cn=ldaptestuser4)(objectClass=user))",
1339                     scope=SCOPE_SUBTREE)
1340             self.fail(res)
1341         except LdbError, (num, _):
1342             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1343
1344         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
1345         try:
1346             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1347                     expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
1348             self.fail()
1349         except LdbError, (num, _):
1350             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1351
1352         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
1353         res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
1354         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
1355
1356         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
1357         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1358
1359         time.sleep(4)
1360
1361         print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
1362         res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
1363         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?")
1364
1365         print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
1366         try:
1367             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
1368             self.fail()
1369         except LdbError, (num, _):
1370             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1371
1372         print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
1373         try:
1374             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
1375             self.fail()
1376         except LdbError, (num, _):
1377             self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER))
1378
1379         print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
1380         try:
1381             ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
1382             self.fail()
1383         except LdbError, (num, _):
1384             self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
1385
1386         print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
1387         res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
1388         self.assertEquals(len(res), 1)
1389         res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
1390         self.assertEquals(len(res), 0)
1391
1392         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
1393         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
1394         # FIXME: self.assertEquals(len(res), 0)
1395
1396         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
1397         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
1398         # FIXME: self.assertEquals(len(res), 0)
1399
1400         print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
1401         ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
1402         print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
1403         ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
1404
1405         ldb.add({"dn": "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
1406
1407         ldb.add({"dn": "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
1408
1409         print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
1410         res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
1411         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1412
1413         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1414         self.assertEquals(str(res[0]["cn"]), "ldaptestuser")
1415         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1416         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user"]))
1417         self.assertTrue("objectGUID" in res[0])
1418         self.assertTrue("whenCreated" in res[0])
1419         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
1420         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1421         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1422         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1423         self.assertEquals(len(res[0]["memberOf"]), 1)
1424
1425         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
1426         res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1427         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1428
1429         self.assertEquals(res[0].dn, res2[0].dn)
1430
1431         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
1432         res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1433         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
1434
1435         self.assertEquals(res[0].dn, res3[0].dn)
1436
1437         if gc_ldb is not None:
1438             print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
1439             res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1440             self.assertEquals(len(res3gc), 1)
1441
1442             self.assertEquals(res[0].dn, res3gc[0].dn)
1443
1444         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
1445
1446         if gc_ldb is not None:
1447             res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
1448             self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
1449
1450             self.assertEquals(res[0].dn, res3control[0].dn)
1451
1452         ldb.delete(res[0].dn)
1453
1454         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
1455         res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
1456         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1457
1458         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
1459         self.assertEquals(str(res[0]["cn"]), "ldaptestcomputer")
1460         self.assertEquals(str(res[0]["name"]), "ldaptestcomputer")
1461         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user", "computer"]))
1462         self.assertTrue("objectGUID" in res[0])
1463         self.assertTrue("whenCreated" in res[0])
1464         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
1465         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
1466         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1467         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1468         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1469         self.assertEquals(len(res[0]["memberOf"]), 1)
1470
1471         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
1472         res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1473         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1474
1475         self.assertEquals(res[0].dn, res2[0].dn)
1476
1477         if gc_ldb is not None:
1478             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
1479             res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1480             self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
1481
1482             self.assertEquals(res[0].dn, res2gc[0].dn)
1483
1484         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
1485         res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1486         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1487
1488         self.assertEquals(res[0].dn, res3[0].dn)
1489
1490         if gc_ldb is not None:
1491             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
1492             res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1493             self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
1494
1495             self.assertEquals(res[0].dn, res3gc[0].dn)
1496
1497         print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
1498         res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1499         self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1500
1501         self.assertEquals(res[0].dn, res4[0].dn)
1502
1503         print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
1504         res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1505         self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1506
1507         self.assertEquals(res[0].dn, res5[0].dn)
1508
1509         print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
1510         res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
1511         self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
1512
1513         self.assertEquals(res[0].dn, res6[0].dn)
1514
1515         ldb.delete("<GUID=" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + ">")
1516
1517         print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
1518         res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
1519         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
1520
1521         self.assertEquals(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn)
1522         self.assertEquals(str(res[0]["cn"]), "ldaptest2computer")
1523         self.assertEquals(str(res[0]["name"]), "ldaptest2computer")
1524         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user", "computer"])
1525         self.assertTrue("objectGUID" in res[0])
1526         self.assertTrue("whenCreated" in res[0])
1527         self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
1528         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
1529         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT)
1530
1531         ldb.delete("<SID=" + ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + ">")
1532
1533         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"]
1534         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
1535         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
1536         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
1537
1538         self.assertEquals(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1539         self.assertEquals(str(res_user[0]["cn"]), "ldaptestuser2")
1540         self.assertEquals(str(res_user[0]["name"]), "ldaptestuser2")
1541         self.assertEquals(list(res_user[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
1542         self.assertTrue("objectSid" in res_user[0])
1543         self.assertTrue("objectGUID" in res_user[0])
1544         self.assertTrue("whenCreated" in res_user[0])
1545         self.assertTrue("nTSecurityDescriptor" in res_user[0])
1546         self.assertTrue("allowedAttributes" in res_user[0])
1547         self.assertTrue("allowedAttributesEffective" in res_user[0])
1548         self.assertEquals(res_user[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1549
1550         ldaptestuser2_sid = res_user[0]["objectSid"][0]
1551         ldaptestuser2_guid = res_user[0]["objectGUID"][0]
1552
1553         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"]
1554         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
1555         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1556         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1557
1558         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1559         self.assertEquals(str(res[0]["cn"]), "ldaptestgroup2")
1560         self.assertEquals(str(res[0]["name"]), "ldaptestgroup2")
1561         self.assertEquals(list(res[0]["objectClass"]), ["top", "group"])
1562         self.assertTrue("objectGUID" in res[0])
1563         self.assertTrue("objectSid" in res[0])
1564         self.assertTrue("whenCreated" in res[0])
1565         self.assertTrue("nTSecurityDescriptor" in res[0])
1566         self.assertTrue("allowedAttributes" in res[0])
1567         self.assertTrue("allowedAttributesEffective" in res[0])
1568         memberUP = []
1569         for m in res[0]["member"]:
1570             memberUP.append(m.upper())
1571         self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
1572
1573         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"])
1574         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1575
1576         print res[0]["member"]
1577         memberUP = []
1578         for m in res[0]["member"]:
1579             memberUP.append(m.upper())
1580         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()
1581
1582         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)
1583
1584         print "Testing Linked attribute behaviours"
1585         ldb.modify_ldif("""
1586 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1587 changetype: modify
1588 replace: member
1589 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
1590 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1591 """)
1592
1593         ldb.modify_ldif("""
1594 dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1595 changetype: modify
1596 replace: member
1597 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1598 """)
1599
1600         ldb.modify_ldif("""
1601 dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
1602 changetype: modify
1603 delete: member
1604 """)
1605
1606         ldb.modify_ldif("""
1607 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1608 changetype: modify
1609 add: member
1610 member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1611 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1612 """)
1613
1614         ldb.modify_ldif("""
1615 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1616 changetype: modify
1617 replace: member
1618 """)
1619
1620         ldb.modify_ldif("""
1621 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1622 changetype: modify
1623 add: member
1624 member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
1625 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1626 """)
1627
1628         ldb.modify_ldif("""
1629 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1630 changetype: modify
1631 delete: member
1632 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1633 """)
1634
1635         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1636         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1637
1638         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1639         self.assertEquals(res[0]["member"][0], ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1640         self.assertEquals(len(res[0]["member"]), 1)
1641
1642         ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
1643
1644         time.sleep(4)
1645
1646         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
1647         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
1648         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1649         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
1650
1651         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1652         self.assertTrue("member" not in res[0])
1653
1654         print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
1655 # TODO UTF8 users don't seem to work fully anymore
1656 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1657         res = ldb.search(expression="(&(cn=ldaptestutf8user èùéìòà)(objectclass=user))")
1658         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1659
1660         self.assertEquals(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
1661         self.assertEquals(str(res[0]["cn"]), "ldaptestutf8user èùéìòà")
1662         self.assertEquals(str(res[0]["name"]), "ldaptestutf8user èùéìòà")
1663         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
1664         self.assertTrue("objectGUID" in res[0])
1665         self.assertTrue("whenCreated" in res[0])
1666
1667         ldb.delete(res[0].dn)
1668
1669         print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
1670         res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
1671         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
1672
1673         ldb.delete(res[0].dn)
1674
1675         ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1676
1677         print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
1678 # TODO UTF8 users don't seem to work fully anymore
1679 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1680 #        self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1681
1682         print "Testing that we can't get at the configuration DN from the main search base"
1683         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1684         self.assertEquals(len(res), 0)
1685
1686         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"
1687         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
1688         self.assertTrue(len(res) > 0)
1689
1690         if gc_ldb is not None:
1691             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"
1692
1693             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
1694             self.assertTrue(len(res) > 0)
1695
1696             print "Testing that we do find configuration elements in the global catlog"
1697             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1698             self.assertTrue(len(res) > 0)
1699
1700             print "Testing that we do find configuration elements and user elements at the same time"
1701             res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
1702             self.assertTrue(len(res) > 0)
1703
1704             print "Testing that we do find configuration elements in the global catlog, with the configuration basedn"
1705             res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1706             self.assertTrue(len(res) > 0)
1707
1708         print "Testing that we can get at the configuration DN on the main LDAP port"
1709         res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1710         self.assertTrue(len(res) > 0)
1711
1712         print "Testing objectCategory canonacolisation"
1713         res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
1714         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
1715         self.assertTrue(len(res) != 0)
1716
1717         res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
1718         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
1719         self.assertTrue(len(res) != 0)
1720
1721         print "Testing objectClass attribute order on "+ self.base_dn
1722         res = ldb.search(expression="objectClass=domain", base=self.base_dn,
1723                          scope=SCOPE_BASE, attrs=["objectClass"])
1724         self.assertEquals(len(res), 1)
1725
1726         self.assertEquals(list(res[0]["objectClass"]), ["top", "domain", "domainDNS"])
1727
1728     #  check enumeration
1729
1730         print "Testing ldb.search for objectCategory=person"
1731         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
1732         self.assertTrue(len(res) > 0)
1733
1734         print "Testing ldb.search for objectCategory=person with domain scope control"
1735         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1736         self.assertTrue(len(res) > 0)
1737
1738         print "Testing ldb.search for objectCategory=user"
1739         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
1740         self.assertTrue(len(res) > 0)
1741
1742         print "Testing ldb.search for objectCategory=user with domain scope control"
1743         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1744         self.assertTrue(len(res) > 0)
1745
1746         print "Testing ldb.search for objectCategory=group"
1747         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
1748         self.assertTrue(len(res) > 0)
1749
1750         print "Testing ldb.search for objectCategory=group with domain scope control"
1751         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1752         self.assertTrue(len(res) > 0)
1753
1754         print "Testing creating a user with the posixAccount objectClass"
1755         self.ldb.add_ldif("""dn: cn=posixuser,CN=Users,%s
1756 objectClass: top
1757 objectClass: person
1758 objectClass: posixAccount
1759 objectClass: user
1760 objectClass: organizationalPerson
1761 cn: posixuser
1762 uid: posixuser
1763 sn: posixuser
1764 uidNumber: 10126
1765 gidNumber: 10126
1766 homeDirectory: /home/posixuser
1767 loginShell: /bin/bash
1768 gecos: Posix User;;;
1769 description: A POSIX user"""% (self.base_dn))
1770
1771         print "Testing removing the posixAccount objectClass from an existing user"
1772         self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
1773 changetype: modify
1774 delete: objectClass
1775 objectClass: posixAccount"""% (self.base_dn))
1776
1777         print "Testing adding the posixAccount objectClass to an existing user"
1778         self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
1779 changetype: modify
1780 add: objectClass
1781 objectClass: posixAccount"""% (self.base_dn))
1782
1783         self.delete_force(self.ldb, "cn=posixuser,cn=users," + self.base_dn)
1784         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1785         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1786         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
1787         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
1788         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
1789         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
1790         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1791         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1792         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1793         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
1794         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
1795         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
1796         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn)
1797         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
1798         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
1799
1800     def test_security_descriptor_add(self):
1801         """ Testing ldb.add_ldif() for nTSecurityDescriptor """
1802         user_name = "testdescriptoruser1"
1803         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1804         #
1805         # Test add_ldif() with SDDL security descriptor input
1806         #
1807         self.delete_force(self.ldb, user_dn)
1808         try:
1809             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1810             self.ldb.add_ldif("""
1811 dn: """ + user_dn + """
1812 objectclass: user
1813 sAMAccountName: """ + user_name + """
1814 nTSecurityDescriptor: """ + sddl)
1815             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1816             desc = res[0]["nTSecurityDescriptor"][0]
1817             desc = ndr_unpack( security.descriptor, desc )
1818             desc_sddl = desc.as_sddl( self.domain_sid )
1819             self.assertEqual(desc_sddl, sddl)
1820         finally:
1821             self.delete_force(self.ldb, user_dn)
1822         #
1823         # Test add_ldif() with BASE64 security descriptor
1824         #
1825         try:
1826             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1827             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1828             desc_binary = ndr_pack(desc)
1829             desc_base64 = base64.b64encode(desc_binary)
1830             self.ldb.add_ldif("""
1831 dn: """ + user_dn + """
1832 objectclass: user
1833 sAMAccountName: """ + user_name + """
1834 nTSecurityDescriptor:: """ + desc_base64)
1835             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1836             desc = res[0]["nTSecurityDescriptor"][0]
1837             desc = ndr_unpack(security.descriptor, desc)
1838             desc_sddl = desc.as_sddl(self.domain_sid)
1839             self.assertEqual(desc_sddl, sddl)
1840         finally:
1841             self.delete_force(self.ldb, user_dn)
1842
1843     def test_security_descriptor_add_neg(self):
1844         """Test add_ldif() with BASE64 security descriptor input using WRONG domain SID
1845             Negative test
1846         """
1847         user_name = "testdescriptoruser1"
1848         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1849         self.delete_force(self.ldb, user_dn)
1850         try:
1851             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1852             desc = security.descriptor.from_sddl(sddl, security.dom_sid('S-1-5-21'))
1853             desc_base64 = base64.b64encode( ndr_pack(desc) )
1854             self.ldb.add_ldif("""
1855 dn: """ + user_dn + """
1856 objectclass: user
1857 sAMAccountName: """ + user_name + """
1858 nTSecurityDescriptor:: """ + desc_base64)
1859             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1860             self.assertTrue("nTSecurityDescriptor" in res[0])
1861         finally:
1862             self.delete_force(self.ldb, user_dn)
1863
1864     def test_security_descriptor_modify(self):
1865         """ Testing ldb.modify_ldif() for nTSecurityDescriptor """
1866         user_name = "testdescriptoruser2"
1867         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1868         #
1869         # Delete user object and test modify_ldif() with SDDL security descriptor input
1870         # Add ACE to the original descriptor test
1871         #
1872         try:
1873             self.delete_force(self.ldb, user_dn)
1874             self.ldb.add_ldif("""
1875 dn: """ + user_dn + """
1876 objectclass: user
1877 sAMAccountName: """ + user_name)
1878             # Modify descriptor
1879             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1880             desc = res[0]["nTSecurityDescriptor"][0]
1881             desc = ndr_unpack(security.descriptor, desc)
1882             desc_sddl = desc.as_sddl(self.domain_sid)
1883             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
1884             mod = """
1885 dn: """ + user_dn + """
1886 changetype: modify
1887 replace: nTSecurityDescriptor
1888 nTSecurityDescriptor: """ + sddl
1889             self.ldb.modify_ldif(mod)
1890             # Read modified descriptor
1891             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1892             desc = res[0]["nTSecurityDescriptor"][0]
1893             desc = ndr_unpack(security.descriptor, desc)
1894             desc_sddl = desc.as_sddl(self.domain_sid)
1895             self.assertEqual(desc_sddl, sddl)
1896         finally:
1897             self.delete_force(self.ldb, user_dn)
1898         #
1899         # Test modify_ldif() with SDDL security descriptor input
1900         # New desctiptor test
1901         #
1902         try:
1903             self.ldb.add_ldif("""
1904 dn: """ + user_dn + """
1905 objectclass: user
1906 sAMAccountName: """ + user_name)
1907             # Modify descriptor
1908             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1909             mod = """
1910 dn: """ + user_dn + """
1911 changetype: modify
1912 replace: nTSecurityDescriptor
1913 nTSecurityDescriptor: """ + sddl
1914             self.ldb.modify_ldif(mod)
1915             # Read modified descriptor
1916             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1917             desc = res[0]["nTSecurityDescriptor"][0]
1918             desc = ndr_unpack(security.descriptor, desc)
1919             desc_sddl = desc.as_sddl(self.domain_sid)
1920             self.assertEqual(desc_sddl, sddl)
1921         finally:
1922             self.delete_force(self.ldb, user_dn)
1923         #
1924         # Test modify_ldif() with BASE64 security descriptor input
1925         # Add ACE to the original descriptor test
1926         #
1927         try:
1928             self.ldb.add_ldif("""
1929 dn: """ + user_dn + """
1930 objectclass: user
1931 sAMAccountName: """ + user_name)
1932             # Modify descriptor
1933             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1934             desc = res[0]["nTSecurityDescriptor"][0]
1935             desc = ndr_unpack(security.descriptor, desc)
1936             desc_sddl = desc.as_sddl(self.domain_sid)
1937             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
1938             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1939             desc_base64 = base64.b64encode(ndr_pack(desc))
1940             mod = """
1941 dn: """ + user_dn + """
1942 changetype: modify
1943 replace: nTSecurityDescriptor
1944 nTSecurityDescriptor:: """ + desc_base64
1945             self.ldb.modify_ldif(mod)
1946             # Read modified descriptor
1947             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1948             desc = res[0]["nTSecurityDescriptor"][0]
1949             desc = ndr_unpack(security.descriptor, desc)
1950             desc_sddl = desc.as_sddl(self.domain_sid)
1951             self.assertEqual(desc_sddl, sddl)
1952         finally:
1953             self.delete_force(self.ldb, user_dn)
1954         #
1955         # Test modify_ldif() with BASE64 security descriptor input
1956         # New descriptor test
1957         #
1958         try:
1959             self.delete_force(self.ldb, user_dn)
1960             self.ldb.add_ldif("""
1961 dn: """ + user_dn + """
1962 objectclass: user
1963 sAMAccountName: """ + user_name)
1964             # Modify descriptor
1965             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1966             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1967             desc_base64 = base64.b64encode(ndr_pack(desc))
1968             mod = """
1969 dn: """ + user_dn + """
1970 changetype: modify
1971 replace: nTSecurityDescriptor
1972 nTSecurityDescriptor:: """ + desc_base64
1973             self.ldb.modify_ldif(mod)
1974             # Read modified descriptor
1975             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1976             desc = res[0]["nTSecurityDescriptor"][0]
1977             desc = ndr_unpack(security.descriptor, desc)
1978             desc_sddl = desc.as_sddl(self.domain_sid)
1979             self.assertEqual(desc_sddl, sddl)
1980         finally:
1981             self.delete_force(self.ldb, user_dn)
1982
1983 class BaseDnTests(unittest.TestCase):
1984     def setUp(self):
1985         self.ldb = ldb
1986
1987     def test_rootdse_attrs(self):
1988         """Testing for all rootDSE attributes"""
1989         res = self.ldb.search(scope=SCOPE_BASE, attrs=[])
1990         self.assertEquals(len(res), 1)
1991
1992     def test_highestcommittedusn(self):
1993         """Testing for highestCommittedUSN"""
1994         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
1995         self.assertEquals(len(res), 1)
1996         self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
1997
1998     def test_netlogon(self):
1999         """Testing for netlogon via LDAP"""
2000         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
2001         self.assertEquals(len(res), 0)
2002
2003     def test_netlogon_highestcommitted_usn(self):
2004         """Testing for netlogon and highestCommittedUSN via LDAP"""
2005         res = self.ldb.search("", scope=SCOPE_BASE,
2006                 attrs=["netlogon", "highestCommittedUSN"])
2007         self.assertEquals(len(res), 0)
2008
2009     def test_namingContexts(self):
2010         """Testing for namingContexts in rootDSE"""
2011         res = self.ldb.search("", scope=SCOPE_BASE,
2012                 attrs=["namingContexts", "defaultNamingContext", "schemaNamingContext", "configurationNamingContext"])
2013         self.assertEquals(len(res), 1)
2014         
2015         ncs = set([])
2016         for nc in res[0]["namingContexts"]:
2017             self.assertTrue(nc not in ncs)
2018             ncs.add(nc)
2019
2020         self.assertTrue(res[0]["defaultNamingContext"][0] in ncs)
2021         self.assertTrue(res[0]["configurationNamingContext"][0] in ncs)
2022         self.assertTrue(res[0]["schemaNamingContext"][0] in ncs)
2023
2024
2025 if not "://" in host:
2026     if os.path.isfile(host):
2027         host = "tdb://%s" % host
2028     else:
2029         host = "ldap://%s" % host
2030
2031 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
2032 if not "tdb://" in host:
2033     gc_ldb = Ldb("%s:3268" % host, credentials=creds,
2034                  session_info=system_session(), lp=lp)
2035 else:
2036     gc_ldb = None
2037
2038 runner = SubunitTestRunner()
2039 rc = 0
2040 if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
2041     rc = 1
2042 if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
2043     rc = 1
2044 sys.exit(rc)