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