• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/lib/ldb/tests/python/
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3# This is a port of the original in testprogs/ejs/ldap.js
4
5import getopt
6import optparse
7import sys
8import time
9import random
10import base64
11
12sys.path.append("bin/python")
13sys.path.append("../lib/subunit/python")
14
15import samba.getopt as options
16
17from samba.auth import system_session
18from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
19from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
20from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
21from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
22from ldb import Message, MessageElement, Dn, FLAG_MOD_REPLACE
23from samba import Ldb, param, dom_sid_to_rid
24from subunit import SubunitTestRunner
25import unittest
26
27from samba.ndr import ndr_pack, ndr_unpack
28from samba.dcerpc import security
29
30parser = optparse.OptionParser("ldap [options] <host>")
31sambaopts = options.SambaOptions(parser)
32parser.add_option_group(sambaopts)
33parser.add_option_group(options.VersionOptions(parser))
34# use command line creds if available
35credopts = options.CredentialsOptions(parser)
36parser.add_option_group(credopts)
37opts, args = parser.parse_args()
38
39if len(args) < 1:
40    parser.print_usage()
41    sys.exit(1)
42
43host = args[0]
44
45lp = sambaopts.get_loadparm()
46creds = credopts.get_credentials(lp)
47
48class 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("""
434dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
435changetype: modify
436replace: servicePrincipalName
437servicePrincipalName: host/ldaptest2computer
438servicePrincipalName: host/ldaptest2computer
439servicePrincipalName: 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("""
446dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
447changetype: modify
448replace: servicePrincipalName
449servicePrincipalName: host/ldaptest2computer
450servicePrincipalName: cifs/ldaptest2computer
451""")
452        try:
453            ldb.modify_ldif("""
454dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
455changetype: modify
456add: servicePrincipalName
457servicePrincipalName: 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("""
465dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
466changetype: modify
467replace: servicePrincipalName
468""")
469
470        ldb.modify_ldif("""
471dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
472changetype: modify
473add: servicePrincipalName
474servicePrincipalName: host/ldaptest2computer0
475servicePrincipalName: host/ldaptest2computer1
476servicePrincipalName: host/ldaptest2computer2
477servicePrincipalName: host/ldaptest2computer3
478servicePrincipalName: host/ldaptest2computer4
479servicePrincipalName: host/ldaptest2computer5
480servicePrincipalName: host/ldaptest2computer6
481servicePrincipalName: host/ldaptest2computer7
482servicePrincipalName: host/ldaptest2computer8
483servicePrincipalName: host/ldaptest2computer9
484servicePrincipalName: host/ldaptest2computer10
485servicePrincipalName: host/ldaptest2computer11
486servicePrincipalName: host/ldaptest2computer12
487servicePrincipalName: host/ldaptest2computer13
488servicePrincipalName: host/ldaptest2computer14
489servicePrincipalName: host/ldaptest2computer15
490servicePrincipalName: host/ldaptest2computer16
491servicePrincipalName: host/ldaptest2computer17
492servicePrincipalName: host/ldaptest2computer18
493servicePrincipalName: host/ldaptest2computer19
494servicePrincipalName: host/ldaptest2computer20
495servicePrincipalName: host/ldaptest2computer21
496servicePrincipalName: host/ldaptest2computer22
497servicePrincipalName: host/ldaptest2computer23
498servicePrincipalName: host/ldaptest2computer24
499servicePrincipalName: host/ldaptest2computer25
500servicePrincipalName: host/ldaptest2computer26
501servicePrincipalName: host/ldaptest2computer27
502servicePrincipalName: host/ldaptest2computer28
503servicePrincipalName: 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("""
647dn: cn=ldaptestgroup,cn=users,""" + self.base_dn + """
648changetype: modify
649add: member
650member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
651member: 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("""
659dn: cn=ldaptestgroup,cn=users,""" + self.base_dn + """
660changetype: modify
661add: member
662member: 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("""
784dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
785changetype: modify
786add: member
787member: 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("""
1049dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1050changetype: modify
1051replace: member
1052member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
1053member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1054""")
1055
1056        ldb.modify_ldif("""
1057dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1058changetype: modify
1059replace: member
1060member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1061""")
1062
1063        ldb.modify_ldif("""
1064dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
1065changetype: modify
1066delete: member
1067""")
1068
1069        ldb.modify_ldif("""
1070dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1071changetype: modify
1072add: member
1073member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1074member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1075""")
1076
1077        ldb.modify_ldif("""
1078dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1079changetype: modify
1080replace: member
1081""")
1082
1083        ldb.modify_ldif("""
1084dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1085changetype: modify
1086add: member
1087member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
1088member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1089""")
1090
1091        ldb.modify_ldif("""
1092dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1093changetype: modify
1094delete: member
1095member: 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("""
1226dn: """ + user_dn + """
1227objectclass: user
1228sAMAccountName: """ + user_name + """
1229nTSecurityDescriptor: """ + 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("""
1246dn: """ + user_dn + """
1247objectclass: user
1248sAMAccountName: """ + user_name + """
1249nTSecurityDescriptor:: """ + 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("""
1270dn: """ + user_dn + """
1271objectclass: user
1272sAMAccountName: """ + user_name + """
1273nTSecurityDescriptor:: """ + 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("""
1291dn: """ + user_dn + """
1292objectclass: user
1293sAMAccountName: """ + 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 = """
1301dn: """ + user_dn + """
1302changetype: modify
1303replace: nTSecurityDescriptor
1304nTSecurityDescriptor: """ + 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("""
1320dn: """ + user_dn + """
1321objectclass: user
1322sAMAccountName: """ + user_name)
1323            # Modify descriptor
1324            sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1325            mod = """
1326dn: """ + user_dn + """
1327changetype: modify
1328replace: nTSecurityDescriptor
1329nTSecurityDescriptor: """ + 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("""
1345dn: """ + user_dn + """
1346objectclass: user
1347sAMAccountName: """ + 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 = """
1357dn: """ + user_dn + """
1358changetype: modify
1359replace: nTSecurityDescriptor
1360nTSecurityDescriptor:: """ + 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("""
1377dn: """ + user_dn + """
1378objectclass: user
1379sAMAccountName: """ + 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 = """
1385dn: """ + user_dn + """
1386changetype: modify
1387replace: nTSecurityDescriptor
1388nTSecurityDescriptor:: """ + 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
1399class 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
1425class 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 = """
1473dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
1474lDAPDisplayName: """ + class_ldap_display_name + """
1475objectClass: top
1476objectClass: classSchema
1477adminDescription: """ + class_name + """
1478adminDisplayName: """ + class_name + """
1479cn: """ + class_name + """
1480objectCategory: CN=Class-Schema,""" + self.schema_dn + """
1481defaultObjectCategory: CN=%s,%s""" % (class_name, self.schema_dn) + """
1482distinguishedName: CN=%s,%s""" % (class_name, self.schema_dn) + """
1483governsID: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
1484instanceType: 4
1485name: """ + class_name + """
1486objectClassCategory: 1
1487subClassOf: organizationalPerson
1488systemFlags: 16
1489rDNAttID: cn
1490systemMustContain: cn
1491systemOnly: FALSE
1492"""
1493        self.ldb.add_ldif(ldif)
1494        ldif = """
1495dn:
1496changetype: modify
1497add: schemaUpdateNow
1498schemaUpdateNow: 1
1499"""
1500        self.ldb.modify_ldif(ldif)
1501        ldif = """
1502dn: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1503objectClass: organizationalPerson
1504objectClass: person
1505objectClass: """ + class_ldap_display_name + """
1506objectClass: top
1507cn: """ + object_name + """
1508instanceType: 4
1509objectCategory: CN=%s,%s"""% (class_name, self.schema_dn) + """
1510distinguishedName: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1511name: """ + 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
1525if not "://" in host:
1526    host = "ldap://%s" % host
1527
1528ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
1529gc_ldb = Ldb("%s:3268" % host, credentials=creds,
1530             session_info=system_session(), lp=lp)
1531
1532runner = SubunitTestRunner()
1533rc = 0
1534if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
1535    rc = 1
1536if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
1537    rc = 1
1538if not runner.run(unittest.makeSuite(SchemaTests)).wasSuccessful():
1539    rc = 1
1540sys.exit(rc)
1541