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