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