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