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