Test for schemaUpdateNow command
[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
10 sys.path.append("bin/python")
11 sys.path.append("../lib/subunit/python")
12
13 import samba.getopt as options
14
15 from samba.auth import system_session
16 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
17 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
18 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
19 from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
20 from samba import Ldb
21 from subunit import SubunitTestRunner
22 from samba import param
23 import unittest
24
25 parser = optparse.OptionParser("ldap [options] <host>")
26 sambaopts = options.SambaOptions(parser)
27 parser.add_option_group(sambaopts)
28 parser.add_option_group(options.VersionOptions(parser))
29 # use command line creds if available
30 credopts = options.CredentialsOptions(parser)
31 parser.add_option_group(credopts)
32 opts, args = parser.parse_args()
33
34 if len(args) < 1:
35     parser.print_usage()
36     sys.exit(1)
37
38 host = args[0]
39
40 lp = sambaopts.get_loadparm()
41 creds = credopts.get_credentials(lp)
42
43 class BasicTests(unittest.TestCase):
44     def delete_force(self, ldb, dn):
45         try:
46             ldb.delete(dn)
47         except LdbError, (num, _):
48             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
49
50     def find_basedn(self, ldb):
51         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
52                          attrs=["defaultNamingContext"])
53         self.assertEquals(len(res), 1)
54         return res[0]["defaultNamingContext"][0]
55
56     def find_configurationdn(self, ldb):
57         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["configurationNamingContext"])
58         self.assertEquals(len(res), 1)
59         return res[0]["configurationNamingContext"][0]
60
61     def find_schemadn(self, ldb):
62         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
63         self.assertEquals(len(res), 1)
64         return res[0]["schemaNamingContext"][0]
65
66     def setUp(self):
67         self.ldb = ldb
68         self.gc_ldb = gc_ldb
69         self.base_dn = self.find_basedn(ldb)
70         self.configuration_dn = self.find_configurationdn(ldb)
71         self.schema_dn = self.find_schemadn(ldb)
72
73         print "baseDN: %s\n" % self.base_dn
74
75         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
76         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
77         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
78         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
79         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn)
80         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn)
81         self.delete_force(self.ldb, "cn=parentguidtest,cn=users," + self.base_dn)
82         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
83         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
84
85     def test_group_add_invalid_member(self):
86         """Testing group add with invalid member"""
87         try:
88             self.ldb.add({
89                 "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
90                 "objectclass": "group",
91                 "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
92             self.fail()
93         except LdbError, (num, _):
94             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
95
96     def test_parentGUID(self):
97         """Test parentGUID behaviour"""
98         print "Testing parentGUID behaviour\n"
99         
100         self.ldb.add({
101             "dn": "cn=parentguidtest,cn=users," + self.base_dn,
102             "objectclass":"user",
103             "samaccountname":"parentguidtest"});
104         res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE,
105                           attrs=["parentGUID"]);
106         res2 = ldb.search(base="cn=users," + self.base_dn,scope=SCOPE_BASE,
107                           attrs=["objectGUID"]);
108         self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]);
109
110         """Test parentGUID behaviour"""
111         print "Testing parentGUID behaviour on rename\n"
112
113         self.ldb.add({
114             "dn": "cn=testotherusers," + self.base_dn,
115             "objectclass":"container"});
116         res1 = ldb.search(base="cn=testotherusers," + self.base_dn,scope=SCOPE_BASE,
117                           attrs=["objectGUID"]);
118         ldb.rename("cn=parentguidtest,cn=users," + self.base_dn,
119                    "cn=parentguidtest,cn=testotherusers," + self.base_dn);
120         res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn,
121                           scope=SCOPE_BASE,
122                           attrs=["parentGUID"]);
123         self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]);
124         ldb.delete("cn=parentguidtest,cn=testotherusers," + self.base_dn)
125         ldb.delete("cn=testotherusers," + self.base_dn)
126
127     def test_groupType(self):
128         """Test groupType behaviour 
129         (should appear to be casted to a 32 bit signed integer before comparsion)"""
130         print "Testing groupType behaviour\n"
131         
132         res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
133                           attrs=["groupType"], expression="groupType=2147483650");
134
135         res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
136                           attrs=["groupType"], expression="groupType=-2147483646");
137
138         self.assertEquals(len(res1), len(res2))
139
140         self.assertTrue(res1.count > 0)
141
142         self.assertEquals(res1[0]["groupType"][0], "-2147483646")
143
144     def test_all(self):
145         """Basic tests"""
146
147         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
148
149         print "Testing user add"
150         ldb.add({
151         "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
152         "objectclass": ["user", "person"],
153         "cN": "LDAPtestUSER",
154         "givenname": "ldap",
155         "sn": "testy"})
156
157         ldb.add({
158             "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
159             "objectclass": "group",
160             "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
161
162         self.delete_force(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
163         ldb.add({
164             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
165             "objectclass": "computer",
166             "cN": "LDAPtestCOMPUTER"})
167
168         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
169         ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
170             "objectClass": "computer",
171             "cn": "LDAPtest2COMPUTER",
172             "userAccountControl": "4096",
173             "displayname": "ldap testy"})
174
175         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
176         try:
177             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
178                      "objectClass": "computer",
179                      "cn": "LDAPtest2COMPUTER"
180                      })
181             self.fail()
182         except LdbError, (num, _):
183             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
184
185         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
186         try:
187             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
188                      "objectClass": "computer",
189                      "cn": "ldaptestcomputer3",
190                      "sAMAccountType": "805306368"
191                 })
192             self.fail()
193         except LdbError, (num, _):
194             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
195
196         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
197         try:
198             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
199                      "objectClass": "computer",
200                      "cn": "ldaptestcomputer3",
201                      "userAccountControl": "0"
202                 })
203             self.fail()
204         except LdbError, (num, _):
205             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
206
207         self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
208         try:
209             ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn,
210                      "objectClass": "user",
211                      "cn": "LDAPtestuser7",
212                      "userAccountControl": "0"
213                 })
214             self.fail()
215         except LdbError, (num, _):
216             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
217
218         self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
219
220         ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn,
221                  "objectClass": "user",
222                  "cn": "LDAPtestuser7",
223                  "userAccountControl": "2"
224                  })
225
226         self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
227
228         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
229         ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
230                  "objectClass": "computer",
231                  "cn": "LDAPtestCOMPUTER3"
232                  })
233
234         print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
235         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
236         self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
237
238         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn));
239         self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3");
240         self.assertEquals(res[0]["name"][0], "ldaptestcomputer3");
241         self.assertEquals(res[0]["objectClass"][0], "top");
242         self.assertEquals(res[0]["objectClass"][1], "person");
243         self.assertEquals(res[0]["objectClass"][2], "organizationalPerson");
244         self.assertEquals(res[0]["objectClass"][3], "user");
245         self.assertEquals(res[0]["objectClass"][4], "computer");
246         self.assertTrue("objectGUID" in res[0])
247         self.assertTrue("whenCreated" in res[0])
248         self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
249         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
250         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368);
251         self.assertEquals(int(res[0]["userAccountControl"][0]), 546);
252
253         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
254
255         print "Testing attribute or value exists behaviour"
256         try:
257             ldb.modify_ldif("""
258 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
259 changetype: modify
260 replace: servicePrincipalName
261 servicePrincipalName: host/ldaptest2computer
262 servicePrincipalName: host/ldaptest2computer
263 servicePrincipalName: cifs/ldaptest2computer
264 """)
265             self.fail()
266         except LdbError, (num, msg):
267             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
268
269         ldb.modify_ldif("""
270 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
271 changetype: modify
272 replace: servicePrincipalName
273 servicePrincipalName: host/ldaptest2computer
274 servicePrincipalName: cifs/ldaptest2computer
275 """)
276         try:
277             ldb.modify_ldif("""
278 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
279 changetype: modify
280 add: servicePrincipalName
281 servicePrincipalName: host/ldaptest2computer
282 """)
283             self.fail()
284         except LdbError, (num, msg):
285             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
286
287         print "Testing ranged results"
288         ldb.modify_ldif("""
289 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
290 changetype: modify
291 replace: servicePrincipalName
292 """)
293
294         ldb.modify_ldif("""
295 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
296 changetype: modify
297 add: servicePrincipalName
298 servicePrincipalName: host/ldaptest2computer0
299 servicePrincipalName: host/ldaptest2computer1
300 servicePrincipalName: host/ldaptest2computer2
301 servicePrincipalName: host/ldaptest2computer3
302 servicePrincipalName: host/ldaptest2computer4
303 servicePrincipalName: host/ldaptest2computer5
304 servicePrincipalName: host/ldaptest2computer6
305 servicePrincipalName: host/ldaptest2computer7
306 servicePrincipalName: host/ldaptest2computer8
307 servicePrincipalName: host/ldaptest2computer9
308 servicePrincipalName: host/ldaptest2computer10
309 servicePrincipalName: host/ldaptest2computer11
310 servicePrincipalName: host/ldaptest2computer12
311 servicePrincipalName: host/ldaptest2computer13
312 servicePrincipalName: host/ldaptest2computer14
313 servicePrincipalName: host/ldaptest2computer15
314 servicePrincipalName: host/ldaptest2computer16
315 servicePrincipalName: host/ldaptest2computer17
316 servicePrincipalName: host/ldaptest2computer18
317 servicePrincipalName: host/ldaptest2computer19
318 servicePrincipalName: host/ldaptest2computer20
319 servicePrincipalName: host/ldaptest2computer21
320 servicePrincipalName: host/ldaptest2computer22
321 servicePrincipalName: host/ldaptest2computer23
322 servicePrincipalName: host/ldaptest2computer24
323 servicePrincipalName: host/ldaptest2computer25
324 servicePrincipalName: host/ldaptest2computer26
325 servicePrincipalName: host/ldaptest2computer27
326 servicePrincipalName: host/ldaptest2computer28
327 servicePrincipalName: host/ldaptest2computer29
328 """)
329
330         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
331                          attrs=["servicePrincipalName;range=0-*"])
332         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
333         #print len(res[0]["servicePrincipalName;range=0-*"])
334         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
335
336         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
337         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
338             # print res[0]["servicePrincipalName;range=0-19"].length
339         self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
340
341
342         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
343         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
344         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
345
346         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
347         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
348         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
349
350         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
351         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
352         self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
353
354
355         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
356         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
357         self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
358         # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
359
360         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
361         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
362         self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19)
363             # print res[0]["servicePrincipalName;range=11-*"][18]
364             # print pos_11
365             # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
366
367         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
368         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
369         self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5)
370             # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
371
372         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
373         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
374             # print res[0]["servicePrincipalName"][18]
375             # print pos_11
376         self.assertEquals(len(res[0]["servicePrincipalName"]), 30)
377             # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11)
378
379         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
380         ldb.add({
381             "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
382             "objectClass": ["person", "user"],
383             "cn": "LDAPtestUSER2",
384             "givenname": "testy",
385             "sn": "ldap user2"})
386
387         print "Testing Ambigious Name Resolution"
388         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
389         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
390         self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
391
392         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
393         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
394         self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
395
396         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
397         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
398         self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
399
400         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
401         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
402         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
403
404         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
405         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
406         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
407
408         # Testing ldb.search for (&(anr=testy)(objectClass=user))
409         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
410         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
411
412         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
413         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
414         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
415
416         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
417 # this test disabled for the moment, as anr with == tests are not understood
418 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
419 #        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
420
421         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
422         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
423         self.assertEquals(res[0]["name"][0], "ldaptestuser")
424
425         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
426 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
427 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
428
429         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
430         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
431         self.assertEquals(res[0]["name"][0], "ldaptestuser")
432
433         # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
434         res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
435         self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
436
437         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
438         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
439         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
440
441         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
442 #        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
443 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
444
445         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
446         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
447         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
448
449         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
450 #        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
451 #        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
452
453         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
454         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
455         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
456
457         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
458 #        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
459 #        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
460
461         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
462         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
463         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
464
465         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
466 #        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
467 #        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
468
469         print "Testing Group Modifies"
470         ldb.modify_ldif("""
471 dn: cn=ldaptestgroup,cn=users,""" + self.base_dn + """
472 changetype: modify
473 add: member
474 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
475 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
476 """)
477
478         self.delete_force(ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
479
480         print "Testing adding non-existent user to a group"
481         try:
482             ldb.modify_ldif("""
483 dn: cn=ldaptestgroup,cn=users,""" + self.base_dn + """
484 changetype: modify
485 add: member
486 member: cn=ldaptestuser3,cn=users,""" + self.base_dn + """
487 """)
488             self.fail()
489         except LdbError, (num, _):
490             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
491
492         print "Testing Renames"
493
494         attrs = ["objectGUID", "objectSid"]
495         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
496         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
497         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
498
499         #Check rename works with extended/alternate DN forms
500         ldb.rename("<SID=" + ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0]) + ">" , "cn=ldaptestuser3,cn=users," + self.base_dn)
501
502         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
503
504         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestUSER3,cn=users," + self.base_dn)
505
506         print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))"
507         res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
508         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
509
510         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
511         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
512         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
513
514         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
515         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
516         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
517
518         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
519         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
520         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
521
522         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
523         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
524         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
525
526         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
527         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
528         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
529
530         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
531         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
532         self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
533
534         # This is a Samba special, and does not exist in real AD
535         #    print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
536         #    res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
537         #    if (res.error != 0 || len(res) != 1) {
538         #        print "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
539         #        self.assertEquals(len(res), 1)
540         #    }
541         #    self.assertEquals(res[0].dn, ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
542         #    self.assertEquals(res[0].cn, "ldaptestUSER3")
543         #    self.assertEquals(res[0].name, "ldaptestUSER3")
544
545         print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
546         res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
547         self.assertEquals(len(res), 1, "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
548         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
549         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
550         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
551
552         # ensure we cannot add it again
553         try:
554             ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
555                       "objectClass": ["person", "user"],
556                       "cn": "LDAPtestUSER3"})
557             self.fail()
558         except LdbError, (num, _):
559             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
560
561         # rename back
562         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
563
564         # ensure we cannnot rename it twice
565         try:
566             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
567                        "cn=ldaptestuser2,cn=users," + self.base_dn)
568             self.fail()
569         except LdbError, (num, _):
570             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
571
572         # ensure can now use that name
573         ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
574                       "objectClass": ["person", "user"],
575                       "cn": "LDAPtestUSER3"})
576
577         # ensure we now cannnot rename
578         try:
579             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
580             self.fail()
581         except LdbError, (num, _):
582             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
583         try:
584             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
585             self.fail()
586         except LdbError, (num, _):
587             self.assertTrue(num in (71, 64))
588
589         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
590
591         ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
592
593         self.delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
594
595         ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
596
597         print "Testing subtree Renames"
598
599         ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
600                  "objectClass": "container"})
601
602         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
603         ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
604                  "objectClass": ["person", "user"],
605                  "cn": "LDAPtestUSER4"})
606
607         ldb.modify_ldif("""
608 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
609 changetype: modify
610 add: member
611 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
612 """)
613
614         print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
615         ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
616
617         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))"
618         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
619         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
620
621         print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
622         try:
623             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
624                     expression="(&(cn=ldaptestuser4)(objectClass=user))",
625                     scope=SCOPE_SUBTREE)
626             self.fail(res)
627         except LdbError, (num, _):
628             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
629
630         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
631         try:
632             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
633                     expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
634             self.fail()
635         except LdbError, (num, _):
636             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
637
638         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
639         res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
640         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
641
642         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
643         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
644
645         time.sleep(4)
646
647         print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
648         res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
649         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?")
650
651         print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
652         try:
653             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
654             self.fail()
655         except LdbError, (num, _):
656             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
657
658         print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
659         try:
660             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
661             self.fail()
662         except LdbError, (num, _):
663             self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER))
664
665         print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
666         try:
667             ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
668             self.fail()
669         except LdbError, (num, _):
670             self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
671
672         print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
673         res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
674         self.assertEquals(len(res), 1)
675         res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
676         self.assertEquals(len(res), 0)
677
678         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
679         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
680         # FIXME: self.assertEquals(len(res), 0)
681
682         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
683         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
684         # FIXME: self.assertEquals(len(res), 0)
685
686         print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
687         ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
688         print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
689         ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
690
691         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn)
692         ldb.add({"dn": "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn, "objectClass": "user"})
693
694         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn)
695         ldb.add({"dn": "cn=ldaptestutf8user2  èùéìòà ,cn=users," + self.base_dn, "objectClass": "user"})
696
697         print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
698         res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
699         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
700
701         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
702         self.assertEquals(str(res[0]["cn"]), "ldaptestuser")
703         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
704         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user"]))
705         self.assertTrue("objectGUID" in res[0])
706         self.assertTrue("whenCreated" in res[0])
707         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
708         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368)
709         self.assertEquals(int(res[0]["userAccountControl"][0]), 546)
710         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
711         self.assertEquals(len(res[0]["memberOf"]), 1)
712
713         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
714         res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
715         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
716
717         self.assertEquals(res[0].dn, res2[0].dn)
718
719         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
720         res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
721         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
722
723         self.assertEquals(res[0].dn, res3[0].dn)
724
725         if gc_ldb is not None:
726             print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
727             res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
728             self.assertEquals(len(res3gc), 1)
729
730             self.assertEquals(res[0].dn, res3gc[0].dn)
731
732         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
733
734         res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
735         self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
736
737         self.assertEquals(res[0].dn, res3control[0].dn)
738
739         ldb.delete(res[0].dn)
740
741         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
742         res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
743         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
744
745         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
746         self.assertEquals(str(res[0]["cn"]), "ldaptestcomputer")
747         self.assertEquals(str(res[0]["name"]), "ldaptestcomputer")
748         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user", "computer"]))
749         self.assertTrue("objectGUID" in res[0])
750         self.assertTrue("whenCreated" in res[0])
751         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
752         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
753         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306368)
754         self.assertEquals(int(res[0]["userAccountControl"][0]), 546)
755         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
756         self.assertEquals(len(res[0]["memberOf"]), 1)
757
758         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
759         res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
760         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
761
762         self.assertEquals(res[0].dn, res2[0].dn)
763
764         if gc_ldb is not None:
765             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
766             res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
767             self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
768
769             self.assertEquals(res[0].dn, res2gc[0].dn)
770
771         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
772         res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
773         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
774
775         self.assertEquals(res[0].dn, res3[0].dn)
776
777         if gc_ldb is not None:
778             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
779             res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
780             self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
781
782             self.assertEquals(res[0].dn, res3gc[0].dn)
783
784         print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
785         res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
786         self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
787
788         self.assertEquals(res[0].dn, res4[0].dn)
789
790         print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
791         res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
792         self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
793
794         self.assertEquals(res[0].dn, res5[0].dn)
795
796         print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
797         res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
798         self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
799
800         self.assertEquals(res[0].dn, res6[0].dn)
801
802         ldb.delete("<GUID=" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + ">")
803
804         print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
805         res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
806         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
807
808         self.assertEquals(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn)
809         self.assertEquals(str(res[0]["cn"]), "ldaptest2computer")
810         self.assertEquals(str(res[0]["name"]), "ldaptest2computer")
811         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user", "computer"])
812         self.assertTrue("objectGUID" in res[0])
813         self.assertTrue("whenCreated" in res[0])
814         self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
815         self.assertEquals(int(res[0]["sAMAccountType"][0]), 805306369)
816         self.assertEquals(int(res[0]["userAccountControl"][0]), 4096)
817
818         ldb.delete("<SID=" + ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + ">")
819
820         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"]
821         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
822         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
823         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
824
825         self.assertEquals(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
826         self.assertEquals(str(res_user[0]["cn"]), "ldaptestuser2")
827         self.assertEquals(str(res_user[0]["name"]), "ldaptestuser2")
828         self.assertEquals(list(res_user[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
829         self.assertTrue("objectSid" in res_user[0])
830         self.assertTrue("objectGUID" in res_user[0])
831         self.assertTrue("whenCreated" in res_user[0])
832         self.assertTrue("nTSecurityDescriptor" in res_user[0])
833         self.assertTrue("allowedAttributes" in res_user[0])
834         self.assertTrue("allowedAttributesEffective" in res_user[0])
835         self.assertEquals(res_user[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
836
837         ldaptestuser2_sid = res_user[0]["objectSid"][0]
838         ldaptestuser2_guid = res_user[0]["objectGUID"][0]
839
840         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"]
841         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
842         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
843         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
844
845         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
846         self.assertEquals(str(res[0]["cn"]), "ldaptestgroup2")
847         self.assertEquals(str(res[0]["name"]), "ldaptestgroup2")
848         self.assertEquals(list(res[0]["objectClass"]), ["top", "group"])
849         self.assertTrue("objectGUID" in res[0])
850         self.assertTrue("objectSid" in res[0])
851         self.assertTrue("whenCreated" in res[0])
852         self.assertTrue("nTSecurityDescriptor" in res[0])
853         self.assertTrue("allowedAttributes" in res[0])
854         self.assertTrue("allowedAttributesEffective" in res[0])
855         memberUP = []
856         for m in res[0]["member"]:
857             memberUP.append(m.upper())
858         self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
859
860         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"])
861         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
862
863         print res[0]["member"]
864         memberUP = []
865         for m in res[0]["member"]:
866             memberUP.append(m.upper())
867         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()
868
869         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)
870
871         print "Testing Linked attribute behaviours"
872         ldb.modify_ldif("""
873 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
874 changetype: modify
875 replace: member
876 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
877 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
878 """)
879
880         ldb.modify_ldif("""
881 dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
882 changetype: modify
883 replace: member
884 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
885 """)
886
887         ldb.modify_ldif("""
888 dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
889 changetype: modify
890 delete: member
891 """)
892
893         ldb.modify_ldif("""
894 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
895 changetype: modify
896 add: member
897 member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
898 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
899 """)
900
901         ldb.modify_ldif("""
902 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
903 changetype: modify
904 replace: member
905 """)
906
907         ldb.modify_ldif("""
908 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
909 changetype: modify
910 add: member
911 member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
912 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
913 """)
914
915         ldb.modify_ldif("""
916 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
917 changetype: modify
918 delete: member
919 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
920 """)
921
922         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
923         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
924
925         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
926         self.assertEquals(res[0]["member"][0], ("CN=ldaptestuser2,CN=Users," + self.base_dn))
927         self.assertEquals(len(res[0]["member"]), 1)
928
929         ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
930
931         time.sleep(4)
932
933         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
934         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
935         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
936         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
937
938         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
939         self.assertTrue("member" not in res[0])
940
941         print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
942         res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
943         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
944
945         self.assertEquals(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
946         self.assertEquals(str(res[0]["cn"]), "ldaptestutf8user èùéìòà")
947         self.assertEquals(str(res[0]["name"]), "ldaptestutf8user èùéìòà")
948         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
949         self.assertTrue("objectGUID" in res[0])
950         self.assertTrue("whenCreated" in res[0])
951
952         ldb.delete(res[0].dn)
953
954         print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
955         res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
956         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
957
958         ldb.delete(res[0].dn)
959
960         ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
961
962         print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
963         res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
964
965         #FIXME: self.assert len(res) == 1, "Could not find (expect space collapse, win2k3 fails) (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
966
967         print "Testing that we can't get at the configuration DN from the main search base"
968         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
969         self.assertEquals(len(res), 0)
970
971         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"
972         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
973         self.assertTrue(len(res) > 0)
974
975         if gc_ldb is not None:
976             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"
977
978             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
979             self.assertTrue(len(res) > 0)
980
981             print "Testing that we do find configuration elements in the global catlog"
982             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
983             self.assertTrue(len(res) > 0)
984
985             print "Testing that we do find configuration elements and user elements at the same time"
986             res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
987             self.assertTrue(len(res) > 0)
988
989             print "Testing that we do find configuration elements in the global catlog, with the configuration basedn"
990             res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
991             self.assertTrue(len(res) > 0)
992
993         print "Testing that we can get at the configuration DN on the main LDAP port"
994         res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
995         self.assertTrue(len(res) > 0)
996
997         print "Testing objectCategory canonacolisation"
998         res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
999         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
1000         self.assertTrue(len(res) != 0)
1001
1002         res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
1003         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
1004         self.assertTrue(len(res) != 0)
1005
1006         print "Testing objectClass attribute order on "+ self.base_dn
1007         res = ldb.search(expression="objectClass=domain", base=self.base_dn,
1008                          scope=SCOPE_BASE, attrs=["objectClass"])
1009         self.assertEquals(len(res), 1)
1010
1011         self.assertEquals(list(res[0]["objectClass"]), ["top", "domain", "domainDNS"])
1012
1013     #  check enumeration
1014
1015         print "Testing ldb.search for objectCategory=person"
1016         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
1017         self.assertTrue(len(res) > 0)
1018
1019         print "Testing ldb.search for objectCategory=person with domain scope control"
1020         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1021         self.assertTrue(len(res) > 0)
1022
1023         print "Testing ldb.search for objectCategory=user"
1024         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
1025         self.assertTrue(len(res) > 0)
1026
1027         print "Testing ldb.search for objectCategory=user with domain scope control"
1028         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1029         self.assertTrue(len(res) > 0)
1030
1031         print "Testing ldb.search for objectCategory=group"
1032         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
1033         self.assertTrue(len(res) > 0)
1034
1035         print "Testing ldb.search for objectCategory=group with domain scope control"
1036         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1037         self.assertTrue(len(res) > 0)
1038
1039
1040 class BaseDnTests(unittest.TestCase):
1041     def setUp(self):
1042         self.ldb = ldb
1043
1044     def test_rootdse_attrs(self):
1045         """Testing for all rootDSE attributes"""
1046         res = self.ldb.search(scope=SCOPE_BASE, attrs=[])
1047         self.assertEquals(len(res), 1)
1048
1049     def test_highestcommittedusn(self):
1050         """Testing for highestCommittedUSN"""
1051         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
1052         self.assertEquals(len(res), 1)
1053         self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
1054
1055     def test_netlogon(self):
1056         """Testing for netlogon via LDAP"""
1057         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
1058         self.assertEquals(len(res), 0)
1059
1060     def test_netlogon_highestcommitted_usn(self):
1061         """Testing for netlogon and highestCommittedUSN via LDAP"""
1062         res = self.ldb.search("", scope=SCOPE_BASE,
1063                 attrs=["netlogon", "highestCommittedUSN"])
1064         self.assertEquals(len(res), 0)
1065
1066 class SchemaTests(unittest.TestCase):
1067     def delete_force(self, ldb, dn):
1068         try:
1069             ldb.delete(dn)
1070         except LdbError, (num, _):
1071             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1072
1073     def find_schemadn(self, ldb):
1074         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
1075         self.assertEquals(len(res), 1)
1076         return res[0]["schemaNamingContext"][0]
1077
1078     def find_basedn(self, ldb):
1079         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
1080                          attrs=["defaultNamingContext"])
1081         self.assertEquals(len(res), 1)
1082         return res[0]["defaultNamingContext"][0]
1083
1084     def setUp(self):
1085         self.ldb = ldb
1086         self.schema_dn = self.find_schemadn(ldb)
1087         self.base_dn = self.find_basedn(ldb)
1088
1089     def test_generated_schema(self):
1090         """Testing we can read the generated schema via LDAP"""
1091         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
1092                 attrs=["objectClasses", "attributeTypes", "dITContentRules"])
1093         self.assertEquals(len(res), 1)
1094         self.assertTrue("dITContentRules" in res[0])
1095         self.assertTrue("objectClasses" in res[0])
1096         self.assertTrue("attributeTypes" in res[0])
1097
1098     def test_generated_schema_is_operational(self):
1099         """Testing we don't get the generated schema via LDAP by default"""
1100         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
1101                 attrs=["*"])
1102         self.assertEquals(len(res), 1)
1103         self.assertFalse("dITContentRules" in res[0])
1104         self.assertFalse("objectClasses" in res[0])
1105         self.assertFalse("attributeTypes" in res[0])
1106
1107     def test_schemaUpdateNow(self):
1108         """Testing schemaUpdateNow"""
1109         class_name = "test-class" + time.strftime("%s", time.gmtime())
1110         class_ldap_display_name = class_name.replace("-", "")
1111         object_name = "obj" + time.strftime("%s", time.gmtime())
1112
1113         ldif = """
1114 dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
1115 lDAPDisplayName: """ + class_ldap_display_name + """
1116 objectClass: top
1117 objectClass: classSchema
1118 adminDescription: """ + class_name + """
1119 adminDisplayName: """ + class_name + """
1120 cn: """ + class_name + """
1121 objectCategory: CN=Class-Schema,""" + self.schema_dn + """
1122 defaultObjectCategory: CN=%s,%s""" % (class_name, self.schema_dn) + """
1123 distinguishedName: CN=%s,%s""" % (class_name, self.schema_dn) + """
1124 governsID: 1.2.840.""" + time.strftime("%s", time.gmtime())[3:] + """.1.5.9939
1125 instanceType: 4
1126 name: """ + class_name + """
1127 objectClassCategory: 1
1128 subClassOf: organizationalPerson
1129 systemFlags: 16
1130 rDNAttID: cn
1131 systemMustContain: cn
1132 systemOnly: FALSE
1133 """
1134         self.ldb.add_ldif(ldif)
1135         ldif = """
1136 dn:
1137 changetype: modify
1138 add: schemaUpdateNow
1139 schemaUpdateNow: 1
1140 """
1141         self.ldb.modify_ldif(ldif)
1142         ldif = """
1143 dn: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1144 objectClass: organizationalPerson
1145 objectClass: person
1146 objectClass: """ + class_ldap_display_name + """
1147 objectClass: top
1148 cn: """ + object_name + """
1149 instanceType: 4
1150 objectCategory: CN=%s,%s"""% (class_name, self.schema_dn) + """
1151 distinguishedName: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1152 name: """ + object_name + """
1153 """
1154         self.ldb.add_ldif(ldif)
1155         # Search for created objectClass
1156         res = []
1157         res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
1158         self.assertNotEqual(res, [])
1159
1160         res = []
1161         res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["*"])
1162         self.assertNotEqual(res, [])
1163         # Delete the object
1164         self.delete_force(self.ldb, "cn=%s,cn=Users,%s" % (object_name, self.base_dn))
1165
1166 if not "://" in host:
1167     host = "ldap://%s" % host
1168
1169 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
1170 gc_ldb = Ldb("%s:3268" % host, credentials=creds,
1171              session_info=system_session(), lp=lp)
1172
1173 runner = SubunitTestRunner()
1174 rc = 0
1175 if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
1176     rc = 1
1177 if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
1178     rc = 1
1179 if not runner.run(unittest.makeSuite(SchemaTests)).wasSuccessful():
1180     rc = 1
1181 sys.exit(rc)