f9801e2f5a6f171629cf23bbfa0f59a0287a7dc7
[gd/samba/.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 # TODO Has to wait until we support read-only generated attributes correctly
794 #        m = Message()
795 #        m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
796 #        m["primaryGroupToken"] = "100"
797 #        try:
798 #                ldb.modify(m)
799 #                self.fail()
800 #        except LdbError, (num, msg):
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_all(self):
823         """Basic tests"""
824
825         print "Testing user add"
826
827         ldb.add({
828             "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
829             "objectclass": ["user", "person"],
830             "cN": "LDAPtestUSER",
831             "givenname": "ldap",
832             "sn": "testy"})
833
834         ldb.add({
835             "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
836             "objectclass": "group",
837             "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
838
839         ldb.add({
840             "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
841             "objectclass": "computer",
842             "cN": "LDAPtestCOMPUTER"})
843
844         ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
845             "objectClass": "computer",
846             "cn": "LDAPtest2COMPUTER",
847             "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT),
848             "displayname": "ldap testy"})
849
850         try:
851             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
852                      "objectClass": "computer",
853                      "cn": "LDAPtest2COMPUTER"
854                      })
855             self.fail()
856         except LdbError, (num, _):
857             self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
858
859         try:
860             ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
861                      "objectClass": "computer",
862                      "cn": "ldaptestcomputer3",
863                      "sAMAccountType": str(ATYPE_NORMAL_ACCOUNT)
864                 })
865             self.fail()
866         except LdbError, (num, _):
867             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
868
869         ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
870                  "objectClass": "computer",
871                  "cn": "LDAPtestCOMPUTER3"
872                  })
873
874         print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
875         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
876         self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
877
878         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn));
879         self.assertEquals(res[0]["cn"][0], "ldaptestcomputer3");
880         self.assertEquals(res[0]["name"][0], "ldaptestcomputer3");
881         self.assertEquals(res[0]["objectClass"][0], "top");
882         self.assertEquals(res[0]["objectClass"][1], "person");
883         self.assertEquals(res[0]["objectClass"][2], "organizationalPerson");
884         self.assertEquals(res[0]["objectClass"][3], "user");
885         self.assertEquals(res[0]["objectClass"][4], "computer");
886         self.assertTrue("objectGUID" in res[0])
887         self.assertTrue("whenCreated" in res[0])
888         self.assertEquals(res[0]["objectCategory"][0], ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn));
889         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513);
890         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT);
891         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE);
892
893         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
894
895         print "Testing attribute or value exists behaviour"
896         try:
897             ldb.modify_ldif("""
898 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
899 changetype: modify
900 replace: servicePrincipalName
901 servicePrincipalName: host/ldaptest2computer
902 servicePrincipalName: host/ldaptest2computer
903 servicePrincipalName: cifs/ldaptest2computer
904 """)
905             self.fail()
906         except LdbError, (num, msg):
907             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
908
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: cifs/ldaptest2computer
915 """)
916         try:
917             ldb.modify_ldif("""
918 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
919 changetype: modify
920 add: servicePrincipalName
921 servicePrincipalName: host/ldaptest2computer
922 """)
923             self.fail()
924         except LdbError, (num, msg):
925             self.assertEquals(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
926
927         print "Testing ranged results"
928         ldb.modify_ldif("""
929 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
930 changetype: modify
931 replace: servicePrincipalName
932 """)
933
934         ldb.modify_ldif("""
935 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
936 changetype: modify
937 add: servicePrincipalName
938 servicePrincipalName: host/ldaptest2computer0
939 servicePrincipalName: host/ldaptest2computer1
940 servicePrincipalName: host/ldaptest2computer2
941 servicePrincipalName: host/ldaptest2computer3
942 servicePrincipalName: host/ldaptest2computer4
943 servicePrincipalName: host/ldaptest2computer5
944 servicePrincipalName: host/ldaptest2computer6
945 servicePrincipalName: host/ldaptest2computer7
946 servicePrincipalName: host/ldaptest2computer8
947 servicePrincipalName: host/ldaptest2computer9
948 servicePrincipalName: host/ldaptest2computer10
949 servicePrincipalName: host/ldaptest2computer11
950 servicePrincipalName: host/ldaptest2computer12
951 servicePrincipalName: host/ldaptest2computer13
952 servicePrincipalName: host/ldaptest2computer14
953 servicePrincipalName: host/ldaptest2computer15
954 servicePrincipalName: host/ldaptest2computer16
955 servicePrincipalName: host/ldaptest2computer17
956 servicePrincipalName: host/ldaptest2computer18
957 servicePrincipalName: host/ldaptest2computer19
958 servicePrincipalName: host/ldaptest2computer20
959 servicePrincipalName: host/ldaptest2computer21
960 servicePrincipalName: host/ldaptest2computer22
961 servicePrincipalName: host/ldaptest2computer23
962 servicePrincipalName: host/ldaptest2computer24
963 servicePrincipalName: host/ldaptest2computer25
964 servicePrincipalName: host/ldaptest2computer26
965 servicePrincipalName: host/ldaptest2computer27
966 servicePrincipalName: host/ldaptest2computer28
967 servicePrincipalName: host/ldaptest2computer29
968 """)
969
970         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
971                          attrs=["servicePrincipalName;range=0-*"])
972         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
973         #print len(res[0]["servicePrincipalName;range=0-*"])
974         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
975
976         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
977         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
978             # print res[0]["servicePrincipalName;range=0-19"].length
979         self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
980
981
982         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
983         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
984         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
985
986         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
987         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
988         self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
989
990         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
991         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
992         self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
993
994
995         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
996         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
997         self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
998         # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
999
1000         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
1001         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1002         self.assertEquals(len(res[0]["servicePrincipalName;range=11-*"]), 19)
1003             # print res[0]["servicePrincipalName;range=11-*"][18]
1004             # print pos_11
1005             # self.assertEquals((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
1006
1007         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
1008         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1009         self.assertEquals(len(res[0]["servicePrincipalName;range=11-15"]), 5)
1010             # self.assertEquals(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
1011
1012         res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
1013         self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
1014             # print res[0]["servicePrincipalName"][18]
1015             # print pos_11
1016         self.assertEquals(len(res[0]["servicePrincipalName"]), 30)
1017             # self.assertEquals(res[0]["servicePrincipalName"][18], pos_11)
1018
1019         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1020         ldb.add({
1021             "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
1022             "objectClass": ["person", "user"],
1023             "cn": "LDAPtestUSER2",
1024             "givenname": "testy",
1025             "sn": "ldap user2"})
1026
1027         print "Testing Ambigious Name Resolution"
1028         # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
1029         res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
1030         self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
1031
1032         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1033         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1034         self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
1035
1036         # Testing ldb.search for (&(anr=ldap)(objectClass=user))
1037         res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
1038         self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
1039
1040         # Testing ldb.search for (&(anr==ldap)(objectClass=user))
1041         res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
1042         self.assertEquals(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
1043
1044         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1045         self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1046         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1047
1048         # Testing ldb.search for (&(anr=testy)(objectClass=user))
1049         res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
1050         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
1051
1052         # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
1053         res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
1054         self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
1055
1056         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1057 # this test disabled for the moment, as anr with == tests are not understood
1058 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1059 #        self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
1060
1061 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1062 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1063 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1064
1065         # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
1066 #        res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
1067 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
1068
1069 #        self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1070 #        self.assertEquals(res[0]["cn"][0], "ldaptestuser")
1071 #        self.assertEquals(res[0]["name"][0], "ldaptestuser")
1072
1073         # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
1074         res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
1075         self.assertEquals(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
1076
1077         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1078         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1079         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1080
1081         # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
1082 #        res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
1083 #        self.assertEquals(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
1084
1085         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1086         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1087         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1088
1089         # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
1090 #        res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
1091 #        self.assertEquals(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
1092
1093         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1094         self.assertEquals(str(res[0]["cn"]), "ldaptestuser2")
1095         self.assertEquals(str(res[0]["name"]), "ldaptestuser2")
1096
1097         # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
1098 #        res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
1099 #        self.assertEquals(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
1100
1101         # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
1102         res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
1103         self.assertEquals(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
1104
1105         # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
1106 #        res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
1107 #        self.assertEquals(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
1108
1109         print "Testing Renames"
1110
1111         attrs = ["objectGUID", "objectSid"]
1112         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
1113         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
1114         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
1115
1116         # Check rename works with extended/alternate DN forms
1117         ldb.rename("<SID=" + ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0]) + ">" , "cn=ldaptestUSER3,cn=users," + self.base_dn)
1118
1119         print "Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))"
1120         res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
1121         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
1122
1123         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1124         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1125         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1126
1127         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
1128         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
1129         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
1130
1131         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1132         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1133         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1134
1135         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
1136         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
1137         self.assertEquals(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
1138
1139         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1140         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1141         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1142
1143         #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
1144         res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
1145         self.assertEquals(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
1146
1147         # This is a Samba special, and does not exist in real AD
1148         #    print "Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1149         #    res = ldb.search("(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1150         #    if (res.error != 0 || len(res) != 1) {
1151         #        print "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1152         #        self.assertEquals(len(res), 1)
1153         #    }
1154         #    self.assertEquals(res[0].dn, ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1155         #    self.assertEquals(res[0].cn, "ldaptestUSER3")
1156         #    self.assertEquals(res[0].name, "ldaptestUSER3")
1157
1158         print "Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")"
1159         res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1160         self.assertEquals(len(res), 1, "Could not find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
1161         self.assertEquals(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
1162         self.assertEquals(str(res[0]["cn"]), "ldaptestUSER3")
1163         self.assertEquals(str(res[0]["name"]), "ldaptestUSER3")
1164
1165         # ensure we cannot add it again
1166         try:
1167             ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
1168                       "objectClass": ["person", "user"],
1169                       "cn": "LDAPtestUSER3"})
1170             self.fail()
1171         except LdbError, (num, _):
1172             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1173
1174         # rename back
1175         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
1176
1177         # ensure we cannot rename it twice
1178         try:
1179             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
1180                        "cn=ldaptestuser2,cn=users," + self.base_dn)
1181             self.fail()
1182         except LdbError, (num, _):
1183             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1184
1185         # ensure can now use that name
1186         ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
1187                       "objectClass": ["person", "user"],
1188                       "cn": "LDAPtestUSER3"})
1189
1190         # ensure we now cannot rename
1191         try:
1192             ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
1193             self.fail()
1194         except LdbError, (num, _):
1195             self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
1196         try:
1197             ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=configuration," + self.base_dn)
1198             self.fail()
1199         except LdbError, (num, _):
1200             self.assertTrue(num in (71, 64))
1201
1202         ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
1203
1204         ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
1205
1206         self.delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1207
1208         ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1209
1210         print "Testing subtree renames"
1211
1212         ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
1213                  "objectClass": "container"})
1214
1215         ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
1216                  "objectClass": ["person", "user"],
1217                  "cn": "LDAPtestUSER4"})
1218
1219         ldb.modify_ldif("""
1220 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1221 changetype: modify
1222 add: member
1223 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
1224 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
1225 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
1226 """)
1227
1228         print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
1229         ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
1230
1231         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))"
1232         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
1233         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
1234
1235         print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
1236         try:
1237             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1238                     expression="(&(cn=ldaptestuser4)(objectClass=user))",
1239                     scope=SCOPE_SUBTREE)
1240             self.fail(res)
1241         except LdbError, (num, _):
1242             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1243
1244         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
1245         try:
1246             res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1247                     expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
1248             self.fail()
1249         except LdbError, (num, _):
1250             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1251
1252         print "Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
1253         res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
1254         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
1255
1256         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
1257         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1258
1259         time.sleep(4)
1260
1261         print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
1262         res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
1263         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?")
1264
1265         print "Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
1266         try:
1267             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
1268             self.fail()
1269         except LdbError, (num, _):
1270             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
1271
1272         print "Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
1273         try:
1274             ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
1275             self.fail()
1276         except LdbError, (num, _):
1277             self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER))
1278
1279         print "Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
1280         try:
1281             ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
1282             self.fail()
1283         except LdbError, (num, _):
1284             self.assertEquals(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
1285
1286         print "Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
1287         res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
1288         self.assertEquals(len(res), 1)
1289         res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
1290         self.assertEquals(len(res), 0)
1291
1292         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
1293         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
1294         # FIXME: self.assertEquals(len(res), 0)
1295
1296         print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
1297         res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
1298         # FIXME: self.assertEquals(len(res), 0)
1299
1300         print "Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
1301         ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
1302         print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
1303         ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
1304
1305         ldb.add({"dn": "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
1306
1307         ldb.add({"dn": "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
1308
1309         print "Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
1310         res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
1311         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1312
1313         self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
1314         self.assertEquals(str(res[0]["cn"]), "ldaptestuser")
1315         self.assertEquals(str(res[0]["name"]), "ldaptestuser")
1316         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user"]))
1317         self.assertTrue("objectGUID" in res[0])
1318         self.assertTrue("whenCreated" in res[0])
1319         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Person,CN=Schema,CN=Configuration," + self.base_dn))
1320         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1321         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1322         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1323         self.assertEquals(len(res[0]["memberOf"]), 1)
1324
1325         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
1326         res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1327         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
1328
1329         self.assertEquals(res[0].dn, res2[0].dn)
1330
1331         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
1332         res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1333         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
1334
1335         self.assertEquals(res[0].dn, res3[0].dn)
1336
1337         if gc_ldb is not None:
1338             print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
1339             res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
1340             self.assertEquals(len(res3gc), 1)
1341
1342             self.assertEquals(res[0].dn, res3gc[0].dn)
1343
1344         print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
1345
1346         res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
1347         self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
1348
1349         self.assertEquals(res[0].dn, res3control[0].dn)
1350
1351         ldb.delete(res[0].dn)
1352
1353         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
1354         res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
1355         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
1356
1357         self.assertEquals(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
1358         self.assertEquals(str(res[0]["cn"]), "ldaptestcomputer")
1359         self.assertEquals(str(res[0]["name"]), "ldaptestcomputer")
1360         self.assertEquals(set(res[0]["objectClass"]), set(["top", "person", "organizationalPerson", "user", "computer"]))
1361         self.assertTrue("objectGUID" in res[0])
1362         self.assertTrue("whenCreated" in res[0])
1363         self.assertEquals(str(res[0]["objectCategory"]), ("CN=Computer,CN=Schema,CN=Configuration," + self.base_dn))
1364         self.assertEquals(int(res[0]["primaryGroupID"][0]), 513)
1365         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
1366         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
1367         self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1368         self.assertEquals(len(res[0]["memberOf"]), 1)
1369
1370         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))"
1371         res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1372         self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1373
1374         self.assertEquals(res[0].dn, res2[0].dn)
1375
1376         if gc_ldb is not None:
1377             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog"
1378             res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + "))")
1379             self.assertEquals(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,cn=schema,cn=configuration," + self.base_dn + ")) in Global Catlog")
1380
1381             self.assertEquals(res[0].dn, res2gc[0].dn)
1382
1383         print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
1384         res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1385         self.assertEquals(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1386
1387         self.assertEquals(res[0].dn, res3[0].dn)
1388
1389         if gc_ldb is not None:
1390             print "Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
1391             res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
1392             self.assertEquals(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
1393
1394             self.assertEquals(res[0].dn, res3gc[0].dn)
1395
1396         print "Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
1397         res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1398         self.assertEquals(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
1399
1400         self.assertEquals(res[0].dn, res4[0].dn)
1401
1402         print "Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
1403         res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1404         self.assertEquals(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
1405
1406         self.assertEquals(res[0].dn, res5[0].dn)
1407
1408         print "Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
1409         res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
1410         self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
1411
1412         self.assertEquals(res[0].dn, res6[0].dn)
1413
1414         ldb.delete("<GUID=" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + ">")
1415
1416         print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
1417         res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
1418         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
1419
1420         self.assertEquals(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn)
1421         self.assertEquals(str(res[0]["cn"]), "ldaptest2computer")
1422         self.assertEquals(str(res[0]["name"]), "ldaptest2computer")
1423         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user", "computer"])
1424         self.assertTrue("objectGUID" in res[0])
1425         self.assertTrue("whenCreated" in res[0])
1426         self.assertEquals(res[0]["objectCategory"][0], "CN=Computer,CN=Schema,CN=Configuration," + self.base_dn)
1427         self.assertEquals(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
1428         self.assertEquals(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT)
1429
1430         ldb.delete("<SID=" + ldb.schema_format_value("objectSID", res[0]["objectSID"][0]) + ">")
1431
1432         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"]
1433         print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
1434         res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
1435         self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
1436
1437         self.assertEquals(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1438         self.assertEquals(str(res_user[0]["cn"]), "ldaptestuser2")
1439         self.assertEquals(str(res_user[0]["name"]), "ldaptestuser2")
1440         self.assertEquals(list(res_user[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
1441         self.assertTrue("objectSid" in res_user[0])
1442         self.assertTrue("objectGUID" in res_user[0])
1443         self.assertTrue("whenCreated" in res_user[0])
1444         self.assertTrue("nTSecurityDescriptor" in res_user[0])
1445         self.assertTrue("allowedAttributes" in res_user[0])
1446         self.assertTrue("allowedAttributesEffective" in res_user[0])
1447         self.assertEquals(res_user[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
1448
1449         ldaptestuser2_sid = res_user[0]["objectSid"][0]
1450         ldaptestuser2_guid = res_user[0]["objectGUID"][0]
1451
1452         attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"]
1453         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
1454         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1455         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1456
1457         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1458         self.assertEquals(str(res[0]["cn"]), "ldaptestgroup2")
1459         self.assertEquals(str(res[0]["name"]), "ldaptestgroup2")
1460         self.assertEquals(list(res[0]["objectClass"]), ["top", "group"])
1461         self.assertTrue("objectGUID" in res[0])
1462         self.assertTrue("objectSid" in res[0])
1463         self.assertTrue("whenCreated" in res[0])
1464         self.assertTrue("nTSecurityDescriptor" in res[0])
1465         self.assertTrue("allowedAttributes" in res[0])
1466         self.assertTrue("allowedAttributesEffective" in res[0])
1467         memberUP = []
1468         for m in res[0]["member"]:
1469             memberUP.append(m.upper())
1470         self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
1471
1472         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"])
1473         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1474
1475         print res[0]["member"]
1476         memberUP = []
1477         for m in res[0]["member"]:
1478             memberUP.append(m.upper())
1479         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()
1480
1481         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)
1482
1483         print "Testing Linked attribute behaviours"
1484         ldb.modify_ldif("""
1485 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1486 changetype: modify
1487 replace: member
1488 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
1489 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1490 """)
1491
1492         ldb.modify_ldif("""
1493 dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1494 changetype: modify
1495 replace: member
1496 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1497 """)
1498
1499         ldb.modify_ldif("""
1500 dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
1501 changetype: modify
1502 delete: member
1503 """)
1504
1505         ldb.modify_ldif("""
1506 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1507 changetype: modify
1508 add: member
1509 member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
1510 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1511 """)
1512
1513         ldb.modify_ldif("""
1514 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1515 changetype: modify
1516 replace: member
1517 """)
1518
1519         ldb.modify_ldif("""
1520 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1521 changetype: modify
1522 add: member
1523 member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
1524 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1525 """)
1526
1527         ldb.modify_ldif("""
1528 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
1529 changetype: modify
1530 delete: member
1531 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
1532 """)
1533
1534         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1535         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
1536
1537         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1538         self.assertEquals(res[0]["member"][0], ("CN=ldaptestuser2,CN=Users," + self.base_dn))
1539         self.assertEquals(len(res[0]["member"]), 1)
1540
1541         ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
1542
1543         time.sleep(4)
1544
1545         attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
1546         print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
1547         res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
1548         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
1549
1550         self.assertEquals(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1551         self.assertTrue("member" not in res[0])
1552
1553         print "Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
1554 # TODO UTF8 users don't seem to work fully anymore
1555 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1556         res = ldb.search(expression="(&(cn=ldaptestutf8user èùéìòà)(objectclass=user))")
1557         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1558
1559         self.assertEquals(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
1560         self.assertEquals(str(res[0]["cn"]), "ldaptestutf8user èùéìòà")
1561         self.assertEquals(str(res[0]["name"]), "ldaptestutf8user èùéìòà")
1562         self.assertEquals(list(res[0]["objectClass"]), ["top", "person", "organizationalPerson", "user"])
1563         self.assertTrue("objectGUID" in res[0])
1564         self.assertTrue("whenCreated" in res[0])
1565
1566         ldb.delete(res[0].dn)
1567
1568         print "Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
1569         res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
1570         self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
1571
1572         ldb.delete(res[0].dn)
1573
1574         ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
1575
1576         print "Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
1577 # TODO UTF8 users don't seem to work fully anymore
1578 #        res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1579 #        self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
1580
1581         print "Testing that we can't get at the configuration DN from the main search base"
1582         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1583         self.assertEquals(len(res), 0)
1584
1585         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"
1586         res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
1587         self.assertTrue(len(res) > 0)
1588
1589         if gc_ldb is not None:
1590             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"
1591
1592             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
1593             self.assertTrue(len(res) > 0)
1594
1595             print "Testing that we do find configuration elements in the global catlog"
1596             res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1597             self.assertTrue(len(res) > 0)
1598
1599             print "Testing that we do find configuration elements and user elements at the same time"
1600             res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
1601             self.assertTrue(len(res) > 0)
1602
1603             print "Testing that we do find configuration elements in the global catlog, with the configuration basedn"
1604             res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1605             self.assertTrue(len(res) > 0)
1606
1607         print "Testing that we can get at the configuration DN on the main LDAP port"
1608         res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
1609         self.assertTrue(len(res) > 0)
1610
1611         print "Testing objectCategory canonacolisation"
1612         res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
1613         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
1614         self.assertTrue(len(res) != 0)
1615
1616         res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
1617         self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
1618         self.assertTrue(len(res) != 0)
1619
1620         print "Testing objectClass attribute order on "+ self.base_dn
1621         res = ldb.search(expression="objectClass=domain", base=self.base_dn,
1622                          scope=SCOPE_BASE, attrs=["objectClass"])
1623         self.assertEquals(len(res), 1)
1624
1625         self.assertEquals(list(res[0]["objectClass"]), ["top", "domain", "domainDNS"])
1626
1627     #  check enumeration
1628
1629         print "Testing ldb.search for objectCategory=person"
1630         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
1631         self.assertTrue(len(res) > 0)
1632
1633         print "Testing ldb.search for objectCategory=person with domain scope control"
1634         res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1635         self.assertTrue(len(res) > 0)
1636
1637         print "Testing ldb.search for objectCategory=user"
1638         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
1639         self.assertTrue(len(res) > 0)
1640
1641         print "Testing ldb.search for objectCategory=user with domain scope control"
1642         res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1643         self.assertTrue(len(res) > 0)
1644
1645         print "Testing ldb.search for objectCategory=group"
1646         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
1647         self.assertTrue(len(res) > 0)
1648
1649         print "Testing ldb.search for objectCategory=group with domain scope control"
1650         res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
1651         self.assertTrue(len(res) > 0)
1652
1653         self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1654         self.delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1655         self.delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
1656         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
1657         self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
1658         self.delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
1659         self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1660         self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
1661         self.delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
1662         self.delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
1663         self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
1664         self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
1665         self.delete_force(self.ldb, "cn=ldaptestutf8user2  èùéìòà,cn=users," + self.base_dn)
1666         self.delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
1667         self.delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
1668
1669     def test_security_descriptor_add(self):
1670         """ Testing ldb.add_ldif() for nTSecurityDescriptor """
1671         user_name = "testdescriptoruser1"
1672         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1673         #
1674         # Test add_ldif() with SDDL security descriptor input
1675         #
1676         self.delete_force(self.ldb, user_dn)
1677         try:
1678             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1679             self.ldb.add_ldif("""
1680 dn: """ + user_dn + """
1681 objectclass: user
1682 sAMAccountName: """ + user_name + """
1683 nTSecurityDescriptor: """ + sddl)
1684             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1685             desc = res[0]["nTSecurityDescriptor"][0]
1686             desc = ndr_unpack( security.descriptor, desc )
1687             desc_sddl = desc.as_sddl( self.domain_sid )
1688             self.assertEqual(desc_sddl, sddl)
1689         finally:
1690             self.delete_force(self.ldb, user_dn)
1691         #
1692         # Test add_ldif() with BASE64 security descriptor
1693         #
1694         try:
1695             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1696             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1697             desc_binary = ndr_pack(desc)
1698             desc_base64 = base64.b64encode(desc_binary)
1699             self.ldb.add_ldif("""
1700 dn: """ + user_dn + """
1701 objectclass: user
1702 sAMAccountName: """ + user_name + """
1703 nTSecurityDescriptor:: """ + desc_base64)
1704             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1705             desc = res[0]["nTSecurityDescriptor"][0]
1706             desc = ndr_unpack(security.descriptor, desc)
1707             desc_sddl = desc.as_sddl(self.domain_sid)
1708             self.assertEqual(desc_sddl, sddl)
1709         finally:
1710             self.delete_force(self.ldb, user_dn)
1711
1712     def test_security_descriptor_add_neg(self):
1713         """Test add_ldif() with BASE64 security descriptor input using WRONG domain SID
1714             Negative test
1715         """
1716         user_name = "testdescriptoruser1"
1717         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1718         self.delete_force(self.ldb, user_dn)
1719         try:
1720             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1721             desc = security.descriptor.from_sddl(sddl, security.dom_sid('S-1-5-21'))
1722             desc_base64 = base64.b64encode( ndr_pack(desc) )
1723             self.ldb.add_ldif("""
1724 dn: """ + user_dn + """
1725 objectclass: user
1726 sAMAccountName: """ + user_name + """
1727 nTSecurityDescriptor:: """ + desc_base64)
1728             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1729             print res
1730             self.assertRaises(KeyError, lambda: res[0]["nTSecurityDescriptor"])
1731         finally:
1732             self.delete_force(self.ldb, user_dn)
1733
1734     def test_security_descriptor_modify(self):
1735         """ Testing ldb.modify_ldif() for nTSecurityDescriptor """
1736         user_name = "testdescriptoruser2"
1737         user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
1738         #
1739         # Delete user object and test modify_ldif() with SDDL security descriptor input
1740         # Add ACE to the original descriptor test
1741         #
1742         try:
1743             self.delete_force(self.ldb, user_dn)
1744             self.ldb.add_ldif("""
1745 dn: """ + user_dn + """
1746 objectclass: user
1747 sAMAccountName: """ + user_name)
1748             # Modify descriptor
1749             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1750             desc = res[0]["nTSecurityDescriptor"][0]
1751             desc = ndr_unpack(security.descriptor, desc)
1752             desc_sddl = desc.as_sddl(self.domain_sid)
1753             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
1754             mod = """
1755 dn: """ + user_dn + """
1756 changetype: modify
1757 replace: nTSecurityDescriptor
1758 nTSecurityDescriptor: """ + sddl
1759             self.ldb.modify_ldif(mod)
1760             # Read modified 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             self.assertEqual(desc_sddl, sddl)
1766         finally:
1767             self.delete_force(self.ldb, user_dn)
1768         #
1769         # Test modify_ldif() with SDDL security descriptor input
1770         # New desctiptor test
1771         #
1772         try:
1773             self.ldb.add_ldif("""
1774 dn: """ + user_dn + """
1775 objectclass: user
1776 sAMAccountName: """ + user_name)
1777             # Modify descriptor
1778             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1779             mod = """
1780 dn: """ + user_dn + """
1781 changetype: modify
1782 replace: nTSecurityDescriptor
1783 nTSecurityDescriptor: """ + sddl
1784             self.ldb.modify_ldif(mod)
1785             # Read modified descriptor
1786             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1787             desc = res[0]["nTSecurityDescriptor"][0]
1788             desc = ndr_unpack(security.descriptor, desc)
1789             desc_sddl = desc.as_sddl(self.domain_sid)
1790             self.assertEqual(desc_sddl, sddl)
1791         finally:
1792             self.delete_force(self.ldb, user_dn)
1793         #
1794         # Test modify_ldif() with BASE64 security descriptor input
1795         # Add ACE to the original descriptor test
1796         #
1797         try:
1798             self.ldb.add_ldif("""
1799 dn: """ + user_dn + """
1800 objectclass: user
1801 sAMAccountName: """ + user_name)
1802             # Modify descriptor
1803             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1804             desc = res[0]["nTSecurityDescriptor"][0]
1805             desc = ndr_unpack(security.descriptor, desc)
1806             desc_sddl = desc.as_sddl(self.domain_sid)
1807             sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
1808             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1809             desc_base64 = base64.b64encode(ndr_pack(desc))
1810             mod = """
1811 dn: """ + user_dn + """
1812 changetype: modify
1813 replace: nTSecurityDescriptor
1814 nTSecurityDescriptor:: """ + desc_base64
1815             self.ldb.modify_ldif(mod)
1816             # Read modified descriptor
1817             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1818             desc = res[0]["nTSecurityDescriptor"][0]
1819             desc = ndr_unpack(security.descriptor, desc)
1820             desc_sddl = desc.as_sddl(self.domain_sid)
1821             self.assertEqual(desc_sddl, sddl)
1822         finally:
1823             self.delete_force(self.ldb, user_dn)
1824         #
1825         # Test modify_ldif() with BASE64 security descriptor input
1826         # New descriptor test
1827         #
1828         try:
1829             self.delete_force(self.ldb, user_dn)
1830             self.ldb.add_ldif("""
1831 dn: """ + user_dn + """
1832 objectclass: user
1833 sAMAccountName: """ + user_name)
1834             # Modify descriptor
1835             sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
1836             desc = security.descriptor.from_sddl(sddl, self.domain_sid)
1837             desc_base64 = base64.b64encode(ndr_pack(desc))
1838             mod = """
1839 dn: """ + user_dn + """
1840 changetype: modify
1841 replace: nTSecurityDescriptor
1842 nTSecurityDescriptor:: """ + desc_base64
1843             self.ldb.modify_ldif(mod)
1844             # Read modified descriptor
1845             res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
1846             desc = res[0]["nTSecurityDescriptor"][0]
1847             desc = ndr_unpack(security.descriptor, desc)
1848             desc_sddl = desc.as_sddl(self.domain_sid)
1849             self.assertEqual(desc_sddl, sddl)
1850         finally:
1851             self.delete_force(self.ldb, user_dn)
1852
1853 class BaseDnTests(unittest.TestCase):
1854     def setUp(self):
1855         self.ldb = ldb
1856
1857     def test_rootdse_attrs(self):
1858         """Testing for all rootDSE attributes"""
1859         res = self.ldb.search(scope=SCOPE_BASE, attrs=[])
1860         self.assertEquals(len(res), 1)
1861
1862     def test_highestcommittedusn(self):
1863         """Testing for highestCommittedUSN"""
1864         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
1865         self.assertEquals(len(res), 1)
1866         self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
1867
1868     def test_netlogon(self):
1869         """Testing for netlogon via LDAP"""
1870         res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
1871         self.assertEquals(len(res), 0)
1872
1873     def test_netlogon_highestcommitted_usn(self):
1874         """Testing for netlogon and highestCommittedUSN via LDAP"""
1875         res = self.ldb.search("", scope=SCOPE_BASE,
1876                 attrs=["netlogon", "highestCommittedUSN"])
1877         self.assertEquals(len(res), 0)
1878
1879 class SchemaTests(unittest.TestCase):
1880     def delete_force(self, ldb, dn):
1881         try:
1882             ldb.delete(dn)
1883         except LdbError, (num, _):
1884             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
1885
1886     def find_schemadn(self, ldb):
1887         res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
1888         self.assertEquals(len(res), 1)
1889         return res[0]["schemaNamingContext"][0]
1890
1891     def find_basedn(self, ldb):
1892         res = ldb.search(base="", expression="", scope=SCOPE_BASE,
1893                          attrs=["defaultNamingContext"])
1894         self.assertEquals(len(res), 1)
1895         return res[0]["defaultNamingContext"][0]
1896
1897     def setUp(self):
1898         self.ldb = ldb
1899         self.schema_dn = self.find_schemadn(ldb)
1900         self.base_dn = self.find_basedn(ldb)
1901
1902     def test_generated_schema(self):
1903         """Testing we can read the generated schema via LDAP"""
1904         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
1905                 attrs=["objectClasses", "attributeTypes", "dITContentRules"])
1906         self.assertEquals(len(res), 1)
1907         self.assertTrue("dITContentRules" in res[0])
1908         self.assertTrue("objectClasses" in res[0])
1909         self.assertTrue("attributeTypes" in res[0])
1910
1911     def test_generated_schema_is_operational(self):
1912         """Testing we don't get the generated schema via LDAP by default"""
1913         res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
1914                 attrs=["*"])
1915         self.assertEquals(len(res), 1)
1916         self.assertFalse("dITContentRules" in res[0])
1917         self.assertFalse("objectClasses" in res[0])
1918         self.assertFalse("attributeTypes" in res[0])
1919
1920
1921     def test_schemaUpdateNow(self):
1922         """Testing schemaUpdateNow"""
1923         attr_name = "test-Attr" + time.strftime("%s", time.gmtime())
1924         attr_ldap_display_name = attr_name.replace("-", "")
1925
1926         ldif = """
1927 dn: CN=%s,%s""" % (attr_name, self.schema_dn) + """
1928 objectClass: top
1929 objectClass: attributeSchema
1930 adminDescription: """ + attr_name + """
1931 adminDisplayName: """ + attr_name + """
1932 cn: """ + attr_name + """
1933 attributeId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9940
1934 attributeSyntax: 2.5.5.12
1935 omSyntax: 64
1936 instanceType: 4
1937 isSingleValued: TRUE
1938 systemOnly: FALSE
1939 """
1940         self.ldb.add_ldif(ldif)
1941
1942         class_name = "test-Class" + time.strftime("%s", time.gmtime())
1943         class_ldap_display_name = class_name.replace("-", "")
1944
1945         ldif = """
1946 dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
1947 objectClass: top
1948 objectClass: classSchema
1949 adminDescription: """ + class_name + """
1950 adminDisplayName: """ + class_name + """
1951 cn: """ + class_name + """
1952 governsId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
1953 instanceType: 4
1954 objectClassCategory: 1
1955 subClassOf: organizationalPerson
1956 systemFlags: 16
1957 rDNAttID: cn
1958 systemMustContain: cn, """ + attr_ldap_display_name + """
1959 systemOnly: FALSE
1960 """
1961         self.ldb.add_ldif(ldif)
1962
1963         ldif = """
1964 dn:
1965 changetype: modify
1966 add: schemaUpdateNow
1967 schemaUpdateNow: 1
1968 """
1969         self.ldb.modify_ldif(ldif)
1970
1971         object_name = "obj" + time.strftime("%s", time.gmtime())
1972
1973         ldif = """
1974 dn: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1975 objectClass: organizationalPerson
1976 objectClass: person
1977 objectClass: """ + class_ldap_display_name + """
1978 objectClass: top
1979 cn: """ + object_name + """
1980 instanceType: 4
1981 objectCategory: CN=%s,%s"""% (class_name, self.schema_dn) + """
1982 distinguishedName: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
1983 name: """ + object_name + """
1984 """ + attr_ldap_display_name + """: test
1985 """
1986         self.ldb.add_ldif(ldif)
1987
1988         # Search for created attribute
1989         res = []
1990         res = self.ldb.search("cn=%s,%s" % (attr_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
1991         self.assertEquals(len(res), 1)
1992         self.assertEquals(res[0]["lDAPDisplayName"][0], attr_ldap_display_name)
1993
1994         # Search for created objectclass
1995         res = []
1996         res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
1997         self.assertEquals(len(res), 1)
1998         self.assertEquals(res[0]["lDAPDisplayName"][0], class_ldap_display_name)
1999         self.assertEquals(res[0]["defaultObjectCategory"][0], res[0]["distinguishedName"][0])
2000
2001         # Search for created object
2002         res = []
2003         res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["*"])
2004         self.assertEquals(len(res), 1)
2005         # Delete the object
2006         self.delete_force(self.ldb, "cn=%s,cn=Users,%s" % (object_name, self.base_dn))
2007
2008 if not "://" in host:
2009     if os.path.isfile(host):
2010         host = "tdb://%s" % host
2011     else:
2012         host = "ldap://%s" % host
2013
2014 ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
2015 gc_ldb = Ldb("%s:3268" % host, credentials=creds,
2016              session_info=system_session(), lp=lp)
2017
2018 runner = SubunitTestRunner()
2019 rc = 0
2020 if not runner.run(unittest.makeSuite(BaseDnTests)).wasSuccessful():
2021     rc = 1
2022 if not runner.run(unittest.makeSuite(BasicTests)).wasSuccessful():
2023     rc = 1
2024 if not runner.run(unittest.makeSuite(SchemaTests)).wasSuccessful():
2025     rc = 1
2026 sys.exit(rc)