s4:ldap.py - add tests for valid parent and RDN
[ira/wip.git] / source4 / lib / ldb / tests / python / ldap.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
4
5 import getopt
6 import optparse
7 import sys
8 import time
9 import random
10 import base64
11
12 sys.path.append("bin/python")
13 sys.path.append("../lib/subunit/python")
14
15 import samba.getopt as options
16
17 from samba.auth import system_session
18 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
19 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
20 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
21 from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
22 from ldb import ERR_NO_SUCH_ATTRIBUTE, ERR_INSUFFICIENT_ACCESS_RIGHTS
23 from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
24 from ldb import ERR_NAMING_VIOLATION
25 from ldb import Message, MessageElement, Dn, FLAG_MOD_ADD, FLAG_MOD_REPLACE
26 from samba import Ldb, param, dom_sid_to_rid
27 from samba import UF_NORMAL_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT
28 from samba import UF_SERVER_TRUST_ACCOUNT, UF_WORKSTATION_TRUST_ACCOUNT
29 from samba import UF_INTERDOMAIN_TRUST_ACCOUNT
30 from samba import UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE
31 from samba import GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
32 from samba import GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP
33 from samba import GTYPE_SECURITY_UNIVERSAL_GROUP
34 from samba import GTYPE_DISTRIBUTION_GLOBAL_GROUP
35 from samba import GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP
36 from samba import GTYPE_DISTRIBUTION_UNIVERSAL_GROUP
37 from samba import ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST
38 from samba import ATYPE_SECURITY_GLOBAL_GROUP, ATYPE_SECURITY_LOCAL_GROUP
39 from samba import ATYPE_SECURITY_UNIVERSAL_GROUP
40 from samba import ATYPE_DISTRIBUTION_GLOBAL_GROUP
41 from samba import ATYPE_DISTRIBUTION_LOCAL_GROUP
42 from samba import ATYPE_DISTRIBUTION_UNIVERSAL_GROUP
43
44 from subunit import SubunitTestRunner
45 import unittest
46
47 from samba.ndr import ndr_pack, ndr_unpack
48 from samba.dcerpc import security
49
50 parser = optparse.OptionParser("ldap [options] <host>")
51 sambaopts = options.SambaOptions(parser)
52 parser.add_option_group(sambaopts)
53 parser.add_option_group(options.VersionOptions(parser))
54 # use command line creds if available
55 credopts = options.CredentialsOptions(parser)
56 parser.add_option_group(credopts)
57 opts, args = parser.parse_args()
58
59 if len(args) < 1:
60     parser.print_usage()
61     sys.exit(1)
62
63 host = args[0]
64
65 lp = sambaopts.get_loadparm()
66 creds = credopts.get_credentials(lp)
67
68 class BasicTests(unittest.TestCase):
69     def delete_force(self, ldb, dn):
70         try:
71             ldb.delete(dn)
72         except LdbError, (num, _):
73             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
74
75     def find_basedn(self, ldb):
76         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
77                          attrs=["defaultNamingContext"])
78         self.assertEquals(len(res), 1)
79         return res[0]["defaultNamingContext"][0]
80
81     def find_configurationdn(self, ldb):
82         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["configurationNamingContext"])
83         self.assertEquals(len(res), 1)
84         return res[0]["configurationNamingContext"][0]
85
86     def find_schemadn(self, ldb):
87         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
88         self.assertEquals(len(res), 1)
89         return res[0]["schemaNamingContext"][0]
90
91     def find_domain_sid(self):
92         res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
93         return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
94
95     def setUp(self):
96         self.ldb = ldb
97         self.gc_ldb = gc_ldb
98         self.base_dn = self.find_basedn(ldb)
99         self.configuration_dn = self.find_configurationdn(ldb)
100         self.schema_dn = self.find_schemadn(ldb)
101         self.domain_sid = self.find_domain_sid()
102
103         print "baseDN: %s\n" % self.base_dn
104
105         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
106         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
107         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
108         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=users," + self.base_dn)
109         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
110         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
111         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
112         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
113         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
114         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn)
115         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn)
116         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
117         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
118         self.delete_force(self.ldb, "cn=parentguidtest,cn=users," + self.base_dn)
119         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
120         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
121         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
122         self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
123         self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
124
125     def test_system_only(self):
126         """Test systemOnly objects"""
127         print "Test systemOnly objects"""
128
129         try:
130             self.ldb.add({
131                 "dn": "cn=ldaptestobject," + self.base_dn,
132                 "objectclass": "configuration"})
133             self.fail()
134         except LdbError, (num, _):
135             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
136
137         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
138
139     def test_invalid_parent(self):
140         """Test adding an object with invalid parent"""
141         print "Test adding an object with invalid parent"""
142
143         try:
144             self.ldb.add({
145                 "dn": "cn=ldaptestgroup,cn=thisdoesnotexist123,"
146                    + self.base_dn,
147                 "objectclass": "group"})
148             self.fail()
149         except LdbError, (num, _):
150             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
151
152         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=thisdoesnotexist123,"
153           + self.base_dn)
154
155         try:
156             self.ldb.add({
157                 "dn": "ou=testou,cn=users," + self.base_dn,
158                 "objectclass": "organizationalUnit"})
159             self.fail()
160         except LdbError, (num, _):
161             self.assertEquals(num, ERR_NAMING_VIOLATION)
162
163         self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
164
165     def test_invalid_attribute(self):
166         """Test adding invalid attributes (not in schema)"""
167         print "Test adding invalid attributes (not in schema)"""
168
169         try:
170             self.ldb.add({
171                 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
172                 "objectclass": "group",
173                 "thisdoesnotexist": "x"})
174             self.fail()
175         except LdbError, (num, _):
176             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
177
178         self.ldb.add({
179              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
180              "objectclass": "group"})
181
182         m = Message()
183         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
184         m["thisdoesnotexist"] = MessageElement("x", FLAG_MOD_REPLACE,
185           "thisdoesnotexist")
186         try:
187             ldb.modify(m)
188             self.fail()
189         except LdbError, (num, _):
190             self.assertEquals(num, ERR_NO_SUCH_ATTRIBUTE)
191
192         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
193
194     def test_distinguished_name(self):
195         """Tests the 'distinguishedName' attribute"""
196         print "Tests the 'distinguishedName' attribute"""
197
198         self.ldb.add({
199              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
200              "objectclass": "group"})
201
202         m = Message()
203         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
204         m["distinguishedName"] = MessageElement(
205           "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_REPLACE,
206           "distinguishedName")
207
208         try:
209             ldb.modify(m)
210             self.fail()
211         except LdbError, (num, _):
212             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
213
214         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
215
216     def test_rdn_name(self):
217         """Tests the RDN"""
218         print "Tests the RDN"""
219
220         try:
221             self.ldb.add({
222                  "dn": "description=xyz,cn=users," + self.base_dn,
223                  "objectclass": "group"})
224             self.fail()
225         except LdbError, (num, _):
226             self.assertEquals(num, ERR_NAMING_VIOLATION)
227  
228         self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
229
230         self.ldb.add({
231              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
232              "objectclass": "group"})
233
234         m = Message()
235         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
236         m["name"] = MessageElement("cn=ldaptestuser", FLAG_MOD_REPLACE,
237           "name")
238
239         try:
240             ldb.modify(m)
241             self.fail()
242         except LdbError, (num, _):
243             self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN)
244
245         m = Message()
246         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
247         m["cn"] = MessageElement("ldaptestuser",
248           FLAG_MOD_REPLACE, "cn")
249
250         try:
251             ldb.modify(m)
252             self.fail()
253         except LdbError, (num, _):
254             self.assertEquals(num, ERR_NOT_ALLOWED_ON_RDN)
255
256         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
257
258     def test_rename(self):
259         """Tests the rename operation"""
260         print "Tests the rename operations"""
261
262         self.ldb.add({
263              "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
264              "objectclass": ["user", "person"] })
265
266         ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
267         ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
268         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestUSER3,cn=users," + self.base_dn)
269         try:
270             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, ",cn=users," + self.base_dn)
271             self.fail()
272         except LdbError, (num, _):
273             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
274
275         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
276
277     def test_parentGUID(self):
278         """Test parentGUID behaviour"""
279         print "Testing parentGUID behaviour\n"
280
281         # TODO: This seems to fail on Windows Server. Hidden attribute?
282
283         self.ldb.add({
284             "dn": "cn=parentguidtest,cn=users," + self.base_dn,
285             "objectclass":"user",
286             "samaccountname":"parentguidtest"});
287         res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE,
288                           attrs=["parentGUID"]);
289         res2 = ldb.search(base="cn=users," + self.base_dn,scope=SCOPE_BASE,
290                           attrs=["objectGUID"]);
291         self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]);
292
293         print "Testing parentGUID behaviour on rename\n"
294
295         self.ldb.add({
296             "dn": "cn=testotherusers," + self.base_dn,
297             "objectclass":"container"});
298         res1 = ldb.search(base="cn=testotherusers," + self.base_dn,scope=SCOPE_BASE,
299                           attrs=["objectGUID"]);
300         ldb.rename("cn=parentguidtest,cn=users," + self.base_dn,
301                    "cn=parentguidtest,cn=testotherusers," + self.base_dn);
302         res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn,
303                           scope=SCOPE_BASE,
304                           attrs=["parentGUID"]);
305         self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]);
306
307         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
308         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
309
310     def test_groupType_int32(self):
311         """Test groupType (int32) behaviour (should appear to be casted to a 32 bit signed integer before comparsion)"""
312         print "Testing groupType (int32) behaviour\n"
313
314         res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
315                           attrs=["groupType"], expression="groupType=2147483653");
316
317         res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
318                           attrs=["groupType"], expression="groupType=-2147483643");
319
320         self.assertEquals(len(res1), len(res2))
321
322         self.assertTrue(res1.count > 0)
323
324         self.assertEquals(res1[0]["groupType"][0], "-2147483643")
325
326     def test_groups(self):
327         """This tests the group behaviour (setting, changing) of a user account"""
328         print "Testing group behaviour\n"
329
330         ldb.add({
331             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
332             "objectclass": "group"})
333
334         ldb.add({
335             "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
336             "objectclass": "group"})
337
338         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
339                           scope=SCOPE_BASE, attrs=["objectSID"])
340         self.assertTrue(len(res1) == 1)
341         group_rid_1 = dom_sid_to_rid(ldb.schema_format_value("objectSID",
342           res1[0]["objectSID"][0]))
343
344         res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
345                           scope=SCOPE_BASE, attrs=["objectSID"])
346         self.assertTrue(len(res1) == 1)
347         group_rid_2 = dom_sid_to_rid(ldb.schema_format_value("objectSID",
348           res1[0]["objectSID"][0]))
349
350         # Try to create a user with an invalid primary group
351         try:
352             ldb.add({
353                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
354                 "objectclass": ["user", "person"],
355                 "primaryGroupID": "0"})
356             self.fail()
357         except LdbError, (num, _):
358             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
359         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
360
361         # Try to Create a user with a valid primary group
362 # TODO Some more investigation needed here
363 #        try:
364 #            ldb.add({
365 #                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
366 #                "objectclass": ["user", "person"],
367 #                "primaryGroupID": str(group_rid_1)})
368 #            self.fail()
369 #        except LdbError, (num, _):
370 #            self.assertEquasl(num, ERR_UNWILLING_TO_PERFORM)
371 #        self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
372
373         ldb.add({
374             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
375             "objectclass": ["user", "person"]})
376
377         # Try to add invalid primary group
378         m = Message()
379         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
380         m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
381           "primaryGroupID")
382         try:
383             ldb.modify(m)
384             self.fail()
385         except LdbError, (num, _):
386             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
387
388         # Try to make group 1 primary - should be denied since it is not yet
389         # secondary
390         m = Message()
391         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
392         m["primaryGroupID"] = MessageElement(str(group_rid_1),
393           FLAG_MOD_REPLACE, "primaryGroupID")
394         try:
395             ldb.modify(m)
396             self.fail()
397         except LdbError, (num, _):
398             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
399
400         # Make group 1 secondary
401         m = Message()
402         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
403         m["member"] = "cn=ldaptestuser,cn=users," + self.base_dn
404         ldb.modify(m)
405
406         # Make group 1 primary
407         m = Message()
408         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
409         m["primaryGroupID"] = MessageElement(str(group_rid_1),
410           FLAG_MOD_REPLACE, "primaryGroupID")
411         ldb.modify(m)
412
413         # Try to delete group 1 - should be denied
414         try:
415             ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
416             self.fail()
417         except LdbError, (num, _):
418             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
419
420         # Try to add group 1 also as secondary - should be denied
421         m = Message()
422         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
423         m["member"] = "cn=ldaptestuser,cn=users," + self.base_dn
424         try:
425             ldb.modify(m)
426             self.fail()
427         except LdbError, (num, _):
428             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
429
430         # Try to add invalid member to group 1 - should be denied
431         m = Message()
432         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
433         m["member"] = MessageElement(
434           "cn=ldaptestuser3,cn=users," + self.base_dn,
435           FLAG_MOD_ADD, "member")
436         try:
437             ldb.modify(m)
438             self.fail()
439         except LdbError, (num, _):
440             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
441
442         # Make group 2 secondary
443         m = Message()
444         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
445         m["member"] = "cn=ldaptestuser,cn=users," + self.base_dn
446         ldb.modify(m)
447
448         # Swap the groups
449         m = Message()
450         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
451         m["primaryGroupID"] = MessageElement(str(group_rid_2),
452           FLAG_MOD_REPLACE, "primaryGroupID")
453         ldb.modify(m)
454
455         # Old primary group should contain a "member" attribute for the user,
456         # the new shouldn't contain anymore one
457         res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
458                           scope=SCOPE_BASE, attrs=["member"])
459         self.assertTrue(len(res1) == 1)
460         self.assertTrue(len(res1[0]["member"]) == 1)
461         self.assertEquals(res1[0]["member"][0].lower(),
462           ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
463
464         res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
465                           scope=SCOPE_BASE, attrs=["member"])
466         self.assertTrue(len(res1) == 1)
467         self.assertFalse("member" in res1[0])
468
469         # Also this should be denied
470         try:
471             ldb.add({
472               "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
473               "objectclass": ["user", "person"],
474               "primaryGroupID": "0"})
475             self.fail()
476         except LdbError, (num, _):
477             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
478
479         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
480         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
481         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
482
483     def test_primary_group_token(self):
484         """Test the primary group token behaviour (hidden-generated-readonly attribute on groups)"""
485         print "Testing primary group token behaviour\n"
486
487         ldb.add({
488             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
489             "objectclass": ["user", "person"]})
490
491         ldb.add({
492             "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
493             "objectclass": "group"})
494
495         res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
496                           scope=SCOPE_BASE, attrs=["primaryGroupToken"])
497         self.assertTrue(len(res1) == 1)
498         self.assertFalse("primaryGroupToken" in res1[0])
499
500         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
501                           scope=SCOPE_BASE)
502         self.assertTrue(len(res1) == 1)
503         self.assertFalse("primaryGroupToken" in res1[0])
504
505         res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
506                           scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
507         self.assertTrue(len(res1) == 1)
508         primary_group_token = int(res1[0]["primaryGroupToken"][0])
509
510         rid = dom_sid_to_rid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0]))
511         self.assertEquals(primary_group_token, rid)
512
513 # TODO Has to wait until we support read-only generated attributes correctly
514 #        m = Message()
515 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
516 #        m["primaryGroupToken"] = "100"
517 #        try:
518 #                ldb.modify(m)
519 #                self.fail()
520 #        except LdbError, (num, msg):
521
522         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
523         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
524
525     def test_all(self):
526         """Basic tests"""
527
528         print "Testing user add"
529
530         ldb.add({
531             "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
532             "objectclass": ["user", "person"],
533             "cN": "LDAPtestUSER",
534             "givenname": "ldap",
535             "sn": "testy"})
536
537         ldb.add({
538             "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
539             "objectclass": "group",
540             "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
541
542         ldb.add({
543             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
544             "objectclass": "computer",
545             "cN": "LDAPtestCOMPUTER"})
546
547         ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
548             "objectClass": "computer",
549             "cn": "LDAPtest2COMPUTER",
550             "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT),
551             "displayname": "ldap testy"})
552
553         try:
554             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
555                      "objectClass": "computer",
556                      "cn": "LDAPtest2COMPUTER"
557                      })
558             self.fail()
559         except LdbError, (num, _):
560             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
561
562         try:
563             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
564                      "objectClass": "computer",
565                      "cn": "ldaptestcomputer3",
566                      "sAMAccountType": str(ATYPE_NORMAL_ACCOUNT)
567                 })
568             self.fail()
569         except LdbError, (num, _):
570             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
571
572         ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
573                  "objectClass": "computer",
574                  "cn": "LDAPtestCOMPUTER3"
575                  })
576
577         print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
578         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
579         self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
580
581         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn));
582         self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3");
583         self.assertEquals(res[0]["name"][0], "ldaptestcomputer3");
584         self.assertEquals(res[0]["objectClass"][0], "top");
585         self.assertEquals(res[0]["objectClass"][1], "person");
586         self.assertEquals(res[0]["objectClass"][2], "organizationalPerson");
587         self.assertEquals(res[0]["objectClass"][3], "user");
588         self.assertEquals(res[0]["objectClass"][4], "computer");
589         self.assertTrue("objectGUID" in res[0])
590         self.assertTrue("whenCreated" in res[0])
591         self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
592         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
593         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT);
594         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE);
595
596         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
597
598         print "Testing attribute or value exists behaviour"
599         try:
600             ldb.modify_ldif("""
601 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
602 changetype: modify
603 replace: servicePrincipalName
604 servicePrincipalName: host/ldaptest2computer
605 servicePrincipalName: host/ldaptest2computer
606 servicePrincipalName: cifs/ldaptest2computer
607 """)
608             self.fail()
609         except LdbError, (num, msg):
610             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
611
612         ldb.modify_ldif("""
613 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
614 changetype: modify
615 replace: servicePrincipalName
616 servicePrincipalName: host/ldaptest2computer
617 servicePrincipalName: cifs/ldaptest2computer
618 """)
619         try:
620             ldb.modify_ldif("""
621 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
622 changetype: modify
623 add: servicePrincipalName
624 servicePrincipalName: host/ldaptest2computer
625 """)
626             self.fail()
627         except LdbError, (num, msg):
628             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
629
630         print "Testing ranged results"
631         ldb.modify_ldif("""
632 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
633 changetype: modify
634 replace: servicePrincipalName
635 """)
636
637         ldb.modify_ldif("""
638 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
639 changetype: modify
640 add: servicePrincipalName
641 servicePrincipalName: host/ldaptest2computer0
642 servicePrincipalName: host/ldaptest2computer1
643 servicePrincipalName: host/ldaptest2computer2
644 servicePrincipalName: host/ldaptest2computer3
645 servicePrincipalName: host/ldaptest2computer4
646 servicePrincipalName: host/ldaptest2computer5
647 servicePrincipalName: host/ldaptest2computer6
648 servicePrincipalName: host/ldaptest2computer7
649 servicePrincipalName: host/ldaptest2computer8
650 servicePrincipalName: host/ldaptest2computer9
651 servicePrincipalName: host/ldaptest2computer10
652 servicePrincipalName: host/ldaptest2computer11
653 servicePrincipalName: host/ldaptest2computer12
654 servicePrincipalName: host/ldaptest2computer13
655 servicePrincipalName: host/ldaptest2computer14
656 servicePrincipalName: host/ldaptest2computer15
657 servicePrincipalName: host/ldaptest2computer16
658 servicePrincipalName: host/ldaptest2computer17
659 servicePrincipalName: host/ldaptest2computer18
660 servicePrincipalName: host/ldaptest2computer19
661 servicePrincipalName: host/ldaptest2computer20
662 servicePrincipalName: host/ldaptest2computer21
663 servicePrincipalName: host/ldaptest2computer22
664 servicePrincipalName: host/ldaptest2computer23
665 servicePrincipalName: host/ldaptest2computer24
666 servicePrincipalName: host/ldaptest2computer25
667 servicePrincipalName: host/ldaptest2computer26
668 servicePrincipalName: host/ldaptest2computer27
669 servicePrincipalName: host/ldaptest2computer28
670 servicePrincipalName: host/ldaptest2computer29
671 """)
672
673         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
674                          attrs=["servicePrincipalName;range=0-*"])
675         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
676         #print len(res[0]["servicePrincipalName;range=0-*"])
677         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
678
679         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
680         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
681             # print res[0]["servicePrincipalName;range=0-19"].length
682         self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
683
684
685         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
686         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
687         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
688
689         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
690         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
691         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
692
693         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
694         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
695         self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
696
697
698         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
699         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
700         self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
701         # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
702
703         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
704         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
705         self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19)
706             # print res[0]["servicePrincipalName;range=11-*"][18]
707             # print pos_11
708             # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
709
710         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
711         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
712         self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5)
713             # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
714
715         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
716         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
717             # print res[0]["servicePrincipalName"][18]
718             # print pos_11
719         self.assertEquals(len(res[0]["servicePrincipalName"]), 30)
720             # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11)
721
722         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
723         ldb.add({
724             "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
725             "objectClass": ["person", "user"],
726             "cn": "LDAPtestUSER2",
727             "givenname": "testy",
728             "sn": "ldap user2"})
729
730         print "Testing Ambigious Name Resolution"
731         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
732         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
733         self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
734
735         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
736         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
737         self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
738
739         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
740         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
741         self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
742
743         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
744         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
745         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
746
747         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
748         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
749         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
750
751         # Testing ldb.search for (&(anr=testy)(objectClass=user))
752         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
753         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
754
755         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
756         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
757         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
758
759         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
760 # this test disabled for the moment, as anr with == tests are not understood
761 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
762 #        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
763
764         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
765         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
766         self.assertEquals(res[0]["name"][0], "ldaptestuser")
767
768         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
769 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
770 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
771
772         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
773         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
774         self.assertEquals(res[0]["name"][0], "ldaptestuser")
775
776         # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
777         res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
778         self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
779
780         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
781         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
782         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
783
784         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
785 #        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
786 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
787
788         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
789         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
790         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
791
792         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
793 #        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
794 #        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
795
796         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
797         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
798         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
799
800         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
801 #        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
802 #        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
803
804         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
805         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
806         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
807
808         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
809 #        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
810 #        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
811
812         print "Testing Renames"
813
814         attrs = ["objectGUID", "objectSid"]
815         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
816         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
817         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
818
819         # Check rename works with extended/alternate DN forms
820         ldb.rename("<SID=" + ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0]) + ">" , "cn=ldaptestUSER3,cn=users," + self.base_dn)
821
822         print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))"
823         res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
824         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
825
826         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
827         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
828         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
829
830         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
831         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
832         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
833
834         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
835         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
836         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
837
838         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
839         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
840         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
841
842         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
843         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
844         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
845
846         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
847         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
848         self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
849
850         # This is a Samba special, and does not exist in real AD
851         #    print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
852         #    res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
853         #    if (res.error != 0 || len(res) != 1) {
854         #        print "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
855         #        self.assertEquals(len(res), 1)
856         #    }
857         #    self.assertEquals(res[0].dn, ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
858         #    self.assertEquals(res[0].cn, "ldaptestUSER3")
859         #    self.assertEquals(res[0].name, "ldaptestUSER3")
860
861         print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
862         res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
863         self.assertEquals(len(res), 1, "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
864         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
865         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
866         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
867
868         # ensure we cannot add it again
869         try:
870             ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
871                       "objectClass": ["person", "user"],
872                       "cn": "LDAPtestUSER3"})
873             self.fail()
874         except LdbError, (num, _):
875             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
876
877         # rename back
878         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
879
880         # ensure we cannot rename it twice
881         try:
882             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
883                        "cn=ldaptestuser2,cn=users," + self.base_dn)
884             self.fail()
885         except LdbError, (num, _):
886             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
887
888         # ensure can now use that name
889         ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
890                       "objectClass": ["person", "user"],
891                       "cn": "LDAPtestUSER3"})
892
893         # ensure we now cannot rename
894         try:
895             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
896             self.fail()
897         except LdbError, (num, _):
898             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
899         try:
900             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
901             self.fail()
902         except LdbError, (num, _):
903             self.assertTrue(num in (71, 64))
904
905         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
906
907         ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
908
909         self.delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
910
911         ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
912
913         print "Testing subtree renames"
914
915         ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
916                  "objectClass": "container"})
917
918         ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
919                  "objectClass": ["person", "user"],
920                  "cn": "LDAPtestUSER4"})
921
922         ldb.modify_ldif("""
923 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
924 changetype: modify
925 add: member
926 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
927 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
928 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
929 """)
930
931         print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
932         ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
933
934         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))"
935         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
936         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
937
938         print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
939         try:
940             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
941                     expression="(&(cn=ldaptestuser4)(objectClass=user))",
942                     scope=SCOPE_SUBTREE)
943             self.fail(res)
944         except LdbError, (num, _):
945             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
946
947         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
948         try:
949             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
950                     expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
951             self.fail()
952         except LdbError, (num, _):
953             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
954
955         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
956         res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
957         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
958
959         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
960         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
961
962         time.sleep(4)
963
964         print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
965         res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
966         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?")
967
968         print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
969         try:
970             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
971             self.fail()
972         except LdbError, (num, _):
973             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
974
975         print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
976         try:
977             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
978             self.fail()
979         except LdbError, (num, _):
980             self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER))
981
982         print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
983         try:
984             ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
985             self.fail()
986         except LdbError, (num, _):
987             self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
988
989         print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
990         res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
991         self.assertEquals(len(res), 1)
992         res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
993         self.assertEquals(len(res), 0)
994
995         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
996         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
997         # FIXME: self.assertEquals(len(res), 0)
998
999         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
1000         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
1001         # FIXME: self.assertEquals(len(res), 0)
1002
1003         print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
1004         ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
1005         print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
1006         ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
1007
1008         ldb.add({"dn": "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn, "objectClass": "user"})
1009
1010         ldb.add({"dn": "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn, "objectClass": "user"})
1011
1012         print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
1013         res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
1014         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1015
1016         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1017         self.assertEquals(str(res[0]["cn"]), "ldaptestuser")
1018         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1019         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user"]))
1020         self.assertTrue("objectGUID" in res[0])
1021         self.assertTrue("whenCreated" in res[0])
1022         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
1023         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1024         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1025         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1026         self.assertEquals(len(res[0]["memberOf"]), 1)
1027
1028         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
1029         res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1030         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1031
1032         self.assertEquals(res[0].dn, res2[0].dn)
1033
1034         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
1035         res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1036         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
1037
1038         self.assertEquals(res[0].dn, res3[0].dn)
1039
1040         if gc_ldb is not None:
1041             print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
1042             res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1043             self.assertEquals(len(res3gc), 1)
1044
1045             self.assertEquals(res[0].dn, res3gc[0].dn)
1046
1047         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
1048
1049         res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
1050         self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
1051
1052         self.assertEquals(res[0].dn, res3control[0].dn)
1053
1054         ldb.delete(res[0].dn)
1055
1056         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
1057         res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
1058         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1059
1060         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
1061         self.assertEquals(str(res[0]["cn"]), "ldaptestcomputer")
1062         self.assertEquals(str(res[0]["name"]), "ldaptestcomputer")
1063         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user", "computer"]))
1064         self.assertTrue("objectGUID" in res[0])
1065         self.assertTrue("whenCreated" in res[0])
1066         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
1067         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
1068         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1069         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1070         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1071         self.assertEquals(len(res[0]["memberOf"]), 1)
1072
1073         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
1074         res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1075         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1076
1077         self.assertEquals(res[0].dn, res2[0].dn)
1078
1079         if gc_ldb is not None:
1080             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
1081             res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1082             self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
1083
1084             self.assertEquals(res[0].dn, res2gc[0].dn)
1085
1086         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
1087         res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1088         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1089
1090         self.assertEquals(res[0].dn, res3[0].dn)
1091
1092         if gc_ldb is not None:
1093             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
1094             res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1095             self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
1096
1097             self.assertEquals(res[0].dn, res3gc[0].dn)
1098
1099         print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
1100         res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1101         self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1102
1103         self.assertEquals(res[0].dn, res4[0].dn)
1104
1105         print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
1106         res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1107         self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1108
1109         self.assertEquals(res[0].dn, res5[0].dn)
1110
1111         print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
1112         res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
1113         self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
1114
1115         self.assertEquals(res[0].dn, res6[0].dn)
1116
1117         ldb.delete("<GUID=" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + ">")
1118
1119         print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
1120         res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
1121         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
1122
1123         self.assertEquals(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn)
1124         self.assertEquals(str(res[0]["cn"]), "ldaptest2computer")
1125         self.assertEquals(str(res[0]["name"]), "ldaptest2computer")
1126         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user", "computer"])
1127         self.assertTrue("objectGUID" in res[0])
1128         self.assertTrue("whenCreated" in res[0])
1129         self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
1130         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
1131         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT)
1132
1133         ldb.delete("<SID=" + ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + ">")
1134
1135         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"]
1136         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
1137         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
1138         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
1139
1140         self.assertEquals(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1141         self.assertEquals(str(res_user[0]["cn"]), "ldaptestuser2")
1142         self.assertEquals(str(res_user[0]["name"]), "ldaptestuser2")
1143         self.assertEquals(list(res_user[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
1144         self.assertTrue("objectSid" in res_user[0])
1145         self.assertTrue("objectGUID" in res_user[0])
1146         self.assertTrue("whenCreated" in res_user[0])
1147         self.assertTrue("nTSecurityDescriptor" in res_user[0])
1148         self.assertTrue("allowedAttributes" in res_user[0])
1149         self.assertTrue("allowedAttributesEffective" in res_user[0])
1150         self.assertEquals(res_user[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1151
1152         ldaptestuser2_sid = res_user[0]["objectSid"][0]
1153         ldaptestuser2_guid = res_user[0]["objectGUID"][0]
1154
1155         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"]
1156         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
1157         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1158         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1159
1160         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1161         self.assertEquals(str(res[0]["cn"]), "ldaptestgroup2")
1162         self.assertEquals(str(res[0]["name"]), "ldaptestgroup2")
1163         self.assertEquals(list(res[0]["objectClass"]), ["top", "group"])
1164         self.assertTrue("objectGUID" in res[0])
1165         self.assertTrue("objectSid" in res[0])
1166         self.assertTrue("whenCreated" in res[0])
1167         self.assertTrue("nTSecurityDescriptor" in res[0])
1168         self.assertTrue("allowedAttributes" in res[0])
1169         self.assertTrue("allowedAttributesEffective" in res[0])
1170         memberUP = []
1171         for m in res[0]["member"]:
1172             memberUP.append(m.upper())
1173         self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
1174
1175         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"])
1176         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1177
1178         print res[0]["member"]
1179         memberUP = []
1180         for m in res[0]["member"]:
1181             memberUP.append(m.upper())
1182         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()
1183
1184         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)
1185
1186         print "Testing Linked attribute behaviours"
1187         ldb.modify_ldif("""
1188 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1189 changetype: modify
1190 replace: member
1191 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
1192 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1193 """)
1194
1195         ldb.modify_ldif("""
1196 dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1197 changetype: modify
1198 replace: member
1199 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1200 """)
1201
1202         ldb.modify_ldif("""
1203 dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
1204 changetype: modify
1205 delete: member
1206 """)
1207
1208         ldb.modify_ldif("""
1209 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1210 changetype: modify
1211 add: member
1212 member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1213 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1214 """)
1215
1216         ldb.modify_ldif("""
1217 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1218 changetype: modify
1219 replace: member
1220 """)
1221
1222         ldb.modify_ldif("""
1223 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1224 changetype: modify
1225 add: member
1226 member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
1227 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1228 """)
1229
1230         ldb.modify_ldif("""
1231 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1232 changetype: modify
1233 delete: member
1234 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1235 """)
1236
1237         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1238         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1239
1240         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1241         self.assertEquals(res[0]["member"][0], ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1242         self.assertEquals(len(res[0]["member"]), 1)
1243
1244         ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
1245
1246         time.sleep(4)
1247
1248         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
1249         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
1250         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1251         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
1252
1253         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1254         self.assertTrue("member" not in res[0])
1255
1256         print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
1257         res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1258         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1259
1260         self.assertEquals(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
1261         self.assertEquals(str(res[0]["cn"]), "ldaptestutf8user èùéìòà")
1262         self.assertEquals(str(res[0]["name"]), "ldaptestutf8user èùéìòà")
1263         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
1264         self.assertTrue("objectGUID" in res[0])
1265         self.assertTrue("whenCreated" in res[0])
1266
1267         ldb.delete(res[0].dn)
1268
1269         print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
1270         res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
1271         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
1272
1273         ldb.delete(res[0].dn)
1274
1275         ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1276
1277         print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
1278         res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1279
1280         #FIXME: self.assert len(res) == 1, "Could not find (expect space collapse, win2k3 fails) (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
1281
1282         print "Testing that we can't get at the configuration DN from the main search base"
1283         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1284         self.assertEquals(len(res), 0)
1285
1286         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"
1287         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
1288         self.assertTrue(len(res) > 0)
1289
1290         if gc_ldb is not None:
1291             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"
1292
1293             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
1294             self.assertTrue(len(res) > 0)
1295
1296             print "Testing that we do find configuration elements in the global catlog"
1297             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1298             self.assertTrue(len(res) > 0)
1299
1300             print "Testing that we do find configuration elements and user elements at the same time"
1301             res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
1302             self.assertTrue(len(res) > 0)
1303
1304             print "Testing that we do find configuration elements in the global catlog, with the configuration basedn"
1305             res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1306             self.assertTrue(len(res) > 0)
1307
1308         print "Testing that we can get at the configuration DN on the main LDAP port"
1309         res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1310         self.assertTrue(len(res) > 0)
1311
1312         print "Testing objectCategory canonacolisation"
1313         res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
1314         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
1315         self.assertTrue(len(res) != 0)
1316
1317         res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
1318         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
1319         self.assertTrue(len(res) != 0)
1320
1321         print "Testing objectClass attribute order on "+ self.base_dn
1322         res = ldb.search(expression="objectClass=domain", base=self.base_dn,
1323                          scope=SCOPE_BASE, attrs=["objectClass"])
1324         self.assertEquals(len(res), 1)
1325
1326         self.assertEquals(list(res[0]["objectClass"]), ["top", "domain", "domainDNS"])
1327
1328     #  check enumeration
1329
1330         print "Testing ldb.search for objectCategory=person"
1331         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
1332         self.assertTrue(len(res) > 0)
1333
1334         print "Testing ldb.search for objectCategory=person with domain scope control"
1335         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1336         self.assertTrue(len(res) > 0)
1337
1338         print "Testing ldb.search for objectCategory=user"
1339         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
1340         self.assertTrue(len(res) > 0)
1341
1342         print "Testing ldb.search for objectCategory=user with domain scope control"
1343         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1344         self.assertTrue(len(res) > 0)
1345
1346         print "Testing ldb.search for objectCategory=group"
1347         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
1348         self.assertTrue(len(res) > 0)
1349
1350         print "Testing ldb.search for objectCategory=group with domain scope control"
1351         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1352         self.assertTrue(len(res) > 0)
1353
1354         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1355         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1356         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
1357         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=users," + self.base_dn)
1358         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1359         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1360         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1361         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
1362         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
1363         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn)
1364         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn)
1365         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
1366         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
1367
1368     def test_security_descriptor_add(self):
1369         """ Testing ldb.add_ldif() for nTSecurityDescriptor """
1370         user_name = "testdescriptoruser1"
1371         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1372         #
1373         # Test add_ldif() with SDDL security descriptor input
1374         #
1375         self.delete_force(self.ldb, user_dn)
1376         try:
1377             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1378             self.ldb.add_ldif("""
1379 dn: """ + user_dn + """
1380 objectclass: user
1381 sAMAccountName: """ + user_name + """
1382 nTSecurityDescriptor: """ + sddl)
1383             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1384             desc = res[0]["nTSecurityDescriptor"][0]
1385             desc = ndr_unpack( security.descriptor, desc )
1386             desc_sddl = desc.as_sddl( self.domain_sid )
1387             self.assertEqual(desc_sddl, sddl)
1388         finally:
1389             self.delete_force(self.ldb, user_dn)
1390         #
1391         # Test add_ldif() with BASE64 security descriptor
1392         #
1393         try:
1394             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1395             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1396             desc_binary = ndr_pack(desc)
1397             desc_base64 = base64.b64encode(desc_binary)
1398             self.ldb.add_ldif("""
1399 dn: """ + user_dn + """
1400 objectclass: user
1401 sAMAccountName: """ + user_name + """
1402 nTSecurityDescriptor:: """ + desc_base64)
1403             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1404             desc = res[0]["nTSecurityDescriptor"][0]
1405             desc = ndr_unpack(security.descriptor, desc)
1406             desc_sddl = desc.as_sddl(self.domain_sid)
1407             self.assertEqual(desc_sddl, sddl)
1408         finally:
1409             self.delete_force(self.ldb, user_dn)
1410
1411     def test_security_descriptor_add_neg(self):
1412         """Test add_ldif() with BASE64 security descriptor input using WRONG domain SID
1413             Negative test
1414         """
1415         user_name = "testdescriptoruser1"
1416         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1417         self.delete_force(self.ldb, user_dn)
1418         try:
1419             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1420             desc = security.descriptor.from_sddl(sddl, security.dom_sid('S-1-5-21'))
1421             desc_base64 = base64.b64encode( ndr_pack(desc) )
1422             self.ldb.add_ldif("""
1423 dn: """ + user_dn + """
1424 objectclass: user
1425 sAMAccountName: """ + user_name + """
1426 nTSecurityDescriptor:: """ + desc_base64)
1427             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1428             print res
1429             self.assertRaises(KeyError, lambda: res[0]["nTSecurityDescriptor"])
1430         finally:
1431             self.delete_force(self.ldb, user_dn)
1432
1433     def test_security_descriptor_modify(self):
1434         """ Testing ldb.modify_ldif() for nTSecurityDescriptor """
1435         user_name = "testdescriptoruser2"
1436         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1437         #
1438         # Delete user object and test modify_ldif() with SDDL security descriptor input
1439         # Add ACE to the original descriptor test
1440         #
1441         try:
1442             self.delete_force(self.ldb, user_dn)
1443             self.ldb.add_ldif("""
1444 dn: """ + user_dn + """
1445 objectclass: user
1446 sAMAccountName: """ + user_name)
1447             # Modify descriptor
1448             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1449             desc = res[0]["nTSecurityDescriptor"][0]
1450             desc = ndr_unpack(security.descriptor, desc)
1451             desc_sddl = desc.as_sddl(self.domain_sid)
1452             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
1453             mod = """
1454 dn: """ + user_dn + """
1455 changetype: modify
1456 replace: nTSecurityDescriptor
1457 nTSecurityDescriptor: """ + sddl
1458             self.ldb.modify_ldif(mod)
1459             # Read modified descriptor
1460             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1461             desc = res[0]["nTSecurityDescriptor"][0]
1462             desc = ndr_unpack(security.descriptor, desc)
1463             desc_sddl = desc.as_sddl(self.domain_sid)
1464             self.assertEqual(desc_sddl, sddl)
1465         finally:
1466             self.delete_force(self.ldb, user_dn)
1467         #
1468         # Test modify_ldif() with SDDL security descriptor input
1469         # New desctiptor test
1470         #
1471         try:
1472             self.ldb.add_ldif("""
1473 dn: """ + user_dn + """
1474 objectclass: user
1475 sAMAccountName: """ + user_name)
1476             # Modify descriptor
1477             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1478             mod = """
1479 dn: """ + user_dn + """
1480 changetype: modify
1481 replace: nTSecurityDescriptor
1482 nTSecurityDescriptor: """ + sddl
1483             self.ldb.modify_ldif(mod)
1484             # Read modified descriptor
1485             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1486             desc = res[0]["nTSecurityDescriptor"][0]
1487             desc = ndr_unpack(security.descriptor, desc)
1488             desc_sddl = desc.as_sddl(self.domain_sid)
1489             self.assertEqual(desc_sddl, sddl)
1490         finally:
1491             self.delete_force(self.ldb, user_dn)
1492         #
1493         # Test modify_ldif() with BASE64 security descriptor input
1494         # Add ACE to the original descriptor test
1495         #
1496         try:
1497             self.ldb.add_ldif("""
1498 dn: """ + user_dn + """
1499 objectclass: user
1500 sAMAccountName: """ + user_name)
1501             # Modify descriptor
1502             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1503             desc = res[0]["nTSecurityDescriptor"][0]
1504             desc = ndr_unpack(security.descriptor, desc)
1505             desc_sddl = desc.as_sddl(self.domain_sid)
1506             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
1507             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1508             desc_base64 = base64.b64encode(ndr_pack(desc))
1509             mod = """
1510 dn: """ + user_dn + """
1511 changetype: modify
1512 replace: nTSecurityDescriptor
1513 nTSecurityDescriptor:: """ + desc_base64
1514             self.ldb.modify_ldif(mod)
1515             # Read modified descriptor
1516             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1517             desc = res[0]["nTSecurityDescriptor"][0]
1518             desc = ndr_unpack(security.descriptor, desc)
1519             desc_sddl = desc.as_sddl(self.domain_sid)
1520             self.assertEqual(desc_sddl, sddl)
1521         finally:
1522             self.delete_force(self.ldb, user_dn)
1523         #
1524         # Test modify_ldif() with BASE64 security descriptor input
1525         # New descriptor test
1526         #
1527         try:
1528             self.delete_force(self.ldb, user_dn)
1529             self.ldb.add_ldif("""
1530 dn: """ + user_dn + """
1531 objectclass: user
1532 sAMAccountName: """ + user_name)
1533             # Modify descriptor
1534             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1535             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1536             desc_base64 = base64.b64encode(ndr_pack(desc))
1537             mod = """
1538 dn: """ + user_dn + """
1539 changetype: modify
1540 replace: nTSecurityDescriptor
1541 nTSecurityDescriptor:: """ + desc_base64
1542             self.ldb.modify_ldif(mod)
1543             # Read modified descriptor
1544             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1545             desc = res[0]["nTSecurityDescriptor"][0]
1546             desc = ndr_unpack(security.descriptor, desc)
1547             desc_sddl = desc.as_sddl(self.domain_sid)
1548             self.assertEqual(desc_sddl, sddl)
1549         finally:
1550             self.delete_force(self.ldb, user_dn)
1551
1552 class BaseDnTests(unittest.TestCase):
1553     def setUp(self):
1554         self.ldb = ldb
1555
1556     def test_rootdse_attrs(self):
1557         """Testing for all rootDSE attributes"""
1558         res = self.ldb.search(scope=SCOPE_BASE, attrs=[])
1559         self.assertEquals(len(res), 1)
1560
1561     def test_highestcommittedusn(self):
1562         """Testing for highestCommittedUSN"""
1563         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
1564         self.assertEquals(len(res), 1)
1565         self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
1566
1567     def test_netlogon(self):
1568         """Testing for netlogon via LDAP"""
1569         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
1570         self.assertEquals(len(res), 0)
1571
1572     def test_netlogon_highestcommitted_usn(self):
1573         """Testing for netlogon and highestCommittedUSN via LDAP"""
1574         res = self.ldb.search("", scope=SCOPE_BASE,
1575                 attrs=["netlogon", "highestCommittedUSN"])
1576         self.assertEquals(len(res), 0)
1577
1578 class SchemaTests(unittest.TestCase):
1579     def delete_force(self, ldb, dn):
1580         try:
1581             ldb.delete(dn)
1582         except LdbError, (num, _):
1583             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1584
1585     def find_schemadn(self, ldb):
1586         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
1587         self.assertEquals(len(res), 1)
1588         return res[0]["schemaNamingContext"][0]
1589
1590     def find_basedn(self, ldb):
1591         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
1592                          attrs=["defaultNamingContext"])
1593         self.assertEquals(len(res), 1)
1594         return res[0]["defaultNamingContext"][0]
1595
1596     def setUp(self):
1597         self.ldb = ldb
1598         self.schema_dn = self.find_schemadn(ldb)
1599         self.base_dn = self.find_basedn(ldb)
1600
1601     def test_generated_schema(self):
1602         """Testing we can read the generated schema via LDAP"""
1603         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
1604                 attrs=["objectClasses", "attributeTypes", "dITContentRules"])
1605         self.assertEquals(len(res), 1)
1606         self.assertTrue("dITContentRules" in res[0])
1607         self.assertTrue("objectClasses" in res[0])
1608         self.assertTrue("attributeTypes" in res[0])
1609
1610     def test_generated_schema_is_operational(self):
1611         """Testing we don't get the generated schema via LDAP by default"""
1612         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
1613                 attrs=["*"])
1614         self.assertEquals(len(res), 1)
1615         self.assertFalse("dITContentRules" in res[0])
1616         self.assertFalse("objectClasses" in res[0])
1617         self.assertFalse("attributeTypes" in res[0])
1618
1619     def test_schemaUpdateNow(self):
1620         """Testing schemaUpdateNow"""
1621         class_name = "test-class" + time.strftime("%s", time.gmtime())
1622         class_ldap_display_name = class_name.replace("-", "")
1623         object_name = "obj" + time.strftime("%s", time.gmtime())
1624
1625         ldif = """
1626 dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
1627 lDAPDisplayName: """ + class_ldap_display_name + """
1628 objectClass: top
1629 objectClass: classSchema
1630 adminDescription: """ + class_name + """
1631 adminDisplayName: """ + class_name + """
1632 cn: """ + class_name + """
1633 objectCategory: CN=Class-Schema,""" + self.schema_dn + """
1634 defaultObjectCategory: CN=%s,%s""" % (class_name, self.schema_dn) + """
1635 distinguishedName: CN=%s,%s""" % (class_name, self.schema_dn) + """
1636 governsID: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
1637 instanceType: 4
1638 name: """ + class_name + """
1639 objectClassCategory: 1
1640 subClassOf: organizationalPerson
1641 systemFlags: 16
1642 rDNAttID: cn
1643 systemMustContain: cn
1644 systemOnly: FALSE
1645 """
1646         self.ldb.add_ldif(ldif)
1647         ldif = """
1648 dn:
1649 changetype: modify
1650 add: schemaUpdateNow
1651 schemaUpdateNow: 1
1652 """
1653         self.ldb.modify_ldif(ldif)
1654         ldif = """
1655 dn: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1656 objectClass: organizationalPerson
1657 objectClass: person
1658 objectClass: """ + class_ldap_display_name + """
1659 objectClass: top
1660 cn: """ + object_name + """
1661 instanceType: 4
1662 objectCategory: CN=%s,%s"""% (class_name, self.schema_dn) + """
1663 distinguishedName: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1664 name: """ + object_name + """
1665 """
1666         self.ldb.add_ldif(ldif)
1667         # Search for created objectClass
1668         res = []
1669         res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
1670         self.assertNotEqual(res, [])
1671
1672         res = []
1673         res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["*"])
1674         self.assertNotEqual(res, [])
1675         # Delete the object
1676         self.delete_force(self.ldb, "cn=%s,cn=Users,%s" % (object_name, self.base_dn))
1677
1678 if not "://" in host:
1679     host = "ldap://%s" % host
1680
1681 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
1682 gc_ldb = Ldb("%s:3268" % host, credentials=creds,
1683              session_info=system_session(), lp=lp)
1684
1685 runner = SubunitTestRunner()
1686 rc = 0
1687 if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
1688     rc = 1
1689 if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
1690     rc = 1
1691 if not runner.run(unittest.makeSuite(SchemaTests)).wasSuccessful():
1692     rc = 1
1693 sys.exit(rc)