9682b4bc5320ba3afdf624582a5d0ddd37e9de10
[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         # Try to add invalid primary group
1032         m = Message()
1033         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1034         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
1035           "primaryGroupID")
1036         try:
1037             ldb.modify(m)
1038             self.fail()
1039         except LdbError, (num, _):
1040             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1041
1042         # Try to make group 1 primary - should be denied since it is not yet
1043         # secondary
1044         m = Message()
1045         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1046         m["primaryGroupID"] = MessageElement(str(group_rid_1),
1047           FLAG_MOD_REPLACE, "primaryGroupID")
1048         try:
1049             ldb.modify(m)
1050             self.fail()
1051         except LdbError, (num, _):
1052             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1053
1054         # Make group 1 secondary
1055         m = Message()
1056         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1057         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1058                                      FLAG_MOD_REPLACE, "member")
1059         ldb.modify(m)
1060
1061         # Make group 1 primary
1062         m = Message()
1063         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1064         m["primaryGroupID"] = MessageElement(str(group_rid_1),
1065           FLAG_MOD_REPLACE, "primaryGroupID")
1066         ldb.modify(m)
1067
1068         # Try to delete group 1 - should be denied
1069         try:
1070             ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
1071             self.fail()
1072         except LdbError, (num, _):
1073             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1074
1075         # Try to add group 1 also as secondary - should be denied
1076         m = Message()
1077         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1078         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1079                                      FLAG_MOD_ADD, "member")
1080         try:
1081             ldb.modify(m)
1082             self.fail()
1083         except LdbError, (num, _):
1084             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1085
1086         # Try to add invalid member to group 1 - should be denied
1087         m = Message()
1088         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1089         m["member"] = MessageElement(
1090           "cn=ldaptestuser3,cn=users," + self.base_dn,
1091           FLAG_MOD_ADD, "member")
1092         try:
1093             ldb.modify(m)
1094             self.fail()
1095         except LdbError, (num, _):
1096             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1097
1098         # Make group 2 secondary
1099         m = Message()
1100         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1101         m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1102                                      FLAG_MOD_ADD, "member")
1103         ldb.modify(m)
1104
1105         # Swap the groups
1106         m = Message()
1107         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1108         m["primaryGroupID"] = MessageElement(str(group_rid_2),
1109           FLAG_MOD_REPLACE, "primaryGroupID")
1110         ldb.modify(m)
1111
1112         # Old primary group should contain a "member" attribute for the user,
1113         # the new shouldn't contain anymore one
1114         res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
1115                           scope=SCOPE_BASE, attrs=["member"])
1116         self.assertTrue(len(res1) == 1)
1117         self.assertTrue(len(res1[0]["member"]) == 1)
1118         self.assertEquals(res1[0]["member"][0].lower(),
1119           ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
1120
1121         res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
1122                           scope=SCOPE_BASE, attrs=["member"])
1123         self.assertTrue(len(res1) == 1)
1124         self.assertFalse("member" in res1[0])
1125
1126         # Also this should be denied
1127         try:
1128             ldb.add({
1129               "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
1130               "objectclass": ["user", "person"],
1131               "primaryGroupID": "0"})
1132             self.fail()
1133         except LdbError, (num, _):
1134             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1135
1136         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1137         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1138         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1139
1140     def test_sam_attributes(self):
1141         """Test the behaviour of special attributes of SAM objects"""
1142         print "Testing the behaviour of special attributes of SAM objects\n"""
1143
1144         ldb.add({
1145             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1146             "objectclass": ["user", "person"]})
1147         ldb.add({
1148             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1149             "objectclass": "group"})
1150
1151         m = Message()
1152         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1153         m["groupType"] = MessageElement("0", FLAG_MOD_ADD,
1154           "groupType")
1155         try:
1156             ldb.modify(m)
1157             self.fail()
1158         except LdbError, (num, _):
1159             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1160
1161         m = Message()
1162         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1163         m["groupType"] = MessageElement([], FLAG_MOD_DELETE,
1164           "groupType")
1165         try:
1166             ldb.modify(m)
1167             self.fail()
1168         except LdbError, (num, _):
1169             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1170
1171         m = Message()
1172         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1173         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_ADD,
1174           "primaryGroupID")
1175         try:
1176             ldb.modify(m)
1177             self.fail()
1178         except LdbError, (num, _):
1179             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1180
1181         m = Message()
1182         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1183         m["primaryGroupID"] = MessageElement([], FLAG_MOD_DELETE,
1184           "primaryGroupID")
1185         try:
1186             ldb.modify(m)
1187             self.fail()
1188         except LdbError, (num, _):
1189             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1190
1191         m = Message()
1192         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1193         m["userAccountControl"] = MessageElement("0", FLAG_MOD_ADD,
1194           "userAccountControl")
1195         try:
1196             ldb.modify(m)
1197             self.fail()
1198         except LdbError, (num, _):
1199             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1200
1201         m = Message()
1202         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1203         m["userAccountControl"] = MessageElement([], FLAG_MOD_DELETE,
1204           "userAccountControl")
1205         try:
1206             ldb.modify(m)
1207             self.fail()
1208         except LdbError, (num, _):
1209             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1210
1211         m = Message()
1212         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1213         m["sAMAccountType"] = MessageElement("0", FLAG_MOD_ADD,
1214           "sAMAccountType")
1215         try:
1216             ldb.modify(m)
1217             self.fail()
1218         except LdbError, (num, _):
1219             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1220
1221         m = Message()
1222         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1223         m["sAMAccountType"] = MessageElement([], FLAG_MOD_REPLACE,
1224           "sAMAccountType")
1225         try:
1226             ldb.modify(m)
1227             self.fail()
1228         except LdbError, (num, _):
1229             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1230
1231         m = Message()
1232         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1233         m["sAMAccountType"] = MessageElement([], FLAG_MOD_DELETE,
1234           "sAMAccountType")
1235         try:
1236             ldb.modify(m)
1237             self.fail()
1238         except LdbError, (num, _):
1239             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1240
1241         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1242         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1243
1244     def test_primary_group_token_constructed(self):
1245         """Test the primary group token behaviour (hidden-generated-readonly attribute on groups) and some other constructed attributes"""
1246         print "Testing primary group token behaviour and other constructed attributes\n"
1247
1248         try:
1249             ldb.add({
1250                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1251                 "objectclass": "group",
1252                 "primaryGroupToken": "100"})
1253             self.fail()
1254         except LdbError, (num, _):
1255             self.assertEquals(num, ERR_UNDEFINED_ATTRIBUTE_TYPE)
1256         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1257
1258         ldb.add({
1259             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1260             "objectclass": ["user", "person"]})
1261
1262         ldb.add({
1263             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1264             "objectclass": "group"})
1265
1266         # Testing for one invalid, and one valid operational attribute, but also the things they are built from
1267         res1 = ldb.search(self.base_dn,
1268                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName", "objectClass", "objectSid"])
1269         self.assertTrue(len(res1) == 1)
1270         self.assertFalse("primaryGroupToken" in res1[0])
1271         self.assertTrue("canonicalName" in res1[0])
1272         self.assertTrue("objectClass" in res1[0])
1273         self.assertTrue("objectSid" in res1[0])
1274
1275         res1 = ldb.search(self.base_dn,
1276                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "canonicalName"])
1277         self.assertTrue(len(res1) == 1)
1278         self.assertFalse("primaryGroupToken" in res1[0])
1279         self.assertFalse("objectSid" in res1[0])
1280         self.assertFalse("objectClass" in res1[0])
1281         self.assertTrue("canonicalName" in res1[0])
1282
1283         res1 = ldb.search("cn=users,"+self.base_dn,
1284                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
1285         self.assertTrue(len(res1) == 1)
1286         self.assertFalse("primaryGroupToken" in res1[0])
1287
1288         res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
1289                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
1290         self.assertTrue(len(res1) == 1)
1291         self.assertFalse("primaryGroupToken" in res1[0])
1292
1293         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1294                           scope=SCOPE_BASE)
1295         self.assertTrue(len(res1) == 1)
1296         self.assertFalse("primaryGroupToken" in res1[0])
1297
1298         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1299                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
1300         self.assertTrue(len(res1) == 1)
1301         primary_group_token = int(res1[0]["primaryGroupToken"][0])
1302
1303         rid = security.dom_sid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0])).split()[1]
1304         self.assertEquals(primary_group_token, rid)
1305
1306         m = Message()
1307         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1308         m["primaryGroupToken"] = "100"
1309         try:
1310             ldb.modify(m)
1311             self.fail()
1312         except LdbError, (num, _):
1313             self.assertEquals(num, ERR_CONSTRAINT_VIOLATION)
1314
1315         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1316         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1317
1318     def test_tokenGroups(self):
1319         """Test the tokenGroups behaviour (hidden-generated-readonly attribute on SAM objects)"""
1320         print "Testing tokenGroups behaviour\n"
1321
1322         # The domain object shouldn't contain any "tokenGroups" entry
1323         res = ldb.search(self.base_dn, scope=SCOPE_BASE, attrs=["tokenGroups"])
1324         self.assertTrue(len(res) == 1)
1325         self.assertFalse("tokenGroups" in res[0])
1326
1327         # The domain administrator should contain "tokenGroups" entries
1328         # (the exact number depends on the domain/forest function level and the
1329         # DC software versions)
1330         res = ldb.search("cn=Administrator,cn=Users," + self.base_dn,
1331                          scope=SCOPE_BASE, attrs=["tokenGroups"])
1332         self.assertTrue(len(res) == 1)
1333         self.assertTrue("tokenGroups" in res[0])
1334
1335         ldb.add({
1336             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1337             "objectclass": ["user", "person"]})
1338
1339         # This testuser should contain at least two "tokenGroups" entries
1340         # (exactly two on an unmodified "Domain Users" and "Users" group)
1341         res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
1342                          scope=SCOPE_BASE, attrs=["tokenGroups"])
1343         self.assertTrue(len(res) == 1)
1344         self.assertTrue(len(res[0]["tokenGroups"]) >= 2)
1345
1346         # one entry which we need to find should point to domains "Domain Users"
1347         # group and another entry should point to the builtin "Users"group
1348         domain_users_group_found = False
1349         users_group_found = False
1350         for sid in res[0]["tokenGroups"]:
1351             rid = security.dom_sid(ldb.schema_format_value("objectSID", sid)).split()[1]
1352             if rid == 513:
1353                 domain_users_group_found = True
1354             if rid == 545:
1355                 users_group_found = True
1356
1357         self.assertTrue(domain_users_group_found)
1358         self.assertTrue(users_group_found)
1359
1360         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1361
1362     def test_wkguid(self):
1363         """Test Well known GUID behaviours (including DN+Binary)"""
1364         print "Test Well known GUID behaviours (including DN+Binary)"""
1365
1366         res = self.ldb.search(base=("<WKGUID=ab1d30f3768811d1aded00c04fd8d5cd,%s>" % self.base_dn), scope=SCOPE_BASE, attrs=[])
1367         self.assertEquals(len(res), 1)
1368         
1369         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd:%s" % res[0].dn))
1370         self.assertEquals(len(res2), 1)
1371
1372         # Prove that the matching rule is over the whole DN+Binary
1373         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd"))
1374         self.assertEquals(len(res2), 0)
1375         # Prove that the matching rule is over the whole DN+Binary
1376         res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=%s") % res[0].dn)
1377         self.assertEquals(len(res2), 0)
1378
1379     def test_subschemasubentry(self):
1380         """Test subSchemaSubEntry appears when requested, but not when not requested"""
1381         print "Test subSchemaSubEntry"""
1382
1383         res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["subSchemaSubEntry"])
1384         self.assertEquals(len(res), 1)
1385         self.assertEquals(res[0]["subSchemaSubEntry"][0], "CN=Aggregate,"+self.schema_dn)
1386
1387         res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["*"])
1388         self.assertEquals(len(res), 1)
1389         self.assertTrue("subScheamSubEntry" not in res[0])
1390
1391     def test_all(self):
1392         """Basic tests"""
1393
1394         print "Testing user add"
1395
1396         ldb.add({
1397             "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
1398             "objectclass": ["user", "person"],
1399             "cN": "LDAPtestUSER",
1400             "givenname": "ldap",
1401             "sn": "testy"})
1402
1403         ldb.add({
1404             "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
1405             "objectclass": "group",
1406             "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
1407
1408         ldb.add({
1409             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1410             "objectclass": "computer",
1411             "cN": "LDAPtestCOMPUTER"})
1412
1413         ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
1414             "objectClass": "computer",
1415             "cn": "LDAPtest2COMPUTER",
1416             "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT),
1417             "displayname": "ldap testy"})
1418
1419         try:
1420             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
1421                      "objectClass": "computer",
1422                      "cn": "LDAPtest2COMPUTER"
1423                      })
1424             self.fail()
1425         except LdbError, (num, _):
1426             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
1427
1428         try:
1429             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
1430                      "objectClass": "computer",
1431                      "cn": "ldaptestcomputer3",
1432                      "sAMAccountType": str(ATYPE_NORMAL_ACCOUNT)
1433                 })
1434             self.fail()
1435         except LdbError, (num, _):
1436             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1437
1438         ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
1439                  "objectClass": "computer",
1440                  "cn": "LDAPtestCOMPUTER3"
1441                  })
1442
1443         print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
1444         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
1445         self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
1446
1447         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn));
1448         self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3");
1449         self.assertEquals(res[0]["name"][0], "ldaptestcomputer3");
1450         self.assertEquals(res[0]["objectClass"][0], "top");
1451         self.assertEquals(res[0]["objectClass"][1], "person");
1452         self.assertEquals(res[0]["objectClass"][2], "organizationalPerson");
1453         self.assertEquals(res[0]["objectClass"][3], "user");
1454         self.assertEquals(res[0]["objectClass"][4], "computer");
1455         self.assertTrue("objectGUID" in res[0])
1456         self.assertTrue("whenCreated" in res[0])
1457         self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
1458         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
1459         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT);
1460         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE);
1461
1462         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
1463
1464         print "Testing attribute or value exists behaviour"
1465         try:
1466             ldb.modify_ldif("""
1467 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1468 changetype: modify
1469 replace: servicePrincipalName
1470 servicePrincipalName: host/ldaptest2computer
1471 servicePrincipalName: host/ldaptest2computer
1472 servicePrincipalName: cifs/ldaptest2computer
1473 """)
1474             self.fail()
1475         except LdbError, (num, msg):
1476             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1477
1478         ldb.modify_ldif("""
1479 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1480 changetype: modify
1481 replace: servicePrincipalName
1482 servicePrincipalName: host/ldaptest2computer
1483 servicePrincipalName: cifs/ldaptest2computer
1484 """)
1485         try:
1486             ldb.modify_ldif("""
1487 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1488 changetype: modify
1489 add: servicePrincipalName
1490 servicePrincipalName: host/ldaptest2computer
1491 """)
1492             self.fail()
1493         except LdbError, (num, msg):
1494             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
1495
1496         print "Testing ranged results"
1497         ldb.modify_ldif("""
1498 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1499 changetype: modify
1500 replace: servicePrincipalName
1501 """)
1502
1503         ldb.modify_ldif("""
1504 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
1505 changetype: modify
1506 add: servicePrincipalName
1507 servicePrincipalName: host/ldaptest2computer0
1508 servicePrincipalName: host/ldaptest2computer1
1509 servicePrincipalName: host/ldaptest2computer2
1510 servicePrincipalName: host/ldaptest2computer3
1511 servicePrincipalName: host/ldaptest2computer4
1512 servicePrincipalName: host/ldaptest2computer5
1513 servicePrincipalName: host/ldaptest2computer6
1514 servicePrincipalName: host/ldaptest2computer7
1515 servicePrincipalName: host/ldaptest2computer8
1516 servicePrincipalName: host/ldaptest2computer9
1517 servicePrincipalName: host/ldaptest2computer10
1518 servicePrincipalName: host/ldaptest2computer11
1519 servicePrincipalName: host/ldaptest2computer12
1520 servicePrincipalName: host/ldaptest2computer13
1521 servicePrincipalName: host/ldaptest2computer14
1522 servicePrincipalName: host/ldaptest2computer15
1523 servicePrincipalName: host/ldaptest2computer16
1524 servicePrincipalName: host/ldaptest2computer17
1525 servicePrincipalName: host/ldaptest2computer18
1526 servicePrincipalName: host/ldaptest2computer19
1527 servicePrincipalName: host/ldaptest2computer20
1528 servicePrincipalName: host/ldaptest2computer21
1529 servicePrincipalName: host/ldaptest2computer22
1530 servicePrincipalName: host/ldaptest2computer23
1531 servicePrincipalName: host/ldaptest2computer24
1532 servicePrincipalName: host/ldaptest2computer25
1533 servicePrincipalName: host/ldaptest2computer26
1534 servicePrincipalName: host/ldaptest2computer27
1535 servicePrincipalName: host/ldaptest2computer28
1536 servicePrincipalName: host/ldaptest2computer29
1537 """)
1538
1539         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
1540                          attrs=["servicePrincipalName;range=0-*"])
1541         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1542         #print len(res[0]["servicePrincipalName;range=0-*"])
1543         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1544
1545         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
1546         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1547             # print res[0]["servicePrincipalName;range=0-19"].length
1548         self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
1549
1550
1551         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
1552         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1553         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1554
1555         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
1556         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1557         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
1558
1559         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
1560         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1561         self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
1562
1563
1564         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
1565         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1566         self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
1567         # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
1568
1569         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
1570         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1571         self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19)
1572             # print res[0]["servicePrincipalName;range=11-*"][18]
1573             # print pos_11
1574             # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
1575
1576         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
1577         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1578         self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5)
1579             # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
1580
1581         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
1582         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1583             # print res[0]["servicePrincipalName"][18]
1584             # print pos_11
1585         self.assertEquals(len(res[0]["servicePrincipalName"]), 30)
1586             # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11)
1587
1588         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1589         ldb.add({
1590             "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
1591             "objectClass": ["person", "user"],
1592             "cn": "LDAPtestUSER2",
1593             "givenname": "testy",
1594             "sn": "ldap user2"})
1595
1596         print "Testing Ambigious Name Resolution"
1597         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
1598         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
1599         self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
1600
1601         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1602         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1603         self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
1604
1605         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
1606         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
1607         self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
1608
1609         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
1610         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
1611         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
1612
1613         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1614         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1615         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1616
1617         # Testing ldb.search for (&(anr=testy)(objectClass=user))
1618         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
1619         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
1620
1621         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1622         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1623         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
1624
1625         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1626 # this test disabled for the moment, as anr with == tests are not understood
1627 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1628 #        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
1629
1630 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1631 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1632 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1633
1634         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1635 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1636 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
1637
1638 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1639 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1640 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1641
1642         # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
1643         res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
1644         self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
1645
1646         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1647         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1648         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1649
1650         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
1651 #        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
1652 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
1653
1654         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1655         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1656         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1657
1658         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
1659 #        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
1660 #        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
1661
1662         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1663         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1664         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1665
1666         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
1667 #        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
1668 #        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
1669
1670         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
1671         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
1672         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
1673
1674         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
1675 #        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
1676 #        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
1677
1678         print "Testing Renames"
1679
1680         attrs = ["objectGUID", "objectSid"]
1681         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
1682         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
1683         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
1684
1685         # Check rename works with extended/alternate DN forms
1686         ldb.rename("<SID=" + ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0]) + ">" , "cn=ldaptestUSER3,cn=users," + self.base_dn)
1687
1688         print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))"
1689         res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
1690         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
1691
1692         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1693         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1694         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1695
1696          #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
1697         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
1698         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
1699
1700         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1701         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1702         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1703
1704          #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
1705         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
1706         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
1707
1708         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1709         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1710         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1711
1712          #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
1713         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
1714         self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
1715
1716         # This is a Samba special, and does not exist in real AD
1717         #    print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1718         #    res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1719         #    if (res.error != 0 || len(res) != 1) {
1720         #        print "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1721         #        self.assertEquals(len(res), 1)
1722         #    }
1723         #    self.assertEquals(res[0].dn, ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1724         #    self.assertEquals(res[0].cn, "ldaptestUSER3")
1725         #    self.assertEquals(res[0].name, "ldaptestUSER3")
1726
1727         print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1728         res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1729         self.assertEquals(len(res), 1, "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1730         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1731         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1732         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1733
1734         # ensure we cannot add it again
1735         try:
1736             ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
1737                       "objectClass": ["person", "user"],
1738                       "cn": "LDAPtestUSER3"})
1739             self.fail()
1740         except LdbError, (num, _):
1741             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1742
1743         # rename back
1744         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
1745
1746         # ensure we cannot rename it twice
1747         try:
1748             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
1749                        "cn=ldaptestuser2,cn=users," + self.base_dn)
1750             self.fail()
1751         except LdbError, (num, _):
1752             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1753
1754         # ensure can now use that name
1755         ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
1756                       "objectClass": ["person", "user"],
1757                       "cn": "LDAPtestUSER3"})
1758
1759         # ensure we now cannot rename
1760         try:
1761             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
1762             self.fail()
1763         except LdbError, (num, _):
1764             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1765         try:
1766             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
1767             self.fail()
1768         except LdbError, (num, _):
1769             self.assertTrue(num in (71, 64))
1770
1771         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
1772
1773         ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
1774
1775         self.delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1776
1777         ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1778
1779         print "Testing subtree renames"
1780
1781         ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
1782                  "objectClass": "container"})
1783
1784         ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
1785                  "objectClass": ["person", "user"],
1786                  "cn": "LDAPtestUSER4"})
1787
1788         ldb.modify_ldif("""
1789 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1790 changetype: modify
1791 add: member
1792 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
1793 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
1794 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
1795 """)
1796
1797         print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
1798         ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
1799
1800         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))"
1801         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
1802         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
1803
1804         print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
1805         try:
1806             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1807                     expression="(&(cn=ldaptestuser4)(objectClass=user))",
1808                     scope=SCOPE_SUBTREE)
1809             self.fail(res)
1810         except LdbError, (num, _):
1811             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1812
1813         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
1814         try:
1815             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1816                     expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
1817             self.fail()
1818         except LdbError, (num, _):
1819             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1820
1821         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
1822         res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
1823         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
1824
1825         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
1826         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1827
1828         time.sleep(4)
1829
1830         print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
1831         res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
1832         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?")
1833
1834         print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
1835         try:
1836             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
1837             self.fail()
1838         except LdbError, (num, _):
1839             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1840
1841         print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
1842         try:
1843             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
1844             self.fail()
1845         except LdbError, (num, _):
1846             self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER))
1847
1848         print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
1849         try:
1850             ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
1851             self.fail()
1852         except LdbError, (num, _):
1853             self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
1854
1855         print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
1856         res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
1857         self.assertEquals(len(res), 1)
1858         res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
1859         self.assertEquals(len(res), 0)
1860
1861         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
1862         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
1863         # FIXME: self.assertEquals(len(res), 0)
1864
1865         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
1866         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
1867         # FIXME: self.assertEquals(len(res), 0)
1868
1869         print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
1870         ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
1871         print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
1872         ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
1873
1874         ldb.add({"dn": "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
1875
1876         ldb.add({"dn": "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
1877
1878         print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
1879         res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
1880         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1881
1882         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1883         self.assertEquals(str(res[0]["cn"]), "ldaptestuser")
1884         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1885         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user"]))
1886         self.assertTrue("objectGUID" in res[0])
1887         self.assertTrue("whenCreated" in res[0])
1888         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
1889         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1890         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1891         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1892         self.assertEquals(len(res[0]["memberOf"]), 1)
1893
1894         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
1895         res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1896         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1897
1898         self.assertEquals(res[0].dn, res2[0].dn)
1899
1900         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
1901         res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1902         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
1903
1904         self.assertEquals(res[0].dn, res3[0].dn)
1905
1906         if gc_ldb is not None:
1907             print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
1908             res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1909             self.assertEquals(len(res3gc), 1)
1910
1911             self.assertEquals(res[0].dn, res3gc[0].dn)
1912
1913         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
1914
1915         if gc_ldb is not None:
1916             res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
1917             self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
1918
1919             self.assertEquals(res[0].dn, res3control[0].dn)
1920
1921         ldb.delete(res[0].dn)
1922
1923         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
1924         res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
1925         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1926
1927         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
1928         self.assertEquals(str(res[0]["cn"]), "ldaptestcomputer")
1929         self.assertEquals(str(res[0]["name"]), "ldaptestcomputer")
1930         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user", "computer"]))
1931         self.assertTrue("objectGUID" in res[0])
1932         self.assertTrue("whenCreated" in res[0])
1933         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
1934         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
1935         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1936         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1937         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1938         self.assertEquals(len(res[0]["memberOf"]), 1)
1939
1940         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
1941         res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1942         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1943
1944         self.assertEquals(res[0].dn, res2[0].dn)
1945
1946         if gc_ldb is not None:
1947             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
1948             res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1949             self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
1950
1951             self.assertEquals(res[0].dn, res2gc[0].dn)
1952
1953         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
1954         res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1955         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1956
1957         self.assertEquals(res[0].dn, res3[0].dn)
1958
1959         if gc_ldb is not None:
1960             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
1961             res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1962             self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
1963
1964             self.assertEquals(res[0].dn, res3gc[0].dn)
1965
1966         print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
1967         res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1968         self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1969
1970         self.assertEquals(res[0].dn, res4[0].dn)
1971
1972         print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
1973         res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1974         self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1975
1976         self.assertEquals(res[0].dn, res5[0].dn)
1977
1978         print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
1979         res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
1980         self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
1981
1982         self.assertEquals(res[0].dn, res6[0].dn)
1983
1984         ldb.delete("<GUID=" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + ">")
1985
1986         print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
1987         res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
1988         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
1989
1990         self.assertEquals(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn)
1991         self.assertEquals(str(res[0]["cn"]), "ldaptest2computer")
1992         self.assertEquals(str(res[0]["name"]), "ldaptest2computer")
1993         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user", "computer"])
1994         self.assertTrue("objectGUID" in res[0])
1995         self.assertTrue("whenCreated" in res[0])
1996         self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
1997         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
1998         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT)
1999
2000         ldb.delete("<SID=" + ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + ">")
2001
2002         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"]
2003         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
2004         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
2005         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
2006
2007         self.assertEquals(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2008         self.assertEquals(str(res_user[0]["cn"]), "ldaptestuser2")
2009         self.assertEquals(str(res_user[0]["name"]), "ldaptestuser2")
2010         self.assertEquals(list(res_user[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
2011         self.assertTrue("objectSid" in res_user[0])
2012         self.assertTrue("objectGUID" in res_user[0])
2013         self.assertTrue("whenCreated" in res_user[0])
2014         self.assertTrue("nTSecurityDescriptor" in res_user[0])
2015         self.assertTrue("allowedAttributes" in res_user[0])
2016         self.assertTrue("allowedAttributesEffective" in res_user[0])
2017         self.assertEquals(res_user[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2018
2019         ldaptestuser2_sid = res_user[0]["objectSid"][0]
2020         ldaptestuser2_guid = res_user[0]["objectGUID"][0]
2021
2022         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"]
2023         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
2024         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2025         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2026
2027         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2028         self.assertEquals(str(res[0]["cn"]), "ldaptestgroup2")
2029         self.assertEquals(str(res[0]["name"]), "ldaptestgroup2")
2030         self.assertEquals(list(res[0]["objectClass"]), ["top", "group"])
2031         self.assertTrue("objectGUID" in res[0])
2032         self.assertTrue("objectSid" in res[0])
2033         self.assertTrue("whenCreated" in res[0])
2034         self.assertTrue("nTSecurityDescriptor" in res[0])
2035         self.assertTrue("allowedAttributes" in res[0])
2036         self.assertTrue("allowedAttributesEffective" in res[0])
2037         memberUP = []
2038         for m in res[0]["member"]:
2039             memberUP.append(m.upper())
2040         self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
2041
2042         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"])
2043         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2044
2045         print res[0]["member"]
2046         memberUP = []
2047         for m in res[0]["member"]:
2048             memberUP.append(m.upper())
2049         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()
2050
2051         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)
2052
2053         print "Testing Linked attribute behaviours"
2054         ldb.modify_ldif("""
2055 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2056 changetype: modify
2057 replace: member
2058 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
2059 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2060 """)
2061
2062         ldb.modify_ldif("""
2063 dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
2064 changetype: modify
2065 replace: member
2066 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2067 """)
2068
2069         ldb.modify_ldif("""
2070 dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
2071 changetype: modify
2072 delete: member
2073 """)
2074
2075         ldb.modify_ldif("""
2076 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2077 changetype: modify
2078 add: member
2079 member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
2080 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2081 """)
2082
2083         ldb.modify_ldif("""
2084 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2085 changetype: modify
2086 replace: member
2087 """)
2088
2089         ldb.modify_ldif("""
2090 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2091 changetype: modify
2092 add: member
2093 member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
2094 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2095 """)
2096
2097         ldb.modify_ldif("""
2098 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2099 changetype: modify
2100 delete: member
2101 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2102 """)
2103
2104         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2105         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2106
2107         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2108         self.assertEquals(res[0]["member"][0], ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2109         self.assertEquals(len(res[0]["member"]), 1)
2110
2111         ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
2112
2113         time.sleep(4)
2114
2115         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
2116         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
2117         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2118         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
2119
2120         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2121         self.assertTrue("member" not in res[0])
2122
2123         print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
2124 # TODO UTF8 users don't seem to work fully anymore
2125 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2126         res = ldb.search(expression="(&(cn=ldaptestutf8user èùéìòà)(objectclass=user))")
2127         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2128
2129         self.assertEquals(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
2130         self.assertEquals(str(res[0]["cn"]), "ldaptestutf8user èùéìòà")
2131         self.assertEquals(str(res[0]["name"]), "ldaptestutf8user èùéìòà")
2132         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
2133         self.assertTrue("objectGUID" in res[0])
2134         self.assertTrue("whenCreated" in res[0])
2135
2136         ldb.delete(res[0].dn)
2137
2138         print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
2139         res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
2140         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
2141
2142         ldb.delete(res[0].dn)
2143
2144         ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2145
2146         print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
2147 # TODO UTF8 users don't seem to work fully anymore
2148 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2149 #        self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2150
2151         print "Testing that we can't get at the configuration DN from the main search base"
2152         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2153         self.assertEquals(len(res), 0)
2154
2155         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"
2156         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
2157         self.assertTrue(len(res) > 0)
2158
2159         if gc_ldb is not None:
2160             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"
2161
2162             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
2163             self.assertTrue(len(res) > 0)
2164
2165             print "Testing that we do find configuration elements in the global catlog"
2166             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2167             self.assertTrue(len(res) > 0)
2168
2169             print "Testing that we do find configuration elements and user elements at the same time"
2170             res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
2171             self.assertTrue(len(res) > 0)
2172
2173             print "Testing that we do find configuration elements in the global catlog, with the configuration basedn"
2174             res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2175             self.assertTrue(len(res) > 0)
2176
2177         print "Testing that we can get at the configuration DN on the main LDAP port"
2178         res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2179         self.assertTrue(len(res) > 0)
2180
2181         print "Testing objectCategory canonacolisation"
2182         res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
2183         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
2184         self.assertTrue(len(res) != 0)
2185
2186         res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
2187         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
2188         self.assertTrue(len(res) != 0)
2189
2190         print "Testing objectClass attribute order on "+ self.base_dn
2191         res = ldb.search(expression="objectClass=domain", base=self.base_dn,
2192                          scope=SCOPE_BASE, attrs=["objectClass"])
2193         self.assertEquals(len(res), 1)
2194
2195         self.assertEquals(list(res[0]["objectClass"]), ["top", "domain", "domainDNS"])
2196
2197     #  check enumeration
2198
2199         print "Testing ldb.search for objectCategory=person"
2200         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
2201         self.assertTrue(len(res) > 0)
2202
2203         print "Testing ldb.search for objectCategory=person with domain scope control"
2204         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2205         self.assertTrue(len(res) > 0)
2206
2207         print "Testing ldb.search for objectCategory=user"
2208         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
2209         self.assertTrue(len(res) > 0)
2210
2211         print "Testing ldb.search for objectCategory=user with domain scope control"
2212         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2213         self.assertTrue(len(res) > 0)
2214
2215         print "Testing ldb.search for objectCategory=group"
2216         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
2217         self.assertTrue(len(res) > 0)
2218
2219         print "Testing ldb.search for objectCategory=group with domain scope control"
2220         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2221         self.assertTrue(len(res) > 0)
2222
2223         print "Testing creating a user with the posixAccount objectClass"
2224         self.ldb.add_ldif("""dn: cn=posixuser,CN=Users,%s
2225 objectClass: top
2226 objectClass: person
2227 objectClass: posixAccount
2228 objectClass: user
2229 objectClass: organizationalPerson
2230 cn: posixuser
2231 uid: posixuser
2232 sn: posixuser
2233 uidNumber: 10126
2234 gidNumber: 10126
2235 homeDirectory: /home/posixuser
2236 loginShell: /bin/bash
2237 gecos: Posix User;;;
2238 description: A POSIX user"""% (self.base_dn))
2239
2240         print "Testing removing the posixAccount objectClass from an existing user"
2241         self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
2242 changetype: modify
2243 delete: objectClass
2244 objectClass: posixAccount"""% (self.base_dn))
2245
2246         print "Testing adding the posixAccount objectClass to an existing user"
2247         self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
2248 changetype: modify
2249 add: objectClass
2250 objectClass: posixAccount"""% (self.base_dn))
2251
2252         self.delete_force(self.ldb, "cn=posixuser,cn=users," + self.base_dn)
2253         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2254         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2255         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
2256         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
2257         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
2258         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
2259         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
2260         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
2261         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2262         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
2263         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
2264         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
2265         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn)
2266         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
2267         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
2268
2269     def test_security_descriptor_add(self):
2270         """ Testing ldb.add_ldif() for nTSecurityDescriptor """
2271         user_name = "testdescriptoruser1"
2272         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2273         #
2274         # Test add_ldif() with SDDL security descriptor input
2275         #
2276         self.delete_force(self.ldb, user_dn)
2277         try:
2278             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2279             self.ldb.add_ldif("""
2280 dn: """ + user_dn + """
2281 objectclass: user
2282 sAMAccountName: """ + user_name + """
2283 nTSecurityDescriptor: """ + sddl)
2284             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2285             desc = res[0]["nTSecurityDescriptor"][0]
2286             desc = ndr_unpack( security.descriptor, desc )
2287             desc_sddl = desc.as_sddl( self.domain_sid )
2288             self.assertEqual(desc_sddl, sddl)
2289         finally:
2290             self.delete_force(self.ldb, user_dn)
2291         #
2292         # Test add_ldif() with BASE64 security descriptor
2293         #
2294         try:
2295             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2296             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
2297             desc_binary = ndr_pack(desc)
2298             desc_base64 = base64.b64encode(desc_binary)
2299             self.ldb.add_ldif("""
2300 dn: """ + user_dn + """
2301 objectclass: user
2302 sAMAccountName: """ + user_name + """
2303 nTSecurityDescriptor:: """ + desc_base64)
2304             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2305             desc = res[0]["nTSecurityDescriptor"][0]
2306             desc = ndr_unpack(security.descriptor, desc)
2307             desc_sddl = desc.as_sddl(self.domain_sid)
2308             self.assertEqual(desc_sddl, sddl)
2309         finally:
2310             self.delete_force(self.ldb, user_dn)
2311
2312     def test_security_descriptor_add_neg(self):
2313         """Test add_ldif() with BASE64 security descriptor input using WRONG domain SID
2314             Negative test
2315         """
2316         user_name = "testdescriptoruser1"
2317         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2318         self.delete_force(self.ldb, user_dn)
2319         try:
2320             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2321             desc = security.descriptor.from_sddl(sddl, security.dom_sid('S-1-5-21'))
2322             desc_base64 = base64.b64encode( ndr_pack(desc) )
2323             self.ldb.add_ldif("""
2324 dn: """ + user_dn + """
2325 objectclass: user
2326 sAMAccountName: """ + user_name + """
2327 nTSecurityDescriptor:: """ + desc_base64)
2328             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2329             self.assertTrue("nTSecurityDescriptor" in res[0])
2330         finally:
2331             self.delete_force(self.ldb, user_dn)
2332
2333     def test_security_descriptor_modify(self):
2334         """ Testing ldb.modify_ldif() for nTSecurityDescriptor """
2335         user_name = "testdescriptoruser2"
2336         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2337         #
2338         # Delete user object and test modify_ldif() with SDDL security descriptor input
2339         # Add ACE to the original descriptor test
2340         #
2341         try:
2342             self.delete_force(self.ldb, user_dn)
2343             self.ldb.add_ldif("""
2344 dn: """ + user_dn + """
2345 objectclass: user
2346 sAMAccountName: """ + user_name)
2347             # Modify descriptor
2348             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2349             desc = res[0]["nTSecurityDescriptor"][0]
2350             desc = ndr_unpack(security.descriptor, desc)
2351             desc_sddl = desc.as_sddl(self.domain_sid)
2352             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
2353             mod = """
2354 dn: """ + user_dn + """
2355 changetype: modify
2356 replace: nTSecurityDescriptor
2357 nTSecurityDescriptor: """ + sddl
2358             self.ldb.modify_ldif(mod)
2359             # Read modified descriptor
2360             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2361             desc = res[0]["nTSecurityDescriptor"][0]
2362             desc = ndr_unpack(security.descriptor, desc)
2363             desc_sddl = desc.as_sddl(self.domain_sid)
2364             self.assertEqual(desc_sddl, sddl)
2365         finally:
2366             self.delete_force(self.ldb, user_dn)
2367         #
2368         # Test modify_ldif() with SDDL security descriptor input
2369         # New desctiptor test
2370         #
2371         try:
2372             self.ldb.add_ldif("""
2373 dn: """ + user_dn + """
2374 objectclass: user
2375 sAMAccountName: """ + user_name)
2376             # Modify descriptor
2377             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2378             mod = """
2379 dn: """ + user_dn + """
2380 changetype: modify
2381 replace: nTSecurityDescriptor
2382 nTSecurityDescriptor: """ + sddl
2383             self.ldb.modify_ldif(mod)
2384             # Read modified descriptor
2385             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2386             desc = res[0]["nTSecurityDescriptor"][0]
2387             desc = ndr_unpack(security.descriptor, desc)
2388             desc_sddl = desc.as_sddl(self.domain_sid)
2389             self.assertEqual(desc_sddl, sddl)
2390         finally:
2391             self.delete_force(self.ldb, user_dn)
2392         #
2393         # Test modify_ldif() with BASE64 security descriptor input
2394         # Add ACE to the original descriptor test
2395         #
2396         try:
2397             self.ldb.add_ldif("""
2398 dn: """ + user_dn + """
2399 objectclass: user
2400 sAMAccountName: """ + user_name)
2401             # Modify descriptor
2402             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2403             desc = res[0]["nTSecurityDescriptor"][0]
2404             desc = ndr_unpack(security.descriptor, desc)
2405             desc_sddl = desc.as_sddl(self.domain_sid)
2406             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
2407             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
2408             desc_base64 = base64.b64encode(ndr_pack(desc))
2409             mod = """
2410 dn: """ + user_dn + """
2411 changetype: modify
2412 replace: nTSecurityDescriptor
2413 nTSecurityDescriptor:: """ + desc_base64
2414             self.ldb.modify_ldif(mod)
2415             # Read modified descriptor
2416             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2417             desc = res[0]["nTSecurityDescriptor"][0]
2418             desc = ndr_unpack(security.descriptor, desc)
2419             desc_sddl = desc.as_sddl(self.domain_sid)
2420             self.assertEqual(desc_sddl, sddl)
2421         finally:
2422             self.delete_force(self.ldb, user_dn)
2423         #
2424         # Test modify_ldif() with BASE64 security descriptor input
2425         # New descriptor test
2426         #
2427         try:
2428             self.delete_force(self.ldb, user_dn)
2429             self.ldb.add_ldif("""
2430 dn: """ + user_dn + """
2431 objectclass: user
2432 sAMAccountName: """ + user_name)
2433             # Modify descriptor
2434             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2435             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
2436             desc_base64 = base64.b64encode(ndr_pack(desc))
2437             mod = """
2438 dn: """ + user_dn + """
2439 changetype: modify
2440 replace: nTSecurityDescriptor
2441 nTSecurityDescriptor:: """ + desc_base64
2442             self.ldb.modify_ldif(mod)
2443             # Read modified descriptor
2444             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2445             desc = res[0]["nTSecurityDescriptor"][0]
2446             desc = ndr_unpack(security.descriptor, desc)
2447             desc_sddl = desc.as_sddl(self.domain_sid)
2448             self.assertEqual(desc_sddl, sddl)
2449         finally:
2450             self.delete_force(self.ldb, user_dn)
2451
2452 class BaseDnTests(unittest.TestCase):
2453     def setUp(self):
2454         self.ldb = ldb
2455
2456     def test_rootdse_attrs(self):
2457         """Testing for all rootDSE attributes"""
2458         res = self.ldb.search(scope=SCOPE_BASE, attrs=[])
2459         self.assertEquals(len(res), 1)
2460
2461     def test_highestcommittedusn(self):
2462         """Testing for highestCommittedUSN"""
2463         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
2464         self.assertEquals(len(res), 1)
2465         self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
2466
2467     def test_netlogon(self):
2468         """Testing for netlogon via LDAP"""
2469         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
2470         self.assertEquals(len(res), 0)
2471
2472     def test_netlogon_highestcommitted_usn(self):
2473         """Testing for netlogon and highestCommittedUSN via LDAP"""
2474         res = self.ldb.search("", scope=SCOPE_BASE,
2475                 attrs=["netlogon", "highestCommittedUSN"])
2476         self.assertEquals(len(res), 0)
2477
2478     def test_namingContexts(self):
2479         """Testing for namingContexts in rootDSE"""
2480         res = self.ldb.search("", scope=SCOPE_BASE,
2481                 attrs=["namingContexts", "defaultNamingContext", "schemaNamingContext", "configurationNamingContext"])
2482         self.assertEquals(len(res), 1)
2483         
2484         ncs = set([])
2485         for nc in res[0]["namingContexts"]:
2486             self.assertTrue(nc not in ncs)
2487             ncs.add(nc)
2488
2489         self.assertTrue(res[0]["defaultNamingContext"][0] in ncs)
2490         self.assertTrue(res[0]["configurationNamingContext"][0] in ncs)
2491         self.assertTrue(res[0]["schemaNamingContext"][0] in ncs)
2492
2493
2494 if not "://" in host:
2495     if os.path.isfile(host):
2496         host = "tdb://%s" % host
2497     else:
2498         host = "ldap://%s" % host
2499
2500 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
2501 if not "tdb://" in host:
2502     gc_ldb = Ldb("%s:3268" % host, credentials=creds,
2503                  session_info=system_session(), lp=lp)
2504 else:
2505     gc_ldb = None
2506
2507 runner = SubunitTestRunner()
2508 rc = 0
2509 if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
2510     rc = 1
2511 if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
2512     rc = 1
2513 sys.exit(rc)