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