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