script/autobuild.py: do some basic testing using --without-winbind
[Samba.git] / source4 / dsdb / tests / python / ldap.py
blob54219ee50033a71633c9c30f3d2fd2c0b75c8bd8
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 # This is a port of the original in testprogs/ejs/ldap.js
5 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008-2011
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 import optparse
21 import sys
22 import time
23 import base64
24 import os
26 sys.path.insert(0, "bin/python")
27 import samba
28 from samba.tests.subunitrun import SubunitOptions, TestProgram
29 import samba.getopt as options
31 from samba.auth import system_session
32 from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
33 from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
34 from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
35 from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
36 from ldb import ERR_NO_SUCH_ATTRIBUTE, ERR_INVALID_ATTRIBUTE_SYNTAX
37 from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
38 from ldb import ERR_NAMING_VIOLATION, ERR_CONSTRAINT_VIOLATION
39 from ldb import Message, MessageElement, Dn
40 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
41 from ldb import timestring
42 from samba import Ldb
43 from samba.samdb import SamDB
44 from samba.dsdb import (UF_NORMAL_ACCOUNT,
45 UF_WORKSTATION_TRUST_ACCOUNT,
46 UF_PASSWD_NOTREQD, UF_ACCOUNTDISABLE, ATYPE_NORMAL_ACCOUNT,
47 ATYPE_WORKSTATION_TRUST, SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE,
48 SYSTEM_FLAG_CONFIG_ALLOW_RENAME, SYSTEM_FLAG_CONFIG_ALLOW_MOVE,
49 SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE)
50 from samba.dcerpc.security import DOMAIN_RID_DOMAIN_MEMBERS
52 from samba.ndr import ndr_pack, ndr_unpack
53 from samba.dcerpc import security, lsa
54 from samba.tests import delete_force
55 from samba.common import get_string
57 parser = optparse.OptionParser("ldap.py [options] <host>")
58 sambaopts = options.SambaOptions(parser)
59 parser.add_option_group(sambaopts)
60 parser.add_option_group(options.VersionOptions(parser))
61 # use command line creds if available
62 credopts = options.CredentialsOptions(parser)
63 parser.add_option_group(credopts)
64 subunitopts = SubunitOptions(parser)
65 parser.add_option_group(subunitopts)
66 opts, args = parser.parse_args()
68 if len(args) < 1:
69 parser.print_usage()
70 sys.exit(1)
72 host = args[0]
74 lp = sambaopts.get_loadparm()
75 creds = credopts.get_credentials(lp)
78 class BasicTests(samba.tests.TestCase):
80 def setUp(self):
81 super(BasicTests, self).setUp()
82 self.ldb = ldb
83 self.gc_ldb = gc_ldb
84 self.base_dn = ldb.domain_dn()
85 self.configuration_dn = ldb.get_config_basedn().get_linearized()
86 self.schema_dn = ldb.get_schema_basedn().get_linearized()
87 self.domain_sid = security.dom_sid(ldb.get_domain_sid())
89 delete_force(self.ldb, "cn=posixuser,cn=users," + self.base_dn)
90 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
91 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
92 delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
93 delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
94 delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
95 delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
96 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
97 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
98 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
99 delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
100 delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
101 delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
102 delete_force(self.ldb, "cn=ldaptestutf8user2 èùéìòà,cn=users," + self.base_dn)
103 delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
104 delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
105 delete_force(self.ldb, "cn=parentguidtest,cn=users," + self.base_dn)
106 delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
107 delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
108 delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
109 delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
110 delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
111 delete_force(self.ldb, "cn=Test Secret,cn=system," + self.base_dn)
112 delete_force(self.ldb, "cn=testtimevaluesuser1,cn=users," + self.base_dn)
114 def test_objectclasses(self):
115 """Test objectClass behaviour"""
116 # Invalid objectclass specified
117 try:
118 self.ldb.add({
119 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
120 "objectClass": []})
121 self.fail()
122 except LdbError as e:
123 (num, _) = e.args
124 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
126 # Invalid objectclass specified
127 try:
128 self.ldb.add({
129 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
130 "objectClass": "X"})
131 self.fail()
132 except LdbError as e:
133 (num, _) = e.args
134 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
136 # Invalid objectCategory specified
137 try:
138 self.ldb.add({
139 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
140 "objectClass": "person",
141 "objectCategory": self.base_dn})
142 self.fail()
143 except LdbError as e:
144 (num, _) = e.args
145 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
147 # Multi-valued "systemFlags"
148 try:
149 self.ldb.add({
150 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
151 "objectClass": "person",
152 "systemFlags": ["0", str(SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE)]})
153 self.fail()
154 except LdbError as e:
155 (num, _) = e.args
156 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
158 # We cannot instantiate from an abstract object class ("connectionPoint"
159 # or "leaf"). In the first case we use "connectionPoint" (subclass of
160 # "leaf") to prevent a naming violation - this returns us a
161 # "ERR_UNWILLING_TO_PERFORM" since it is not structural. In the second
162 # case however we get "ERR_OBJECT_CLASS_VIOLATION" since an abstract
163 # class is also not allowed to be auxiliary.
164 try:
165 self.ldb.add({
166 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
167 "objectClass": "connectionPoint"})
168 self.fail()
169 except LdbError as e:
170 (num, _) = e.args
171 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
172 try:
173 self.ldb.add({
174 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
175 "objectClass": ["person", "leaf"]})
176 self.fail()
177 except LdbError as e:
178 (num, _) = e.args
179 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
181 # Objects instantiated using "satisfied" abstract classes (concrete
182 # subclasses) are allowed
183 self.ldb.add({
184 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
185 "objectClass": ["top", "leaf", "connectionPoint", "serviceConnectionPoint"]})
187 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
189 # Two disjoint top-most structural object classes aren't allowed
190 try:
191 self.ldb.add({
192 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
193 "objectClass": ["person", "container"]})
194 self.fail()
195 except LdbError as e:
196 (num, _) = e.args
197 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
199 # Test allowed system flags
200 self.ldb.add({
201 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
202 "objectClass": "person",
203 "systemFlags": str(~(SYSTEM_FLAG_CONFIG_ALLOW_RENAME | SYSTEM_FLAG_CONFIG_ALLOW_MOVE | SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE))})
205 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
206 scope=SCOPE_BASE, attrs=["systemFlags"])
207 self.assertTrue(len(res) == 1)
208 self.assertEqual(str(res[0]["systemFlags"][0]), "0")
210 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
212 self.ldb.add({
213 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
214 "objectClass": "person"})
216 # We can remove derivation classes of the structural objectclass
217 # but they're going to be re-added afterwards
218 m = Message()
219 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
220 m["objectClass"] = MessageElement("top", FLAG_MOD_DELETE,
221 "objectClass")
222 ldb.modify(m)
224 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
225 scope=SCOPE_BASE, attrs=["objectClass"])
226 self.assertTrue(len(res) == 1)
227 self.assertTrue(b"top" in res[0]["objectClass"])
229 # The top-most structural class cannot be deleted since there are
230 # attributes of it in use
231 m = Message()
232 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
233 m["objectClass"] = MessageElement("person", FLAG_MOD_DELETE,
234 "objectClass")
235 try:
236 ldb.modify(m)
237 self.fail()
238 except LdbError as e:
239 (num, _) = e.args
240 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
242 # We cannot delete classes which weren't specified
243 m = Message()
244 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
245 m["objectClass"] = MessageElement("computer", FLAG_MOD_DELETE,
246 "objectClass")
247 try:
248 ldb.modify(m)
249 self.fail()
250 except LdbError as e:
251 (num, _) = e.args
252 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
254 # An invalid class cannot be added
255 m = Message()
256 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
257 m["objectClass"] = MessageElement("X", FLAG_MOD_ADD,
258 "objectClass")
259 try:
260 ldb.modify(m)
261 self.fail()
262 except LdbError as e:
263 (num, _) = e.args
264 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
266 # We cannot add a new top-most structural class "user" here since
267 # we are missing at least one new mandatory attribute (in this case
268 # "sAMAccountName")
269 m = Message()
270 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
271 m["objectClass"] = MessageElement("user", FLAG_MOD_ADD,
272 "objectClass")
273 try:
274 ldb.modify(m)
275 self.fail()
276 except LdbError as e:
277 (num, _) = e.args
278 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
280 # An already specified objectclass cannot be added another time
281 m = Message()
282 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
283 m["objectClass"] = MessageElement("person", FLAG_MOD_ADD,
284 "objectClass")
285 try:
286 ldb.modify(m)
287 self.fail()
288 except LdbError as e:
289 (num, _) = e.args
290 self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
292 # Auxiliary classes can always be added
293 m = Message()
294 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
295 m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_ADD,
296 "objectClass")
297 ldb.modify(m)
299 # This does not work since object class "leaf" is not auxiliary nor it
300 # stands in direct relation to "person" (and it is abstract too!)
301 m = Message()
302 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
303 m["objectClass"] = MessageElement("leaf", FLAG_MOD_ADD,
304 "objectClass")
305 try:
306 ldb.modify(m)
307 self.fail()
308 except LdbError as e:
309 (num, _) = e.args
310 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
312 # Objectclass replace operations can be performed as well
313 m = Message()
314 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
315 m["objectClass"] = MessageElement(["top", "person", "bootableDevice"],
316 FLAG_MOD_REPLACE, "objectClass")
317 ldb.modify(m)
319 m = Message()
320 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
321 m["objectClass"] = MessageElement(["person", "bootableDevice"],
322 FLAG_MOD_REPLACE, "objectClass")
323 ldb.modify(m)
325 # This does not work since object class "leaf" is not auxiliary nor it
326 # stands in direct relation to "person" (and it is abstract too!)
327 m = Message()
328 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
329 m["objectClass"] = MessageElement(["top", "person", "bootableDevice",
330 "leaf"], FLAG_MOD_REPLACE, "objectClass")
331 try:
332 ldb.modify(m)
333 self.fail()
334 except LdbError as e:
335 (num, _) = e.args
336 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
338 # More than one change operation is allowed
339 m = Message()
340 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
341 m.add(MessageElement("bootableDevice", FLAG_MOD_DELETE, "objectClass"))
342 m.add(MessageElement("bootableDevice", FLAG_MOD_ADD, "objectClass"))
343 ldb.modify(m)
345 # We cannot remove all object classes by an empty replace
346 m = Message()
347 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
348 m["objectClass"] = MessageElement([], FLAG_MOD_REPLACE, "objectClass")
349 try:
350 ldb.modify(m)
351 self.fail()
352 except LdbError as e:
353 (num, _) = e.args
354 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
356 m = Message()
357 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
358 m["objectClass"] = MessageElement(["top", "computer"], FLAG_MOD_REPLACE,
359 "objectClass")
360 try:
361 ldb.modify(m)
362 self.fail()
363 except LdbError as e:
364 (num, _) = e.args
365 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
367 # Classes can be removed unless attributes of them are used.
368 m = Message()
369 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
370 m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
371 "objectClass")
372 ldb.modify(m)
374 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
375 scope=SCOPE_BASE, attrs=["objectClass"])
376 self.assertTrue(len(res) == 1)
377 self.assertFalse("bootableDevice" in res[0]["objectClass"])
379 m = Message()
380 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
381 m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_ADD,
382 "objectClass")
383 ldb.modify(m)
385 # Add an attribute specific to the "bootableDevice" class
386 m = Message()
387 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
388 m["bootParameter"] = MessageElement("test", FLAG_MOD_ADD,
389 "bootParameter")
390 ldb.modify(m)
392 # Classes can be removed unless attributes of them are used. Now there
393 # exist such attributes on the entry.
394 m = Message()
395 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
396 m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
397 "objectClass")
398 try:
399 ldb.modify(m)
400 self.fail()
401 except LdbError as e:
402 (num, _) = e.args
403 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
405 # Remove the previously specified attribute
406 m = Message()
407 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
408 m["bootParameter"] = MessageElement("test", FLAG_MOD_DELETE,
409 "bootParameter")
410 ldb.modify(m)
412 # Classes can be removed unless attributes of them are used.
413 m = Message()
414 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
415 m["objectClass"] = MessageElement("bootableDevice", FLAG_MOD_DELETE,
416 "objectClass")
417 ldb.modify(m)
419 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
421 self.ldb.add({
422 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
423 "objectClass": "user"})
425 # Add a new top-most structural class "container". This does not work
426 # since it stands in no direct relation to the current one.
427 m = Message()
428 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
429 m["objectClass"] = MessageElement("container", FLAG_MOD_ADD,
430 "objectClass")
431 try:
432 ldb.modify(m)
433 self.fail()
434 except LdbError as e:
435 (num, _) = e.args
436 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
438 # Try to add a new top-most structural class "inetOrgPerson"
439 m = Message()
440 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
441 m["objectClass"] = MessageElement("inetOrgPerson", FLAG_MOD_ADD,
442 "objectClass")
443 try:
444 ldb.modify(m)
445 self.fail()
446 except LdbError as e:
447 (num, _) = e.args
448 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
450 # Try to remove the structural class "user"
451 m = Message()
452 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
453 m["objectClass"] = MessageElement("user", FLAG_MOD_DELETE,
454 "objectClass")
455 try:
456 ldb.modify(m)
457 self.fail()
458 except LdbError as e:
459 (num, _) = e.args
460 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
462 # Try to replace top-most structural class to "inetOrgPerson"
463 m = Message()
464 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
465 m["objectClass"] = MessageElement("inetOrgPerson", FLAG_MOD_REPLACE,
466 "objectClass")
467 try:
468 ldb.modify(m)
469 self.fail()
470 except LdbError as e:
471 (num, _) = e.args
472 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
474 # Add a new auxiliary object class "posixAccount" to "ldaptestuser"
475 m = Message()
476 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
477 m["objectClass"] = MessageElement("posixAccount", FLAG_MOD_ADD,
478 "objectClass")
479 ldb.modify(m)
481 # Be sure that "top" is the first and the (most) structural object class
482 # the last value of the "objectClass" attribute - MS-ADTS 3.1.1.1.4
483 res = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
484 scope=SCOPE_BASE, attrs=["objectClass"])
485 self.assertTrue(len(res) == 1)
486 self.assertEqual(str(res[0]["objectClass"][0]), "top")
487 self.assertEqual(str(res[0]["objectClass"][len(res[0]["objectClass"]) - 1]), "user")
489 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
491 def test_system_only(self):
492 """Test systemOnly objects"""
493 try:
494 self.ldb.add({
495 "dn": "cn=ldaptestobject," + self.base_dn,
496 "objectclass": "configuration"})
497 self.fail()
498 except LdbError as e:
499 (num, _) = e.args
500 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
502 try:
503 self.ldb.add({
504 "dn": "cn=Test Secret,cn=system," + self.base_dn,
505 "objectclass": "secret"})
506 self.fail()
507 except LdbError as e:
508 (num, _) = e.args
509 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
511 delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
512 delete_force(self.ldb, "cn=Test Secret,cn=system," + self.base_dn)
514 # Create secret over LSA and try to change it
516 lsa_conn = lsa.lsarpc("ncacn_np:%s" % args[0], lp, creds)
517 lsa_handle = lsa_conn.OpenPolicy2(system_name="\\",
518 attr=lsa.ObjectAttribute(),
519 access_mask=security.SEC_FLAG_MAXIMUM_ALLOWED)
520 secret_name = lsa.String()
521 secret_name.string = "G$Test"
522 sec_handle = lsa_conn.CreateSecret(handle=lsa_handle,
523 name=secret_name,
524 access_mask=security.SEC_FLAG_MAXIMUM_ALLOWED)
525 lsa_conn.Close(lsa_handle)
527 m = Message()
528 m.dn = Dn(ldb, "cn=Test Secret,cn=system," + self.base_dn)
529 m["description"] = MessageElement("desc", FLAG_MOD_REPLACE,
530 "description")
531 try:
532 ldb.modify(m)
533 self.fail()
534 except LdbError as e:
535 (num, _) = e.args
536 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
538 delete_force(self.ldb, "cn=Test Secret,cn=system," + self.base_dn)
540 try:
541 self.ldb.add({
542 "dn": "cn=ldaptestcontainer," + self.base_dn,
543 "objectclass": "container",
544 "isCriticalSystemObject": "TRUE"})
545 self.fail()
546 except LdbError as e:
547 (num, _) = e.args
548 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
550 self.ldb.add({
551 "dn": "cn=ldaptestcontainer," + self.base_dn,
552 "objectclass": "container"})
554 m = Message()
555 m.dn = Dn(ldb, "cn=ldaptestcontainer," + self.base_dn)
556 m["isCriticalSystemObject"] = MessageElement("TRUE", FLAG_MOD_REPLACE,
557 "isCriticalSystemObject")
558 try:
559 ldb.modify(m)
560 self.fail()
561 except LdbError as e:
562 (num, _) = e.args
563 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
565 delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
567 # Proof if DC SAM object has "isCriticalSystemObject" set
568 res = self.ldb.search("", scope=SCOPE_BASE, attrs=["serverName"])
569 self.assertTrue(len(res) == 1)
570 self.assertTrue("serverName" in res[0])
571 res = self.ldb.search(res[0]["serverName"][0], scope=SCOPE_BASE,
572 attrs=["serverReference"])
573 self.assertTrue(len(res) == 1)
574 self.assertTrue("serverReference" in res[0])
575 res = self.ldb.search(res[0]["serverReference"][0], scope=SCOPE_BASE,
576 attrs=["isCriticalSystemObject"])
577 self.assertTrue(len(res) == 1)
578 self.assertTrue("isCriticalSystemObject" in res[0])
579 self.assertEqual(str(res[0]["isCriticalSystemObject"][0]), "TRUE")
581 def test_invalid_parent(self):
582 """Test adding an object with invalid parent"""
583 try:
584 self.ldb.add({
585 "dn": "cn=ldaptestgroup,cn=thisdoesnotexist123,"
586 + self.base_dn,
587 "objectclass": "group"})
588 self.fail()
589 except LdbError as e:
590 (num, _) = e.args
591 self.assertEqual(num, ERR_NO_SUCH_OBJECT)
593 delete_force(self.ldb, "cn=ldaptestgroup,cn=thisdoesnotexist123,"
594 + self.base_dn)
596 try:
597 self.ldb.add({
598 "dn": "ou=testou,cn=users," + self.base_dn,
599 "objectclass": "organizationalUnit"})
600 self.fail()
601 except LdbError as e:
602 (num, _) = e.args
603 self.assertEqual(num, ERR_NAMING_VIOLATION)
605 delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
607 def test_invalid_attribute(self):
608 """Test invalid attributes on schema/objectclasses"""
609 # attributes not in schema test
611 # add operation
613 try:
614 self.ldb.add({
615 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
616 "objectclass": "group",
617 "thisdoesnotexist": "x"})
618 self.fail()
619 except LdbError as e:
620 (num, _) = e.args
621 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
623 self.ldb.add({
624 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
625 "objectclass": "group"})
627 # modify operation
629 m = Message()
630 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
631 m["thisdoesnotexist"] = MessageElement("x", FLAG_MOD_REPLACE,
632 "thisdoesnotexist")
633 try:
634 ldb.modify(m)
635 self.fail()
636 except LdbError as e:
637 (num, _) = e.args
638 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
641 # When searching the unknown attribute should be ignored
642 expr = "(|(cn=ldaptestgroup)(thisdoesnotexist=x))"
643 res = ldb.search(base=self.base_dn,
644 expression=expr,
645 scope=SCOPE_SUBTREE)
646 self.assertTrue(len(res) == 1,
647 "Search including unknown attribute failed")
649 # likewise, if we specifically request an unknown attribute
650 res = ldb.search(base=self.base_dn,
651 expression="(cn=ldaptestgroup)",
652 scope=SCOPE_SUBTREE,
653 attrs=["thisdoesnotexist"])
654 self.assertTrue(len(res) == 1,
655 "Search requesting unknown attribute failed")
657 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
659 # attributes not in objectclasses and mandatory attributes missing test
660 # Use here a non-SAM entry since it doesn't have special triggers
661 # associated which have an impact on the error results.
663 # add operations
665 # mandatory attribute missing
666 try:
667 self.ldb.add({
668 "dn": "cn=ldaptestobject," + self.base_dn,
669 "objectclass": "ipProtocol"})
670 self.fail()
671 except LdbError as e:
672 (num, _) = e.args
673 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
675 # inadequate but schema-valid attribute specified
676 try:
677 self.ldb.add({
678 "dn": "cn=ldaptestobject," + self.base_dn,
679 "objectclass": "ipProtocol",
680 "ipProtocolNumber": "1",
681 "uid": "0"})
682 self.fail()
683 except LdbError as e:
684 (num, _) = e.args
685 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
687 self.ldb.add({
688 "dn": "cn=ldaptestobject," + self.base_dn,
689 "objectclass": "ipProtocol",
690 "ipProtocolNumber": "1"})
692 # modify operations
694 # inadequate but schema-valid attribute add trial
695 m = Message()
696 m.dn = Dn(ldb, "cn=ldaptestobject," + self.base_dn)
697 m["uid"] = MessageElement("0", FLAG_MOD_ADD, "uid")
698 try:
699 ldb.modify(m)
700 self.fail()
701 except LdbError as e:
702 (num, _) = e.args
703 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
705 # mandatory attribute delete trial
706 m = Message()
707 m.dn = Dn(ldb, "cn=ldaptestobject," + self.base_dn)
708 m["ipProtocolNumber"] = MessageElement([], FLAG_MOD_DELETE,
709 "ipProtocolNumber")
710 try:
711 ldb.modify(m)
712 self.fail()
713 except LdbError as e:
714 (num, _) = e.args
715 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
717 # mandatory attribute delete trial
718 m = Message()
719 m.dn = Dn(ldb, "cn=ldaptestobject," + self.base_dn)
720 m["ipProtocolNumber"] = MessageElement([], FLAG_MOD_REPLACE,
721 "ipProtocolNumber")
722 try:
723 ldb.modify(m)
724 self.fail()
725 except LdbError as e:
726 (num, _) = e.args
727 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
729 delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
731 def test_single_valued_attributes(self):
732 """Test single-valued attributes"""
733 try:
734 self.ldb.add({
735 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
736 "objectclass": "group",
737 "sAMAccountName": ["nam1", "nam2"]})
738 self.fail()
739 except LdbError as e:
740 (num, _) = e.args
741 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
743 self.ldb.add({
744 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
745 "objectclass": "group"})
747 m = Message()
748 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
749 m["sAMAccountName"] = MessageElement(["nam1", "nam2"], FLAG_MOD_REPLACE,
750 "sAMAccountName")
751 try:
752 ldb.modify(m)
753 self.fail()
754 except LdbError as e:
755 (num, _) = e.args
756 self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
758 m = Message()
759 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
760 m["sAMAccountName"] = MessageElement("testgroupXX", FLAG_MOD_REPLACE,
761 "sAMAccountName")
762 ldb.modify(m)
764 m = Message()
765 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
766 m["sAMAccountName"] = MessageElement("testgroupXX2", FLAG_MOD_ADD,
767 "sAMAccountName")
768 try:
769 ldb.modify(m)
770 self.fail()
771 except LdbError as e:
772 (num, _) = e.args
773 self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
775 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
777 def test_single_valued_linked_attributes(self):
778 """Test managedBy, a single-valued linked attribute.
780 (The single-valuedness of this is enforced differently, in
781 repl_meta_data.c)
783 ou = 'OU=svla,%s' % (self.base_dn)
785 delete_force(self.ldb, ou, controls=['tree_delete:1'])
787 self.ldb.add({'objectclass': 'organizationalUnit',
788 'dn': ou})
790 managers = []
791 for x in range(3):
792 m = "cn=manager%d,%s" % (x, ou)
793 self.ldb.add({
794 "dn": m,
795 "objectclass": "user"})
796 managers.append(m)
798 try:
799 self.ldb.add({
800 "dn": "cn=group1," + ou,
801 "objectclass": "group",
802 "managedBy": managers
804 self.fail("failed to fail to add multiple managedBy attributes")
805 except LdbError as e:
806 (num, _) = e.args
807 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
809 managee = "cn=group2," + ou
810 self.ldb.add({
811 "dn": managee,
812 "objectclass": "group",
813 "managedBy": [managers[0]]})
815 m = Message()
816 m.dn = Dn(ldb, managee)
817 m["managedBy"] = MessageElement(managers, FLAG_MOD_REPLACE,
818 "managedBy")
819 try:
820 ldb.modify(m)
821 self.fail()
822 except LdbError as e:
823 (num, _) = e.args
824 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
826 m = Message()
827 m.dn = Dn(ldb, managee)
828 m["managedBy"] = MessageElement(managers[1], FLAG_MOD_REPLACE,
829 "managedBy")
830 ldb.modify(m)
832 m = Message()
833 m.dn = Dn(ldb, managee)
834 m["managedBy"] = MessageElement(managers[2], FLAG_MOD_ADD,
835 "managedBy")
836 try:
837 ldb.modify(m)
838 self.fail()
839 except LdbError as e:
840 (num, _) = e.args
841 self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
843 self.ldb.delete(ou, ['tree_delete:1'])
845 def test_multivalued_attributes(self):
846 """Test multi-valued attributes"""
847 ou = 'OU=mvattr,%s' % (self.base_dn)
848 delete_force(self.ldb, ou, controls=['tree_delete:1'])
849 self.ldb.add({'objectclass': 'organizationalUnit',
850 'dn': ou})
852 # beyond 1210, Win2012r2 gives LDAP_ADMIN_LIMIT_EXCEEDED
853 ranges = (3, 30, 300, 1210)
855 for n in ranges:
856 self.ldb.add({
857 "dn": "cn=ldaptestuser%d,%s" % (n, ou),
858 "objectclass": "user",
859 "carLicense": ["car%d" % x for x in range(n)]})
861 # add some more
862 for n in ranges:
863 m = Message()
864 m.dn = Dn(ldb, "cn=ldaptestuser%d,%s" % (n, ou))
865 m["carLicense"] = MessageElement(["another"],
866 FLAG_MOD_ADD,
867 "carLicense")
868 ldb.modify(m)
870 m = Message()
871 m.dn = Dn(ldb, "cn=ldaptestuser%d,%s" % (n, ou))
872 m["carLicense"] = MessageElement(["foo%d" % x for x in range(4)],
873 FLAG_MOD_ADD,
874 "carLicense")
875 ldb.modify(m)
877 m = Message()
878 m.dn = Dn(ldb, "cn=ldaptestuser%d,%s" % (n, ou))
879 m["carLicense"] = MessageElement(["bar%d" % x for x in range(40)],
880 FLAG_MOD_ADD,
881 "carLicense")
882 ldb.modify(m)
884 for n in ranges:
885 m = Message()
886 dn = "cn=ldaptestuser%d,%s" % (n, ou)
887 m.dn = Dn(ldb, dn)
888 m["carLicense"] = MessageElement(["replacement"],
889 FLAG_MOD_REPLACE,
890 "carLicense")
891 ldb.modify(m)
893 m = Message()
894 m.dn = Dn(ldb, dn)
895 m["carLicense"] = MessageElement(["replacement%d" % x for x in range(n)],
896 FLAG_MOD_REPLACE,
897 "carLicense")
898 ldb.modify(m)
900 m = Message()
901 m.dn = Dn(ldb, dn)
902 m["carLicense"] = MessageElement(["again%d" % x for x in range(n)],
903 FLAG_MOD_REPLACE,
904 "carLicense")
905 ldb.modify(m)
907 m = Message()
908 m.dn = Dn(ldb, dn)
909 m["carLicense"] = MessageElement(["andagain%d" % x for x in range(n)],
910 FLAG_MOD_REPLACE,
911 "carLicense")
912 ldb.modify(m)
914 self.ldb.delete(ou, ['tree_delete:1'])
916 def test_attribute_ranges(self):
917 """Test attribute ranges"""
918 # Too short (min. 1)
919 try:
920 ldb.add({
921 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
922 "objectClass": "person",
923 "sn": ""})
924 self.fail()
925 except LdbError as e:
926 (num, _) = e.args
927 self.assertEqual(num, ERR_INVALID_ATTRIBUTE_SYNTAX)
929 ldb.add({
930 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
931 "objectClass": "person"})
933 # Too short (min. 1)
934 m = Message()
935 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
936 m["sn"] = MessageElement("", FLAG_MOD_REPLACE, "sn")
937 try:
938 ldb.modify(m)
939 self.fail()
940 except LdbError as e:
941 (num, _) = e.args
942 self.assertEqual(num, ERR_INVALID_ATTRIBUTE_SYNTAX)
945 m = Message()
946 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
947 m["sn"] = MessageElement("x", FLAG_MOD_REPLACE, "sn")
948 ldb.modify(m)
950 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
952 def test_attribute_ranges_too_long(self):
953 """Test attribute ranges"""
954 # This is knownfail with the wrong error
955 # (INVALID_ATTRIBUTE_SYNTAX vs CONSTRAINT_VIOLATION per Windows)
957 # Too long (max. 64)
958 try:
959 ldb.add({
960 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
961 "objectClass": "person",
962 "sn": "x" * 65 })
963 self.fail()
964 except LdbError as e:
965 (num, _) = e.args
966 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
968 ldb.add({
969 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
970 "objectClass": "person"})
972 # Too long (max. 64)
973 m = Message()
974 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
975 m["sn"] = MessageElement("x" * 66, FLAG_MOD_REPLACE, "sn")
976 try:
977 ldb.modify(m)
978 self.fail()
979 except LdbError as e:
980 self.assertEqual(e.args[0], ERR_CONSTRAINT_VIOLATION)
982 def test_empty_messages(self):
983 """Test empty messages"""
984 m = Message()
985 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
987 try:
988 ldb.add(m)
989 self.fail()
990 except LdbError as e:
991 (num, _) = e.args
992 self.assertEqual(num, ERR_OBJECT_CLASS_VIOLATION)
994 try:
995 ldb.modify(m)
996 self.fail()
997 except LdbError as e:
998 (num, _) = e.args
999 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1001 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1003 def test_empty_attributes(self):
1004 """Test empty attributes"""
1005 m = Message()
1006 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1007 m["objectClass"] = MessageElement("group", FLAG_MOD_ADD, "objectClass")
1008 m["description"] = MessageElement([], FLAG_MOD_ADD, "description")
1010 try:
1011 ldb.add(m)
1012 self.fail()
1013 except LdbError as e:
1014 (num, _) = e.args
1015 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1017 self.ldb.add({
1018 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1019 "objectclass": "group"})
1021 m = Message()
1022 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1023 m["description"] = MessageElement([], FLAG_MOD_ADD, "description")
1025 try:
1026 ldb.modify(m)
1027 self.fail()
1028 except LdbError as e:
1029 (num, _) = e.args
1030 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1032 m = Message()
1033 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1034 m["description"] = MessageElement([], FLAG_MOD_REPLACE, "description")
1035 ldb.modify(m)
1037 m = Message()
1038 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1039 m["description"] = MessageElement([], FLAG_MOD_DELETE, "description")
1040 try:
1041 ldb.modify(m)
1042 self.fail()
1043 except LdbError as e:
1044 (num, _) = e.args
1045 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
1047 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1049 def test_instanceType(self):
1050 """Tests the 'instanceType' attribute"""
1051 # The instance type is single-valued
1052 try:
1053 self.ldb.add({
1054 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1055 "objectclass": "group",
1056 "instanceType": ["0", "1"]})
1057 self.fail()
1058 except LdbError as e:
1059 (num, _) = e.args
1060 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1062 # The head NC flag cannot be set without the write flag
1063 try:
1064 self.ldb.add({
1065 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1066 "objectclass": "group",
1067 "instanceType": "1"})
1068 self.fail()
1069 except LdbError as e:
1070 (num, _) = e.args
1071 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1073 # We cannot manipulate NCs without the head NC flag
1074 try:
1075 self.ldb.add({
1076 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1077 "objectclass": "group",
1078 "instanceType": "32"})
1079 self.fail()
1080 except LdbError as e:
1081 (num, _) = e.args
1082 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1084 self.ldb.add({
1085 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1086 "objectclass": "group"})
1088 m = Message()
1089 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1090 m["instanceType"] = MessageElement("0", FLAG_MOD_REPLACE,
1091 "instanceType")
1092 try:
1093 ldb.modify(m)
1094 self.fail()
1095 except LdbError as e:
1096 (num, _) = e.args
1097 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1099 m = Message()
1100 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1101 m["instanceType"] = MessageElement([], FLAG_MOD_REPLACE,
1102 "instanceType")
1103 try:
1104 ldb.modify(m)
1105 self.fail()
1106 except LdbError as e:
1107 (num, _) = e.args
1108 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1110 m = Message()
1111 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1112 m["instanceType"] = MessageElement([], FLAG_MOD_DELETE, "instanceType")
1113 try:
1114 ldb.modify(m)
1115 self.fail()
1116 except LdbError as e:
1117 (num, _) = e.args
1118 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1120 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1122 # only write is allowed with NC_HEAD for originating updates
1123 try:
1124 self.ldb.add({
1125 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
1126 "objectclass": "user",
1127 "instanceType": "3"})
1128 self.fail()
1129 except LdbError as e:
1130 (num, _) = e.args
1131 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1132 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
1134 def test_distinguished_name(self):
1135 """Tests the 'distinguishedName' attribute"""
1136 # The "dn" shortcut isn't supported
1137 m = Message()
1138 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1139 m["objectClass"] = MessageElement("group", 0, "objectClass")
1140 m["dn"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn, 0,
1141 "dn")
1142 try:
1143 ldb.add(m)
1144 self.fail()
1145 except LdbError as e:
1146 (num, _) = e.args
1147 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
1149 # a wrong "distinguishedName" attribute is obviously tolerated
1150 self.ldb.add({
1151 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1152 "objectclass": "group",
1153 "distinguishedName": "cn=ldaptest,cn=users," + self.base_dn})
1155 # proof if the DN has been set correctly
1156 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1157 scope=SCOPE_BASE, attrs=["distinguishedName"])
1158 self.assertTrue(len(res) == 1)
1159 self.assertTrue("distinguishedName" in res[0])
1160 self.assertTrue(Dn(ldb, str(res[0]["distinguishedName"][0]))
1161 == Dn(ldb, "cn=ldaptestgroup, cn=users," + self.base_dn))
1163 # The "dn" shortcut isn't supported
1164 m = Message()
1165 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1166 m["dn"] = MessageElement(
1167 "cn=ldaptestgroup,cn=users," + self.base_dn, FLAG_MOD_REPLACE,
1168 "dn")
1169 try:
1170 ldb.modify(m)
1171 self.fail()
1172 except LdbError as e:
1173 (num, _) = e.args
1174 self.assertEqual(num, ERR_NO_SUCH_ATTRIBUTE)
1176 m = Message()
1177 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1178 m["distinguishedName"] = MessageElement(
1179 "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_ADD,
1180 "distinguishedName")
1182 try:
1183 ldb.modify(m)
1184 self.fail()
1185 except LdbError as e:
1186 (num, _) = e.args
1187 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1189 m = Message()
1190 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1191 m["distinguishedName"] = MessageElement(
1192 "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_REPLACE,
1193 "distinguishedName")
1195 try:
1196 ldb.modify(m)
1197 self.fail()
1198 except LdbError as e:
1199 (num, _) = e.args
1200 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1202 m = Message()
1203 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1204 m["distinguishedName"] = MessageElement(
1205 "cn=ldaptestuser,cn=users," + self.base_dn, FLAG_MOD_DELETE,
1206 "distinguishedName")
1208 try:
1209 ldb.modify(m)
1210 self.fail()
1211 except LdbError as e:
1212 (num, _) = e.args
1213 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1215 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1217 def test_rdn_name(self):
1218 """Tests the RDN"""
1219 # Search
1221 # empty RDN
1222 try:
1223 self.ldb.search("=,cn=users," + self.base_dn, scope=SCOPE_BASE)
1224 self.fail()
1225 except LdbError as e:
1226 (num, _) = e.args
1227 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1229 # empty RDN name
1230 try:
1231 self.ldb.search("cn=,cn=users," + self.base_dn, scope=SCOPE_BASE)
1232 self.fail()
1233 except LdbError as e:
1234 (num, _) = e.args
1235 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1237 try:
1238 self.ldb.search("=ldaptestgroup,cn=users," + self.base_dn, scope=SCOPE_BASE)
1239 self.fail()
1240 except LdbError as e:
1241 (num, _) = e.args
1242 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1244 # Add
1246 # empty RDN
1247 try:
1248 self.ldb.add({
1249 "dn": "=,cn=users," + self.base_dn,
1250 "objectclass": "group"})
1251 self.fail()
1252 except LdbError as e:
1253 (num, _) = e.args
1254 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1256 # empty RDN name
1257 try:
1258 self.ldb.add({
1259 "dn": "=ldaptestgroup,cn=users," + self.base_dn,
1260 "objectclass": "group"})
1261 self.fail()
1262 except LdbError as e:
1263 (num, _) = e.args
1264 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1266 # empty RDN value
1267 try:
1268 self.ldb.add({
1269 "dn": "cn=,cn=users," + self.base_dn,
1270 "objectclass": "group"})
1271 self.fail()
1272 except LdbError as e:
1273 (num, _) = e.args
1274 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1276 # a wrong RDN candidate
1277 try:
1278 self.ldb.add({
1279 "dn": "description=xyz,cn=users," + self.base_dn,
1280 "objectclass": "group"})
1281 self.fail()
1282 except LdbError as e:
1283 (num, _) = e.args
1284 self.assertEqual(num, ERR_NAMING_VIOLATION)
1286 delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
1288 # a wrong "name" attribute is obviously tolerated
1289 self.ldb.add({
1290 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1291 "objectclass": "group",
1292 "name": "ldaptestgroupx"})
1294 # proof if the name has been set correctly
1295 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1296 scope=SCOPE_BASE, attrs=["name"])
1297 self.assertTrue(len(res) == 1)
1298 self.assertTrue("name" in res[0])
1299 self.assertTrue(str(res[0]["name"][0]) == "ldaptestgroup")
1301 # Modify
1303 # empty RDN value
1304 m = Message()
1305 m.dn = Dn(ldb, "cn=,cn=users," + self.base_dn)
1306 m["description"] = "test"
1307 try:
1308 self.ldb.modify(m)
1309 self.fail()
1310 except LdbError as e:
1311 (num, _) = e.args
1312 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1314 # Delete
1316 # empty RDN value
1317 try:
1318 self.ldb.delete("cn=,cn=users," + self.base_dn)
1319 self.fail()
1320 except LdbError as e:
1321 (num, _) = e.args
1322 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1324 # Rename
1326 # new empty RDN
1327 try:
1328 self.ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn,
1329 "=,cn=users," + self.base_dn)
1330 self.fail()
1331 except LdbError as e:
1332 (num, _) = e.args
1333 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1335 # new empty RDN name
1336 try:
1337 self.ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn,
1338 "=ldaptestgroup,cn=users," + self.base_dn)
1339 self.fail()
1340 except LdbError as e:
1341 (num, _) = e.args
1342 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1344 # new empty RDN value
1345 try:
1346 self.ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn,
1347 "cn=,cn=users," + self.base_dn)
1348 self.fail()
1349 except LdbError as e:
1350 (num, _) = e.args
1351 self.assertEqual(num, ERR_NAMING_VIOLATION)
1353 # new wrong RDN candidate
1354 try:
1355 self.ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn,
1356 "description=xyz,cn=users," + self.base_dn)
1357 self.fail()
1358 except LdbError as e:
1359 (num, _) = e.args
1360 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1362 delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
1364 # old empty RDN value
1365 try:
1366 self.ldb.rename("cn=,cn=users," + self.base_dn,
1367 "cn=ldaptestgroup,cn=users," + self.base_dn)
1368 self.fail()
1369 except LdbError as e:
1370 (num, _) = e.args
1371 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1373 # names
1375 m = Message()
1376 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1377 m["name"] = MessageElement("cn=ldaptestuser", FLAG_MOD_REPLACE,
1378 "name")
1379 try:
1380 ldb.modify(m)
1381 self.fail()
1382 except LdbError as e:
1383 (num, _) = e.args
1384 self.assertEqual(num, ERR_NOT_ALLOWED_ON_RDN)
1386 m = Message()
1387 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1388 m["cn"] = MessageElement("ldaptestuser",
1389 FLAG_MOD_REPLACE, "cn")
1390 try:
1391 ldb.modify(m)
1392 self.fail()
1393 except LdbError as e:
1394 (num, _) = e.args
1395 self.assertEqual(num, ERR_NOT_ALLOWED_ON_RDN)
1397 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1399 # this test needs to be disabled until we really understand
1400 # what the rDN length constraints are
1402 def DISABLED_test_largeRDN(self):
1403 """Testing large rDN (limit 64 characters)"""
1404 rdn = "CN=a012345678901234567890123456789012345678901234567890123456789012"
1405 delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
1406 ldif = """
1407 dn: %s,%s""" % (rdn, self.base_dn) + """
1408 objectClass: container
1410 self.ldb.add_ldif(ldif)
1411 delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
1413 rdn = "CN=a0123456789012345678901234567890123456789012345678901234567890120"
1414 delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
1415 try:
1416 ldif = """
1417 dn: %s,%s""" % (rdn, self.base_dn) + """
1418 objectClass: container
1420 self.ldb.add_ldif(ldif)
1421 self.fail()
1422 except LdbError as e:
1423 (num, _) = e.args
1424 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1425 delete_force(self.ldb, "%s,%s" % (rdn, self.base_dn))
1427 def test_rename(self):
1428 """Tests the rename operation"""
1429 try:
1430 # cannot rename to be a child of itself
1431 ldb.rename(self.base_dn, "dc=test," + self.base_dn)
1432 self.fail()
1433 except LdbError as e:
1434 (num, _) = e.args
1435 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1437 try:
1438 # inexistent object
1439 ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
1440 self.fail()
1441 except LdbError as e:
1442 (num, _) = e.args
1443 self.assertEqual(num, ERR_NO_SUCH_OBJECT)
1445 self.ldb.add({
1446 "dn": "cn=ldaptestuser2,cn=users," + self.base_dn,
1447 "objectclass": "user"})
1449 ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
1450 ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
1451 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestUSER3,cn=users," + self.base_dn)
1453 try:
1454 # containment problem: a user entry cannot contain user entries
1455 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser4,cn=ldaptestuser3,cn=users," + self.base_dn)
1456 self.fail()
1457 except LdbError as e:
1458 (num, _) = e.args
1459 self.assertEqual(num, ERR_NAMING_VIOLATION)
1461 try:
1462 # invalid parent
1463 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=people,cn=users," + self.base_dn)
1464 self.fail()
1465 except LdbError as e:
1466 (num, _) = e.args
1467 self.assertEqual(num, ERR_OTHER)
1469 try:
1470 # invalid target DN syntax
1471 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, ",cn=users," + self.base_dn)
1472 self.fail()
1473 except LdbError as e:
1474 (num, _) = e.args
1475 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1477 try:
1478 # invalid RDN name
1479 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "ou=ldaptestuser3,cn=users," + self.base_dn)
1480 self.fail()
1481 except LdbError as e:
1482 (num, _) = e.args
1483 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1485 delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
1487 # Performs some "systemFlags" testing
1489 # Move failing since no "SYSTEM_FLAG_CONFIG_ALLOW_MOVE"
1490 try:
1491 ldb.rename("CN=DisplaySpecifiers," + self.configuration_dn, "CN=DisplaySpecifiers,CN=Services," + self.configuration_dn)
1492 self.fail()
1493 except LdbError as e:
1494 (num, _) = e.args
1495 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1497 # Limited move failing since no "SYSTEM_FLAG_CONFIG_ALLOW_LIMITED_MOVE"
1498 try:
1499 ldb.rename("CN=Directory Service,CN=Windows NT,CN=Services," + self.configuration_dn, "CN=Directory Service,CN=RRAS,CN=Services," + self.configuration_dn)
1500 self.fail()
1501 except LdbError as e:
1502 (num, _) = e.args
1503 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1505 # Rename failing since no "SYSTEM_FLAG_CONFIG_ALLOW_RENAME"
1506 try:
1507 ldb.rename("CN=DisplaySpecifiers," + self.configuration_dn, "CN=DisplaySpecifiers2," + self.configuration_dn)
1508 self.fail()
1509 except LdbError as e:
1510 (num, _) = e.args
1511 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1513 # It's not really possible to test moves on the schema partition since
1514 # there don't exist subcontainers on it.
1516 # Rename failing since "SYSTEM_FLAG_SCHEMA_BASE_OBJECT"
1517 try:
1518 ldb.rename("CN=Top," + self.schema_dn, "CN=Top2," + self.schema_dn)
1519 self.fail()
1520 except LdbError as e:
1521 (num, _) = e.args
1522 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1524 # Move failing since "SYSTEM_FLAG_DOMAIN_DISALLOW_MOVE"
1525 try:
1526 ldb.rename("CN=Users," + self.base_dn, "CN=Users,CN=Computers," + self.base_dn)
1527 self.fail()
1528 except LdbError as e:
1529 (num, _) = e.args
1530 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1532 # Rename failing since "SYSTEM_FLAG_DOMAIN_DISALLOW_RENAME"
1533 try:
1534 ldb.rename("CN=Users," + self.base_dn, "CN=Users2," + self.base_dn)
1535 self.fail()
1536 except LdbError as e:
1537 (num, _) = e.args
1538 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1540 # Performs some other constraints testing
1542 try:
1543 ldb.rename("CN=Policies,CN=System," + self.base_dn, "CN=Users2," + self.base_dn)
1544 self.fail()
1545 except LdbError as e:
1546 (num, _) = e.args
1547 self.assertEqual(num, ERR_OTHER)
1549 def test_rename_twice(self):
1550 """Tests the rename operation twice - this corresponds to a past bug"""
1551 self.ldb.add({
1552 "dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
1553 "objectclass": "user"})
1555 ldb.rename("cn=ldaptestuser5,cn=users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
1556 delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
1557 self.ldb.add({
1558 "dn": "cn=ldaptestuser5,cn=users," + self.base_dn,
1559 "objectclass": "user"})
1560 ldb.rename("cn=ldaptestuser5,cn=Users," + self.base_dn, "cn=ldaptestUSER5,cn=users," + self.base_dn)
1561 res = ldb.search(expression="cn=ldaptestuser5")
1562 self.assertEqual(len(res), 1, "Wrong number of hits for cn=ldaptestuser5")
1563 res = ldb.search(expression="(&(cn=ldaptestuser5)(objectclass=user))")
1564 self.assertEqual(len(res), 1, "Wrong number of hits for (&(cn=ldaptestuser5)(objectclass=user))")
1565 delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
1567 def test_objectGUID(self):
1568 """Test objectGUID behaviour"""
1569 # The objectGUID cannot directly be set
1570 try:
1571 self.ldb.add_ldif("""
1572 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1573 objectClass: container
1574 objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d
1575 """)
1576 self.fail()
1577 except LdbError as e:
1578 (num, _) = e.args
1579 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1581 self.ldb.add({
1582 "dn": "cn=ldaptestcontainer," + self.base_dn,
1583 "objectClass": "container"})
1585 # The objectGUID cannot directly be changed
1586 try:
1587 self.ldb.modify_ldif("""
1588 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1589 changetype: modify
1590 replace: objectGUID
1591 objectGUID: bd3480c9-58af-4cd8-92df-bc4a18b6e44d
1592 """)
1593 self.fail()
1594 except LdbError as e:
1595 (num, _) = e.args
1596 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
1598 delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
1600 def test_parentGUID(self):
1601 """Test parentGUID behaviour"""
1602 self.ldb.add({
1603 "dn": "cn=parentguidtest,cn=users," + self.base_dn,
1604 "objectclass": "user",
1605 "samaccountname": "parentguidtest"})
1606 res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE,
1607 attrs=["parentGUID", "samaccountname"])
1608 res2 = ldb.search(base="cn=users," + self.base_dn, scope=SCOPE_BASE,
1609 attrs=["objectGUID"])
1610 res3 = ldb.search(base=self.base_dn, scope=SCOPE_BASE,
1611 attrs=["parentGUID"])
1612 res4 = ldb.search(base=self.configuration_dn, scope=SCOPE_BASE,
1613 attrs=["parentGUID"])
1614 res5 = ldb.search(base=self.schema_dn, scope=SCOPE_BASE,
1615 attrs=["parentGUID"])
1617 """Check if the parentGUID is valid """
1618 self.assertEqual(res1[0]["parentGUID"], res2[0]["objectGUID"])
1620 """Check if it returns nothing when there is no parent object - default NC"""
1621 has_parentGUID = False
1622 for key in res3[0].keys():
1623 if key == "parentGUID":
1624 has_parentGUID = True
1625 break
1626 self.assertFalse(has_parentGUID)
1628 """Check if it returns nothing when there is no parent object - configuration NC"""
1629 has_parentGUID = False
1630 for key in res4[0].keys():
1631 if key == "parentGUID":
1632 has_parentGUID = True
1633 break
1634 self.assertFalse(has_parentGUID)
1636 """Check if it returns nothing when there is no parent object - schema NC"""
1637 has_parentGUID = False
1638 for key in res5[0].keys():
1639 if key == "parentGUID":
1640 has_parentGUID = True
1641 break
1642 self.assertFalse(has_parentGUID)
1644 """Ensures that if you look for another object attribute after the constructed
1645 parentGUID, it will return correctly"""
1646 has_another_attribute = False
1647 for key in res1[0].keys():
1648 if key == "sAMAccountName":
1649 has_another_attribute = True
1650 break
1651 self.assertTrue(has_another_attribute)
1652 self.assertTrue(len(res1[0]["samaccountname"]) == 1)
1653 self.assertEqual(str(res1[0]["samaccountname"][0]), "parentguidtest")
1655 # Testing parentGUID behaviour on rename\
1657 self.ldb.add({
1658 "dn": "cn=testotherusers," + self.base_dn,
1659 "objectclass": "container"})
1660 res1 = ldb.search(base="cn=testotherusers," + self.base_dn, scope=SCOPE_BASE,
1661 attrs=["objectGUID"])
1662 ldb.rename("cn=parentguidtest,cn=users," + self.base_dn,
1663 "cn=parentguidtest,cn=testotherusers," + self.base_dn)
1664 res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn,
1665 scope=SCOPE_BASE,
1666 attrs=["parentGUID"])
1667 self.assertEqual(res1[0]["objectGUID"], res2[0]["parentGUID"])
1669 delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
1670 delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
1672 def test_usnChanged(self):
1673 """Test usnChanged behaviour"""
1675 self.ldb.add({
1676 "dn": "cn=ldaptestcontainer," + self.base_dn,
1677 "objectClass": "container"})
1679 res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1680 scope=SCOPE_BASE,
1681 attrs=["objectGUID", "uSNCreated", "uSNChanged", "whenCreated", "whenChanged", "description"])
1682 self.assertTrue(len(res) == 1)
1683 self.assertFalse("description" in res[0])
1684 self.assertTrue("objectGUID" in res[0])
1685 self.assertTrue("uSNCreated" in res[0])
1686 self.assertTrue("uSNChanged" in res[0])
1687 self.assertTrue("whenCreated" in res[0])
1688 self.assertTrue("whenChanged" in res[0])
1690 delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
1692 # All these attributes are specifiable on add operations
1693 self.ldb.add({
1694 "dn": "cn=ldaptestcontainer," + self.base_dn,
1695 "objectclass": "container",
1696 "uSNCreated": "1",
1697 "uSNChanged": "1",
1698 "whenCreated": timestring(int(time.time())),
1699 "whenChanged": timestring(int(time.time()))})
1701 res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1702 scope=SCOPE_BASE,
1703 attrs=["objectGUID", "uSNCreated", "uSNChanged", "whenCreated", "whenChanged", "description"])
1704 self.assertTrue(len(res) == 1)
1705 self.assertFalse("description" in res[0])
1706 self.assertTrue("objectGUID" in res[0])
1707 self.assertTrue("uSNCreated" in res[0])
1708 self.assertFalse(res[0]["uSNCreated"][0] == "1") # these are corrected
1709 self.assertTrue("uSNChanged" in res[0])
1710 self.assertFalse(res[0]["uSNChanged"][0] == "1") # these are corrected
1711 self.assertTrue("whenCreated" in res[0])
1712 self.assertTrue("whenChanged" in res[0])
1714 ldb.modify_ldif("""
1715 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1716 changetype: modify
1717 replace: description
1718 """)
1720 res2 = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1721 scope=SCOPE_BASE,
1722 attrs=["uSNCreated", "uSNChanged", "description"])
1723 self.assertTrue(len(res) == 1)
1724 self.assertFalse("description" in res2[0])
1725 self.assertEqual(res[0]["usnCreated"], res2[0]["usnCreated"])
1726 self.assertEqual(res[0]["usnCreated"], res2[0]["usnChanged"])
1727 self.assertEqual(res[0]["usnChanged"], res2[0]["usnChanged"])
1729 ldb.modify_ldif("""
1730 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1731 changetype: modify
1732 replace: description
1733 description: test
1734 """)
1736 res3 = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1737 scope=SCOPE_BASE,
1738 attrs=["uSNCreated", "uSNChanged", "description"])
1739 self.assertTrue(len(res) == 1)
1740 self.assertTrue("description" in res3[0])
1741 self.assertEqual("test", str(res3[0]["description"][0]))
1742 self.assertEqual(res[0]["usnCreated"], res3[0]["usnCreated"])
1743 self.assertNotEqual(res[0]["usnCreated"], res3[0]["usnChanged"])
1744 self.assertNotEqual(res[0]["usnChanged"], res3[0]["usnChanged"])
1746 ldb.modify_ldif("""
1747 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1748 changetype: modify
1749 replace: description
1750 description: test
1751 """)
1753 res4 = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1754 scope=SCOPE_BASE,
1755 attrs=["uSNCreated", "uSNChanged", "description"])
1756 self.assertTrue(len(res) == 1)
1757 self.assertTrue("description" in res4[0])
1758 self.assertEqual("test", str(res4[0]["description"][0]))
1759 self.assertEqual(res[0]["usnCreated"], res4[0]["usnCreated"])
1760 self.assertNotEqual(res3[0]["usnCreated"], res4[0]["usnChanged"])
1761 self.assertEqual(res3[0]["usnChanged"], res4[0]["usnChanged"])
1763 ldb.modify_ldif("""
1764 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1765 changetype: modify
1766 replace: description
1767 description: test2
1768 """)
1770 res5 = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1771 scope=SCOPE_BASE,
1772 attrs=["uSNCreated", "uSNChanged", "description"])
1773 self.assertTrue(len(res) == 1)
1774 self.assertTrue("description" in res5[0])
1775 self.assertEqual("test2", str(res5[0]["description"][0]))
1776 self.assertEqual(res[0]["usnCreated"], res5[0]["usnCreated"])
1777 self.assertNotEqual(res3[0]["usnChanged"], res5[0]["usnChanged"])
1779 ldb.modify_ldif("""
1780 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1781 changetype: modify
1782 delete: description
1783 description: test2
1784 """)
1786 res6 = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1787 scope=SCOPE_BASE,
1788 attrs=["uSNCreated", "uSNChanged", "description"])
1789 self.assertTrue(len(res) == 1)
1790 self.assertFalse("description" in res6[0])
1791 self.assertEqual(res[0]["usnCreated"], res6[0]["usnCreated"])
1792 self.assertNotEqual(res5[0]["usnChanged"], res6[0]["usnChanged"])
1794 ldb.modify_ldif("""
1795 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1796 changetype: modify
1797 add: description
1798 description: test3
1799 """)
1801 res7 = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1802 scope=SCOPE_BASE,
1803 attrs=["uSNCreated", "uSNChanged", "description"])
1804 self.assertTrue(len(res) == 1)
1805 self.assertTrue("description" in res7[0])
1806 self.assertEqual("test3", str(res7[0]["description"][0]))
1807 self.assertEqual(res[0]["usnCreated"], res7[0]["usnCreated"])
1808 self.assertNotEqual(res6[0]["usnChanged"], res7[0]["usnChanged"])
1810 ldb.modify_ldif("""
1811 dn: cn=ldaptestcontainer,""" + self.base_dn + """
1812 changetype: modify
1813 delete: description
1814 """)
1816 res8 = ldb.search("cn=ldaptestcontainer," + self.base_dn,
1817 scope=SCOPE_BASE,
1818 attrs=["uSNCreated", "uSNChanged", "description"])
1819 self.assertTrue(len(res) == 1)
1820 self.assertFalse("description" in res8[0])
1821 self.assertEqual(res[0]["usnCreated"], res8[0]["usnCreated"])
1822 self.assertNotEqual(res7[0]["usnChanged"], res8[0]["usnChanged"])
1824 delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
1826 def test_groupType_int32(self):
1827 """Test groupType (int32) behaviour (should appear to be cast to a 32 bit signed integer before comparison)"""
1829 res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
1830 attrs=["groupType"], expression="groupType=2147483653")
1832 res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
1833 attrs=["groupType"], expression="groupType=-2147483643")
1835 self.assertEqual(len(res1), len(res2))
1837 self.assertTrue(res1.count > 0)
1839 self.assertEqual(str(res1[0]["groupType"][0]), "-2147483643")
1841 def test_linked_attributes(self):
1842 """This tests the linked attribute behaviour"""
1844 ldb.add({
1845 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1846 "objectclass": "group"})
1848 # This should not work since "memberOf" is linked to "member"
1849 try:
1850 ldb.add({
1851 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1852 "objectclass": "user",
1853 "memberOf": "cn=ldaptestgroup,cn=users," + self.base_dn})
1854 except LdbError as e:
1855 (num, _) = e.args
1856 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1858 ldb.add({
1859 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
1860 "objectclass": "user"})
1862 m = Message()
1863 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1864 m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
1865 FLAG_MOD_ADD, "memberOf")
1866 try:
1867 ldb.modify(m)
1868 self.fail()
1869 except LdbError as e:
1870 (num, _) = e.args
1871 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1873 m = Message()
1874 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1875 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1876 FLAG_MOD_ADD, "member")
1877 ldb.modify(m)
1879 m = Message()
1880 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1881 m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
1882 FLAG_MOD_REPLACE, "memberOf")
1883 try:
1884 ldb.modify(m)
1885 self.fail()
1886 except LdbError as e:
1887 (num, _) = e.args
1888 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1890 m = Message()
1891 m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1892 m["memberOf"] = MessageElement("cn=ldaptestgroup,cn=users," + self.base_dn,
1893 FLAG_MOD_DELETE, "memberOf")
1894 try:
1895 ldb.modify(m)
1896 self.fail()
1897 except LdbError as e:
1898 (num, _) = e.args
1899 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
1901 m = Message()
1902 m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1903 m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
1904 FLAG_MOD_DELETE, "member")
1905 ldb.modify(m)
1907 # This should yield no results since the member attribute for
1908 # "ldaptestuser" should have been deleted
1909 res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
1910 scope=SCOPE_BASE,
1911 expression="(member=cn=ldaptestuser,cn=users," + self.base_dn + ")",
1912 attrs=[])
1913 self.assertTrue(len(res1) == 0)
1915 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1917 ldb.add({
1918 "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
1919 "objectclass": "group",
1920 "member": "cn=ldaptestuser,cn=users," + self.base_dn})
1922 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
1924 # Make sure that the "member" attribute for "ldaptestuser" has been
1925 # removed
1926 res = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
1927 scope=SCOPE_BASE, attrs=["member"])
1928 self.assertTrue(len(res) == 1)
1929 self.assertFalse("member" in res[0])
1931 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
1933 def test_wkguid(self):
1934 """Test Well known GUID behaviours (including DN+Binary)"""
1936 res = self.ldb.search(base=("<WKGUID=ab1d30f3768811d1aded00c04fd8d5cd,%s>" % self.base_dn), scope=SCOPE_BASE, attrs=[])
1937 self.assertEqual(len(res), 1)
1939 res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd:%s" % res[0].dn))
1940 self.assertEqual(len(res2), 1)
1942 # Prove that the matching rule is over the whole DN+Binary
1943 res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=B:32:ab1d30f3768811d1aded00c04fd8d5cd"))
1944 self.assertEqual(len(res2), 0)
1945 # Prove that the matching rule is over the whole DN+Binary
1946 res2 = self.ldb.search(scope=SCOPE_BASE, attrs=["wellKnownObjects"], expression=("wellKnownObjects=%s") % res[0].dn)
1947 self.assertEqual(len(res2), 0)
1949 def test_subschemasubentry(self):
1950 """Test subSchemaSubEntry appears when requested, but not when not requested"""
1952 res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["subSchemaSubEntry"])
1953 self.assertEqual(len(res), 1)
1954 self.assertEqual(str(res[0]["subSchemaSubEntry"][0]), "CN=Aggregate," + self.schema_dn)
1956 res = self.ldb.search(base=self.base_dn, scope=SCOPE_BASE, attrs=["*"])
1957 self.assertEqual(len(res), 1)
1958 self.assertTrue("subScheamSubEntry" not in res[0])
1960 def test_all(self):
1961 """Basic tests"""
1963 # Testing user add
1965 ldb.add({
1966 "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
1967 "objectclass": "user",
1968 "cN": "LDAPtestUSER",
1969 "givenname": "ldap",
1970 "sn": "testy"})
1972 ldb.add({
1973 "dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
1974 "objectclass": "group",
1975 "member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
1977 ldb.add({
1978 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
1979 "objectclass": "computer",
1980 "cN": "LDAPtestCOMPUTER"})
1982 ldb.add({"dn": "cn=ldaptest2computer,cn=computers," + self.base_dn,
1983 "objectClass": "computer",
1984 "cn": "LDAPtest2COMPUTER",
1985 "userAccountControl": str(UF_WORKSTATION_TRUST_ACCOUNT),
1986 "displayname": "ldap testy"})
1988 try:
1989 ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
1990 "objectClass": "computer",
1991 "cn": "LDAPtest2COMPUTER"
1993 self.fail()
1994 except LdbError as e:
1995 (num, _) = e.args
1996 self.assertEqual(num, ERR_INVALID_DN_SYNTAX)
1998 try:
1999 ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
2000 "objectClass": "computer",
2001 "cn": "ldaptestcomputer3",
2002 "sAMAccountType": str(ATYPE_NORMAL_ACCOUNT)
2004 self.fail()
2005 except LdbError as e:
2006 (num, _) = e.args
2007 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
2009 ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
2010 "objectClass": "computer",
2011 "cn": "LDAPtestCOMPUTER3"
2014 # Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))
2015 res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))")
2016 self.assertEqual(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
2018 self.assertEqual(str(res[0].dn), ("CN=ldaptestcomputer3,CN=Computers," + self.base_dn))
2019 self.assertEqual(str(res[0]["cn"][0]), "ldaptestcomputer3")
2020 self.assertEqual(str(res[0]["name"][0]), "ldaptestcomputer3")
2021 self.assertEqual(str(res[0]["objectClass"][0]), "top")
2022 self.assertEqual(str(res[0]["objectClass"][1]), "person")
2023 self.assertEqual(str(res[0]["objectClass"][2]), "organizationalPerson")
2024 self.assertEqual(str(res[0]["objectClass"][3]), "user")
2025 self.assertEqual(str(res[0]["objectClass"][4]), "computer")
2026 self.assertTrue("objectGUID" in res[0])
2027 self.assertTrue("whenCreated" in res[0])
2028 self.assertEqual(str(res[0]["objectCategory"][0]), ("CN=Computer,%s" % ldb.get_schema_basedn()))
2029 self.assertEqual(int(res[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS)
2030 self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
2031 self.assertEqual(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2033 delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
2035 # Testing attribute or value exists behaviour
2036 try:
2037 ldb.modify_ldif("""
2038 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
2039 changetype: modify
2040 replace: servicePrincipalName
2041 servicePrincipalName: host/ldaptest2computer
2042 servicePrincipalName: host/ldaptest2computer
2043 servicePrincipalName: cifs/ldaptest2computer
2044 """)
2045 self.fail()
2046 except LdbError as e:
2047 (num, msg) = e.args
2048 self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
2050 ldb.modify_ldif("""
2051 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
2052 changetype: modify
2053 replace: servicePrincipalName
2054 servicePrincipalName: host/ldaptest2computer
2055 servicePrincipalName: cifs/ldaptest2computer
2056 """)
2057 try:
2058 ldb.modify_ldif("""
2059 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
2060 changetype: modify
2061 add: servicePrincipalName
2062 servicePrincipalName: host/ldaptest2computer
2063 """)
2064 self.fail()
2065 except LdbError as e:
2066 (num, msg) = e.args
2067 self.assertEqual(num, ERR_ATTRIBUTE_OR_VALUE_EXISTS)
2069 # Testing ranged results
2070 ldb.modify_ldif("""
2071 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
2072 changetype: modify
2073 replace: servicePrincipalName
2074 """)
2076 ldb.modify_ldif("""
2077 dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
2078 changetype: modify
2079 add: servicePrincipalName
2080 servicePrincipalName: host/ldaptest2computer0
2081 servicePrincipalName: host/ldaptest2computer1
2082 servicePrincipalName: host/ldaptest2computer2
2083 servicePrincipalName: host/ldaptest2computer3
2084 servicePrincipalName: host/ldaptest2computer4
2085 servicePrincipalName: host/ldaptest2computer5
2086 servicePrincipalName: host/ldaptest2computer6
2087 servicePrincipalName: host/ldaptest2computer7
2088 servicePrincipalName: host/ldaptest2computer8
2089 servicePrincipalName: host/ldaptest2computer9
2090 servicePrincipalName: host/ldaptest2computer10
2091 servicePrincipalName: host/ldaptest2computer11
2092 servicePrincipalName: host/ldaptest2computer12
2093 servicePrincipalName: host/ldaptest2computer13
2094 servicePrincipalName: host/ldaptest2computer14
2095 servicePrincipalName: host/ldaptest2computer15
2096 servicePrincipalName: host/ldaptest2computer16
2097 servicePrincipalName: host/ldaptest2computer17
2098 servicePrincipalName: host/ldaptest2computer18
2099 servicePrincipalName: host/ldaptest2computer19
2100 servicePrincipalName: host/ldaptest2computer20
2101 servicePrincipalName: host/ldaptest2computer21
2102 servicePrincipalName: host/ldaptest2computer22
2103 servicePrincipalName: host/ldaptest2computer23
2104 servicePrincipalName: host/ldaptest2computer24
2105 servicePrincipalName: host/ldaptest2computer25
2106 servicePrincipalName: host/ldaptest2computer26
2107 servicePrincipalName: host/ldaptest2computer27
2108 servicePrincipalName: host/ldaptest2computer28
2109 servicePrincipalName: host/ldaptest2computer29
2110 """)
2112 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
2113 attrs=["servicePrincipalName;range=0-*"])
2114 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2115 self.assertEqual(len(res[0]["servicePrincipalName;range=0-*"]), 30)
2117 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-19"])
2118 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2119 self.assertEqual(len(res[0]["servicePrincipalName;range=0-19"]), 20)
2121 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
2122 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2123 self.assertEqual(len(res[0]["servicePrincipalName;range=0-*"]), 30)
2125 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-40"])
2126 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2127 self.assertEqual(len(res[0]["servicePrincipalName;range=0-*"]), 30)
2129 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=30-40"])
2130 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2131 self.assertEqual(len(res[0]["servicePrincipalName;range=30-*"]), 0)
2133 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
2134 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2135 self.assertEqual(len(res[0]["servicePrincipalName;range=10-*"]), 20)
2136 # pos_11 = res[0]["servicePrincipalName;range=10-*"][18]
2138 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-40"])
2139 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2140 self.assertEqual(len(res[0]["servicePrincipalName;range=11-*"]), 19)
2141 # self.assertEqual((res[0]["servicePrincipalName;range=11-*"][18]), pos_11)
2143 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=11-15"])
2144 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2145 self.assertEqual(len(res[0]["servicePrincipalName;range=11-15"]), 5)
2146 # self.assertEqual(res[0]["servicePrincipalName;range=11-15"][4], pos_11)
2148 res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName"])
2149 self.assertEqual(len(res), 1, "Could not find (cn=ldaptest2computer)")
2150 self.assertEqual(len(res[0]["servicePrincipalName"]), 30)
2151 # self.assertEqual(res[0]["servicePrincipalName"][18], pos_11)
2153 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2154 ldb.add({
2155 "dn": "cn=ldaptestuser2,cn=useRs," + self.base_dn,
2156 "objectClass": "user",
2157 "cn": "LDAPtestUSER2",
2158 "givenname": "testy",
2159 "sn": "ldap user2"})
2161 # Testing Ambiguous Name Resolution
2162 # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
2163 res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
2164 self.assertEqual(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
2166 # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
2167 res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
2168 self.assertEqual(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
2170 # Testing ldb.search for (&(anr=ldap)(objectClass=user))
2171 res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
2172 self.assertEqual(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
2174 # Testing ldb.search for (&(anr==ldap)(objectClass=user))
2175 res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
2176 self.assertEqual(len(res), 1, "Could not find (&(anr==ldap)(objectClass=user)). Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
2178 self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
2179 self.assertEqual(str(res[0]["cn"][0]), "ldaptestuser")
2180 self.assertEqual(str(res[0]["name"]), "ldaptestuser")
2182 # Testing ldb.search for (&(anr=testy)(objectClass=user))
2183 res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
2184 self.assertEqual(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
2186 # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
2187 res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
2188 self.assertEqual(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
2190 # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
2191 # this test disabled for the moment, as anr with == tests are not understood
2192 # res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
2193 # self.assertEqual(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
2195 # self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
2196 # self.assertEqual(res[0]["cn"][0], "ldaptestuser")
2197 # self.assertEqual(res[0]["name"][0], "ldaptestuser")
2199 # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
2200 # res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
2201 # self.assertEqual(len(res), 1, "Could not find (&(anr==testy ldap)(objectClass=user))")
2203 # self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
2204 # self.assertEqual(res[0]["cn"][0], "ldaptestuser")
2205 # self.assertEqual(res[0]["name"][0], "ldaptestuser")
2207 # Testing ldb.search for (&(anr=testy ldap user)(objectClass=user))
2208 res = ldb.search(expression="(&(anr=testy ldap user)(objectClass=user))")
2209 self.assertEqual(len(res), 1, "Could not find (&(anr=testy ldap user)(objectClass=user))")
2211 self.assertEqual(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2212 self.assertEqual(str(res[0]["cn"]), "ldaptestuser2")
2213 self.assertEqual(str(res[0]["name"]), "ldaptestuser2")
2215 # Testing ldb.search for (&(anr==testy ldap user2)(objectClass=user))
2216 # res = ldb.search(expression="(&(anr==testy ldap user2)(objectClass=user))")
2217 # self.assertEqual(len(res), 1, "Could not find (&(anr==testy ldap user2)(objectClass=user))")
2219 self.assertEqual(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2220 self.assertEqual(str(res[0]["cn"]), "ldaptestuser2")
2221 self.assertEqual(str(res[0]["name"]), "ldaptestuser2")
2223 # Testing ldb.search for (&(anr==ldap user2)(objectClass=user))
2224 # res = ldb.search(expression="(&(anr==ldap user2)(objectClass=user))")
2225 # self.assertEqual(len(res), 1, "Could not find (&(anr==ldap user2)(objectClass=user))")
2227 self.assertEqual(str(res[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2228 self.assertEqual(str(res[0]["cn"]), "ldaptestuser2")
2229 self.assertEqual(str(res[0]["name"]), "ldaptestuser2")
2231 # Testing ldb.search for (&(anr==not ldap user2)(objectClass=user))
2232 # res = ldb.search(expression="(&(anr==not ldap user2)(objectClass=user))")
2233 # self.assertEqual(len(res), 0, "Must not find (&(anr==not ldap user2)(objectClass=user))")
2235 # Testing ldb.search for (&(anr=not ldap user2)(objectClass=user))
2236 res = ldb.search(expression="(&(anr=not ldap user2)(objectClass=user))")
2237 self.assertEqual(len(res), 0, "Must not find (&(anr=not ldap user2)(objectClass=user))")
2239 # Testing ldb.search for (&(anr="testy ldap")(objectClass=user)) (ie, with quotes)
2240 # res = ldb.search(expression="(&(anr==\"testy ldap\")(objectClass=user))")
2241 # self.assertEqual(len(res), 0, "Found (&(anr==\"testy ldap\")(objectClass=user))")
2243 # Testing Renames
2245 attrs = ["objectGUID", "objectSid"]
2246 # Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))
2247 res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
2248 self.assertEqual(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
2250 # Check rename works with extended/alternate DN forms
2251 ldb.rename("<SID=" + get_string(ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0])) + ">", "cn=ldaptestUSER3,cn=users," + self.base_dn)
2253 # Testing ldb.search for (&(cn=ldaptestuser3)(objectClass=user))
2254 res = ldb.search(expression="(&(cn=ldaptestuser3)(objectClass=user))")
2255 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser3)(objectClass=user))")
2257 self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2258 self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3")
2259 self.assertEqual(str(res[0]["name"]), "ldaptestUSER3")
2261 #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))"
2262 res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
2263 self.assertEqual(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=*))(objectClass=user))")
2265 self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2266 self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3")
2267 self.assertEqual(str(res[0]["name"]), "ldaptestUSER3")
2269 #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))"
2270 res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
2271 self.assertEqual(len(res), 1, "(&(&(cn=ldaptestuser3)(userAccountControl=546))(objectClass=user))")
2273 self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2274 self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3")
2275 self.assertEqual(str(res[0]["name"]), "ldaptestUSER3")
2277 #"Testing ldb.search for (&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))"
2278 res = ldb.search(expression="(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
2279 self.assertEqual(len(res), 0, "(&(&(cn=ldaptestuser3)(userAccountControl=547))(objectClass=user))")
2281 # Testing ldb.search for (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ") - should not work
2282 res = ldb.search(expression="(dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
2283 self.assertEqual(len(res), 0, "Could find (dn=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
2285 # Testing ldb.search for (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")
2286 res = ldb.search(expression="(distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
2287 self.assertEqual(len(res), 1, "Could not find (distinguishedName=CN=ldaptestUSER3,CN=Users," + self.base_dn + ")")
2288 self.assertEqual(str(res[0].dn), ("CN=ldaptestUSER3,CN=Users," + self.base_dn))
2289 self.assertEqual(str(res[0]["cn"]), "ldaptestUSER3")
2290 self.assertEqual(str(res[0]["name"]), "ldaptestUSER3")
2292 # ensure we cannot add it again
2293 try:
2294 ldb.add({"dn": "cn=ldaptestuser3,cn=userS," + self.base_dn,
2295 "objectClass": "user",
2296 "cn": "LDAPtestUSER3"})
2297 self.fail()
2298 except LdbError as e:
2299 (num, _) = e.args
2300 self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS)
2302 # rename back
2303 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser2,cn=users," + self.base_dn)
2305 # ensure we cannot rename it twice
2306 try:
2307 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
2308 "cn=ldaptestuser2,cn=users," + self.base_dn)
2309 self.fail()
2310 except LdbError as e:
2311 (num, _) = e.args
2312 self.assertEqual(num, ERR_NO_SUCH_OBJECT)
2314 # ensure can now use that name
2315 ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
2316 "objectClass": "user",
2317 "cn": "LDAPtestUSER3"})
2319 # ensure we now cannot rename
2320 try:
2321 ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
2322 self.fail()
2323 except LdbError as e:
2324 (num, _) = e.args
2325 self.assertEqual(num, ERR_ENTRY_ALREADY_EXISTS)
2326 try:
2327 ldb.rename("cn=ldaptestuser3,cn=users,%s" % self.base_dn, "cn=ldaptestuser3,%s" % ldb.get_config_basedn())
2328 self.fail()
2329 except LdbError as e:
2330 (num, _) = e.args
2331 self.assertTrue(num in (71, 64))
2333 ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser5,cn=users," + self.base_dn)
2335 ldb.delete("cn=ldaptestuser5,cn=users," + self.base_dn)
2337 delete_force(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
2339 ldb.rename("cn=ldaptestgroup,cn=users," + self.base_dn, "cn=ldaptestgroup2,cn=users," + self.base_dn)
2341 # Testing subtree renames
2343 ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
2344 "objectClass": "container"})
2346 ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
2347 "objectClass": "user",
2348 "cn": "LDAPtestUSER4"})
2350 # Here we don't enforce these hard "description" constraints
2351 ldb.modify_ldif("""
2352 dn: cn=ldaptestcontainer,""" + self.base_dn + """
2353 changetype: modify
2354 replace: description
2355 description: desc1
2356 description: desc2
2357 """)
2359 ldb.modify_ldif("""
2360 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2361 changetype: modify
2362 add: member
2363 member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
2364 member: cn=ldaptestcomputer,cn=computers,""" + self.base_dn + """
2365 member: cn=ldaptestuser2,cn=users,""" + self.base_dn + """
2366 """)
2368 # Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
2369 ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
2371 # Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user))
2372 res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))")
2373 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user))")
2375 # Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
2376 try:
2377 res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
2378 expression="(&(cn=ldaptestuser4)(objectClass=user))",
2379 scope=SCOPE_SUBTREE)
2380 self.fail(res)
2381 except LdbError as e:
2382 (num, _) = e.args
2383 self.assertEqual(num, ERR_NO_SUCH_OBJECT)
2385 # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
2386 try:
2387 res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
2388 expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
2389 self.fail()
2390 except LdbError as e:
2391 (num, _) = e.args
2392 self.assertEqual(num, ERR_NO_SUCH_OBJECT)
2394 # Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container"
2395 res = ldb.search("cn=ldaptestcontainer2," + self.base_dn, expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_SUBTREE)
2396 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser4)(objectClass=user)) under cn=ldaptestcontainer2," + self.base_dn)
2398 self.assertEqual(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
2399 self.assertEqual(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2401 time.sleep(4)
2403 # Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
2404 res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
2405 self.assertEqual(len(res), 1, "Could not find (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)), perhaps linked attributes are not consistent with subtree renames?")
2407 # Testing ldb.rename (into itself) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn
2408 try:
2409 ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer2," + self.base_dn)
2410 self.fail()
2411 except LdbError as e:
2412 (num, _) = e.args
2413 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
2415 # Testing ldb.rename (into non-existent container) of cn=ldaptestcontainer2," + self.base_dn + " to cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn
2416 try:
2417 ldb.rename("cn=ldaptestcontainer2," + self.base_dn, "cn=ldaptestcontainer,cn=ldaptestcontainer3," + self.base_dn)
2418 self.fail()
2419 except LdbError as e:
2420 (num, _) = e.args
2421 self.assertTrue(num in (ERR_UNWILLING_TO_PERFORM, ERR_OTHER))
2423 # Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + self.base_dn
2424 try:
2425 ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
2426 self.fail()
2427 except LdbError as e:
2428 (num, _) = e.args
2429 self.assertEqual(num, ERR_NOT_ALLOWED_ON_NON_LEAF)
2431 # Testing base ldb.search for CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn
2432 res = ldb.search(expression="(objectclass=*)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
2433 self.assertEqual(len(res), 1)
2434 res = ldb.search(expression="(cn=ldaptestuser40)", base=("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn), scope=SCOPE_BASE)
2435 self.assertEqual(len(res), 0)
2437 # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
2438 res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_ONELEVEL)
2439 self.assertEqual(len(res), 1)
2441 # Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in cn=ldaptestcontainer2," + self.base_dn
2442 res = ldb.search(expression="(&(cn=ldaptestuser4)(objectClass=user))", base=("cn=ldaptestcontainer2," + self.base_dn), scope=SCOPE_SUBTREE)
2443 self.assertEqual(len(res), 1)
2445 # Testing delete of subtree renamed "+("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn)
2446 ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
2447 # Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
2448 ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
2450 ldb.add({"dn": "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
2452 ldb.add({"dn": "cn=ldaptestutf8user2 èùéìòà,cn=users," + self.base_dn, "objectClass": "user"})
2454 # Testing ldb.search for (&(cn=ldaptestuser)(objectClass=user))"
2455 res = ldb.search(expression="(&(cn=ldaptestuser)(objectClass=user))")
2456 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
2458 self.assertEqual(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
2459 self.assertEqual(str(res[0]["cn"]), "ldaptestuser")
2460 self.assertEqual(str(res[0]["name"]), "ldaptestuser")
2461 self.assertEqual(set(res[0]["objectClass"]), set([b"top", b"person", b"organizationalPerson", b"user"]))
2462 self.assertTrue("objectGUID" in res[0])
2463 self.assertTrue("whenCreated" in res[0])
2464 self.assertEqual(str(res[0]["objectCategory"]), ("CN=Person,%s" % ldb.get_schema_basedn()))
2465 self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_NORMAL_ACCOUNT)
2466 self.assertEqual(int(res[0]["userAccountControl"][0]), UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2467 self.assertEqual(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2468 self.assertEqual(len(res[0]["memberOf"]), 1)
2470 # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn()
2471 res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn())
2472 self.assertEqual(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,%s))" % ldb.get_schema_basedn())
2474 self.assertEqual(res[0].dn, res2[0].dn)
2476 # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon))"
2477 res3 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
2478 self.assertEqual(len(res3), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)): matched %d" % len(res3))
2480 self.assertEqual(res[0].dn, res3[0].dn)
2482 if gc_ldb is not None:
2483 # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
2484 res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
2485 self.assertEqual(len(res3gc), 1)
2487 self.assertEqual(res[0].dn, res3gc[0].dn)
2489 # Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
2491 if gc_ldb is not None:
2492 res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
2493 self.assertEqual(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
2495 self.assertEqual(res[0].dn, res3control[0].dn)
2497 ldb.delete(res[0].dn)
2499 # Testing ldb.search for (&(cn=ldaptestcomputer)(objectClass=user))"
2500 res = ldb.search(expression="(&(cn=ldaptestcomputer)(objectClass=user))")
2501 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestuser)(objectClass=user))")
2503 self.assertEqual(str(res[0].dn), ("CN=ldaptestcomputer,CN=Computers," + self.base_dn))
2504 self.assertEqual(str(res[0]["cn"]), "ldaptestcomputer")
2505 self.assertEqual(str(res[0]["name"]), "ldaptestcomputer")
2506 self.assertEqual(set(res[0]["objectClass"]), set([b"top", b"person", b"organizationalPerson", b"user", b"computer"]))
2507 self.assertTrue("objectGUID" in res[0])
2508 self.assertTrue("whenCreated" in res[0])
2509 self.assertEqual(str(res[0]["objectCategory"]), ("CN=Computer,%s" % ldb.get_schema_basedn()))
2510 self.assertEqual(int(res[0]["primaryGroupID"][0]), DOMAIN_RID_DOMAIN_MEMBERS)
2511 self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
2512 self.assertEqual(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT | UF_PASSWD_NOTREQD | UF_ACCOUNTDISABLE)
2513 self.assertEqual(str(res[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2514 self.assertEqual(len(res[0]["memberOf"]), 1)
2516 # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn()
2517 res2 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn())
2518 self.assertEqual(len(res2), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % ldb.get_schema_basedn())
2520 self.assertEqual(res[0].dn, res2[0].dn)
2522 if gc_ldb is not None:
2523 # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) in Global Catalog" % gc_ldb.get_schema_basedn()
2524 res2gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s))" % gc_ldb.get_schema_basedn())
2525 self.assertEqual(len(res2gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=cn=computer,%s)) In Global Catalog" % gc_ldb.get_schema_basedn())
2527 self.assertEqual(res[0].dn, res2gc[0].dn)
2529 # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER))"
2530 res3 = ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
2531 self.assertEqual(len(res3), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER))")
2533 self.assertEqual(res[0].dn, res3[0].dn)
2535 if gc_ldb is not None:
2536 # Testing ldb.search for (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog"
2537 res3gc = gc_ldb.search(expression="(&(cn=ldaptestcomputer)(objectCategory=compuTER))")
2538 self.assertEqual(len(res3gc), 1, "Could not find (&(cn=ldaptestcomputer)(objectCategory=compuTER)) in Global Catalog")
2540 self.assertEqual(res[0].dn, res3gc[0].dn)
2542 # Testing ldb.search for (&(cn=ldaptestcomp*r)(objectCategory=compuTER))"
2543 res4 = ldb.search(expression="(&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
2544 self.assertEqual(len(res4), 1, "Could not find (&(cn=ldaptestcomp*r)(objectCategory=compuTER))")
2546 self.assertEqual(res[0].dn, res4[0].dn)
2548 # Testing ldb.search for (&(cn=ldaptestcomput*)(objectCategory=compuTER))"
2549 res5 = ldb.search(expression="(&(cn=ldaptestcomput*)(objectCategory=compuTER))")
2550 self.assertEqual(len(res5), 1, "Could not find (&(cn=ldaptestcomput*)(objectCategory=compuTER))")
2552 self.assertEqual(res[0].dn, res5[0].dn)
2554 # Testing ldb.search for (&(cn=*daptestcomputer)(objectCategory=compuTER))"
2555 res6 = ldb.search(expression="(&(cn=*daptestcomputer)(objectCategory=compuTER))")
2556 self.assertEqual(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
2558 self.assertEqual(res[0].dn, res6[0].dn)
2560 ldb.delete("<GUID=" + get_string(ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0])) + ">")
2562 # Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
2563 res = ldb.search(expression="(&(cn=ldaptest2computer)(objectClass=user))")
2564 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptest2computer)(objectClass=user))")
2566 self.assertEqual(str(res[0].dn), "CN=ldaptest2computer,CN=Computers," + self.base_dn)
2567 self.assertEqual(str(res[0]["cn"]), "ldaptest2computer")
2568 self.assertEqual(str(res[0]["name"]), "ldaptest2computer")
2569 self.assertEqual(list(res[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user", b"computer"])
2570 self.assertTrue("objectGUID" in res[0])
2571 self.assertTrue("whenCreated" in res[0])
2572 self.assertEqual(str(res[0]["objectCategory"][0]), "CN=Computer,%s" % ldb.get_schema_basedn())
2573 self.assertEqual(int(res[0]["sAMAccountType"][0]), ATYPE_WORKSTATION_TRUST)
2574 self.assertEqual(int(res[0]["userAccountControl"][0]), UF_WORKSTATION_TRUST_ACCOUNT)
2576 ldb.delete("<SID=" + get_string(ldb.schema_format_value("objectSID", res[0]["objectSID"][0])) + ">")
2578 attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"]
2579 # Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))"
2580 res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
2581 self.assertEqual(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
2583 self.assertEqual(str(res_user[0].dn), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2584 self.assertEqual(str(res_user[0]["cn"]), "ldaptestuser2")
2585 self.assertEqual(str(res_user[0]["name"]), "ldaptestuser2")
2586 self.assertEqual(list(res_user[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user"])
2587 self.assertTrue("objectSid" in res_user[0])
2588 self.assertTrue("objectGUID" in res_user[0])
2589 self.assertTrue("whenCreated" in res_user[0])
2590 self.assertTrue("nTSecurityDescriptor" in res_user[0])
2591 self.assertTrue("allowedAttributes" in res_user[0])
2592 self.assertTrue("allowedAttributesEffective" in res_user[0])
2593 self.assertEqual(str(res_user[0]["memberOf"][0]).upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
2595 ldaptestuser2_sid = res_user[0]["objectSid"][0]
2596 ldaptestuser2_guid = res_user[0]["objectGUID"][0]
2598 attrs = ["cn", "name", "objectClass", "objectGUID", "objectSID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"]
2599 # Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))"
2600 res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2601 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2603 self.assertEqual(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2604 self.assertEqual(str(res[0]["cn"]), "ldaptestgroup2")
2605 self.assertEqual(str(res[0]["name"]), "ldaptestgroup2")
2606 self.assertEqual(list(res[0]["objectClass"]), [b"top", b"group"])
2607 self.assertTrue("objectGUID" in res[0])
2608 self.assertTrue("objectSid" in res[0])
2609 self.assertTrue("whenCreated" in res[0])
2610 self.assertTrue("nTSecurityDescriptor" in res[0])
2611 self.assertTrue("allowedAttributes" in res[0])
2612 self.assertTrue("allowedAttributesEffective" in res[0])
2613 memberUP = []
2614 for m in res[0]["member"]:
2615 memberUP.append(str(m).upper())
2616 self.assertTrue(("CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
2618 res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs, controls=["extended_dn:1:1"])
2619 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2621 print(res[0]["member"])
2622 memberUP = []
2623 for m in res[0]["member"]:
2624 memberUP.append(str(m).upper())
2625 print(("<GUID=" + get_string(ldb.schema_format_value("objectGUID", ldaptestuser2_guid)) + ">;<SID=" + get_string(ldb.schema_format_value("objectSid", ldaptestuser2_sid)) + ">;CN=ldaptestuser2,CN=Users," + self.base_dn).upper())
2627 self.assertTrue(("<GUID=" + get_string(ldb.schema_format_value("objectGUID", ldaptestuser2_guid)) + ">;<SID=" + get_string(ldb.schema_format_value("objectSid", ldaptestuser2_sid)) + ">;CN=ldaptestuser2,CN=Users," + self.base_dn).upper() in memberUP)
2629 # Quicktest for linked attributes"
2630 ldb.modify_ldif("""
2631 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2632 changetype: modify
2633 replace: member
2634 member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
2635 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2636 """)
2638 ldb.modify_ldif("""
2639 dn: <GUID=""" + get_string(ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0])) + """>
2640 changetype: modify
2641 replace: member
2642 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2643 """)
2645 ldb.modify_ldif("""
2646 dn: <SID=""" + get_string(ldb.schema_format_value("objectSid", res[0]["objectSid"][0])) + """>
2647 changetype: modify
2648 delete: member
2649 """)
2651 ldb.modify_ldif("""
2652 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2653 changetype: modify
2654 add: member
2655 member: <GUID=""" + get_string(ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0])) + """>
2656 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2657 """)
2659 ldb.modify_ldif("""
2660 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2661 changetype: modify
2662 replace: member
2663 """)
2665 ldb.modify_ldif("""
2666 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2667 changetype: modify
2668 add: member
2669 member: <SID=""" + get_string(ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0])) + """>
2670 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2671 """)
2673 ldb.modify_ldif("""
2674 dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
2675 changetype: modify
2676 delete: member
2677 member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
2678 """)
2680 res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2681 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))")
2683 self.assertEqual(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2684 self.assertEqual(str(res[0]["member"][0]), ("CN=ldaptestuser2,CN=Users," + self.base_dn))
2685 self.assertEqual(len(res[0]["member"]), 1)
2687 ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
2689 time.sleep(4)
2691 attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
2692 # Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
2693 res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs)
2694 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete")
2696 self.assertEqual(str(res[0].dn), ("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2697 self.assertTrue("member" not in res[0])
2699 # Testing ldb.search for (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))"
2700 res = ldb.search(expression="(&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2701 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2702 res = ldb.search(expression="(&(cn=ldaptestutf8user èùéìòà)(objectclass=user))")
2703 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user ÈÙÉÌÒÀ)(objectClass=user))")
2705 self.assertEqual(str(res[0].dn), ("CN=ldaptestutf8user èùéìòà,CN=Users," + self.base_dn))
2706 self.assertEqual(str(res[0]["cn"]), "ldaptestutf8user èùéìòà")
2707 self.assertEqual(str(res[0]["name"]), "ldaptestutf8user èùéìòà")
2708 self.assertEqual(list(res[0]["objectClass"]), [b"top", b"person", b"organizationalPerson", b"user"])
2709 self.assertTrue("objectGUID" in res[0])
2710 self.assertTrue("whenCreated" in res[0])
2712 # delete "ldaptestutf8user"
2713 ldb.delete(res[0].dn)
2715 # Testing ldb.search for (&(cn=ldaptestutf8user2*)(objectClass=user))"
2716 res = ldb.search(expression="(&(cn=ldaptestutf8user2*)(objectClass=user))")
2717 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user2*)(objectClass=user))")
2719 # Testing ldb.search for (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))"
2720 res = ldb.search(expression="(&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))")
2721 self.assertEqual(len(res), 1, "Could not find (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))")
2723 # delete "ldaptestutf8user2 "
2724 ldb.delete(res[0].dn)
2726 ldb.delete(("CN=ldaptestgroup2,CN=Users," + self.base_dn))
2728 # Testing that we can't get at the configuration DN from the main search base"
2729 res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2730 self.assertEqual(len(res), 0)
2732 # 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"
2733 res = ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
2734 self.assertTrue(len(res) > 0)
2736 if gc_ldb is not None:
2737 # Testing that we can get at the configuration DN from the main search base on the GC port with the search_options control == 0"
2739 res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
2740 self.assertTrue(len(res) > 0)
2742 # Testing that we do find configuration elements in the global catlog"
2743 res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2744 self.assertTrue(len(res) > 0)
2746 # Testing that we do find configuration elements and user elements at the same time"
2747 res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
2748 self.assertTrue(len(res) > 0)
2750 # Testing that we do find configuration elements in the global catlog, with the configuration basedn"
2751 res = gc_ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2752 self.assertTrue(len(res) > 0)
2754 # Testing that we can get at the configuration DN on the main LDAP port"
2755 res = ldb.search(self.configuration_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
2756 self.assertTrue(len(res) > 0)
2758 # Testing objectCategory canonicalisation"
2759 res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
2760 self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
2761 self.assertTrue(len(res) != 0)
2763 res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
2764 self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
2765 self.assertTrue(len(res) != 0)
2767 # Testing objectClass attribute order on "+ self.base_dn
2768 res = ldb.search(expression="objectClass=domain", base=self.base_dn,
2769 scope=SCOPE_BASE, attrs=["objectClass"])
2770 self.assertEqual(len(res), 1)
2772 self.assertEqual(list(res[0]["objectClass"]), [b"top", b"domain", b"domainDNS"])
2774 # check enumeration
2776 # Testing ldb.search for objectCategory=person"
2777 res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"])
2778 self.assertTrue(len(res) > 0)
2780 # Testing ldb.search for objectCategory=person with domain scope control"
2781 res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2782 self.assertTrue(len(res) > 0)
2784 # Testing ldb.search for objectCategory=user"
2785 res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
2786 self.assertTrue(len(res) > 0)
2788 # Testing ldb.search for objectCategory=user with domain scope control"
2789 res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2790 self.assertTrue(len(res) > 0)
2792 # Testing ldb.search for objectCategory=group"
2793 res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
2794 self.assertTrue(len(res) > 0)
2796 # Testing ldb.search for objectCategory=group with domain scope control"
2797 res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
2798 self.assertTrue(len(res) > 0)
2800 # Testing creating a user with the posixAccount objectClass"
2801 self.ldb.add_ldif("""dn: cn=posixuser,CN=Users,%s
2802 objectClass: top
2803 objectClass: person
2804 objectClass: posixAccount
2805 objectClass: user
2806 objectClass: organizationalPerson
2807 cn: posixuser
2808 uid: posixuser
2809 sn: posixuser
2810 uidNumber: 10126
2811 gidNumber: 10126
2812 homeDirectory: /home/posixuser
2813 loginShell: /bin/bash
2814 gecos: Posix User;;;
2815 description: A POSIX user""" % (self.base_dn))
2817 # Testing removing the posixAccount objectClass from an existing user"
2818 self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
2819 changetype: modify
2820 delete: objectClass
2821 objectClass: posixAccount""" % (self.base_dn))
2823 # Testing adding the posixAccount objectClass to an existing user"
2824 self.ldb.modify_ldif("""dn: cn=posixuser,CN=Users,%s
2825 changetype: modify
2826 add: objectClass
2827 objectClass: posixAccount""" % (self.base_dn))
2829 delete_force(self.ldb, "cn=posixuser,cn=users," + self.base_dn)
2830 delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
2831 delete_force(self.ldb, "cn=ldaptestuser2,cn=users," + self.base_dn)
2832 delete_force(self.ldb, "cn=ldaptestuser3,cn=users," + self.base_dn)
2833 delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
2834 delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer2," + self.base_dn)
2835 delete_force(self.ldb, "cn=ldaptestuser5,cn=users," + self.base_dn)
2836 delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
2837 delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
2838 delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
2839 delete_force(self.ldb, "cn=ldaptest2computer,cn=computers," + self.base_dn)
2840 delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
2841 delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà,cn=users," + self.base_dn)
2842 delete_force(self.ldb, "cn=ldaptestutf8user2 èùéìòà,cn=users," + self.base_dn)
2843 delete_force(self.ldb, "cn=ldaptestcontainer," + self.base_dn)
2844 delete_force(self.ldb, "cn=ldaptestcontainer2," + self.base_dn)
2846 def test_security_descriptor_add(self):
2847 """ Testing ldb.add_ldif() for nTSecurityDescriptor """
2848 user_name = "testdescriptoruser1"
2849 user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2851 # Test an empty security descriptor (naturally this shouldn't work)
2853 delete_force(self.ldb, user_dn)
2854 try:
2855 self.ldb.add({"dn": user_dn,
2856 "objectClass": "user",
2857 "sAMAccountName": user_name,
2858 "nTSecurityDescriptor": []})
2859 self.fail()
2860 except LdbError as e:
2861 (num, _) = e.args
2862 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
2863 finally:
2864 delete_force(self.ldb, user_dn)
2866 # Test add_ldif() with SDDL security descriptor input
2868 try:
2869 sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2870 self.ldb.add_ldif("""
2871 dn: """ + user_dn + """
2872 objectclass: user
2873 sAMAccountName: """ + user_name + """
2874 nTSecurityDescriptor: """ + sddl)
2875 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2876 desc = res[0]["nTSecurityDescriptor"][0]
2877 desc = ndr_unpack(security.descriptor, desc)
2878 desc_sddl = desc.as_sddl(self.domain_sid)
2879 self.assertEqual(desc_sddl, sddl)
2880 finally:
2881 delete_force(self.ldb, user_dn)
2883 # Test add_ldif() with BASE64 security descriptor
2885 try:
2886 sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
2887 desc = security.descriptor.from_sddl(sddl, self.domain_sid)
2888 desc_binary = ndr_pack(desc)
2889 desc_base64 = base64.b64encode(desc_binary).decode('utf8')
2890 self.ldb.add_ldif("""
2891 dn: """ + user_dn + """
2892 objectclass: user
2893 sAMAccountName: """ + user_name + """
2894 nTSecurityDescriptor:: """ + desc_base64)
2895 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2896 desc = res[0]["nTSecurityDescriptor"][0]
2897 desc = ndr_unpack(security.descriptor, desc)
2898 desc_sddl = desc.as_sddl(self.domain_sid)
2899 self.assertEqual(desc_sddl, sddl)
2900 finally:
2901 delete_force(self.ldb, user_dn)
2903 def test_security_descriptor_add_neg(self):
2904 """Test add_ldif() with BASE64 security descriptor input using WRONG domain SID
2905 Negative test
2907 user_name = "testdescriptoruser1"
2908 user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2909 delete_force(self.ldb, user_dn)
2910 try:
2911 sddl = "O:DUG:DUD:AI(A;;RPWP;;;AU)S:PAI"
2912 desc = security.descriptor.from_sddl(sddl, security.dom_sid('S-1-5-21'))
2913 desc_base64 = base64.b64encode(ndr_pack(desc)).decode('utf8')
2914 self.ldb.add_ldif("""
2915 dn: """ + user_dn + """
2916 objectclass: user
2917 sAMAccountName: """ + user_name + """
2918 nTSecurityDescriptor:: """ + desc_base64)
2919 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2920 self.assertTrue("nTSecurityDescriptor" in res[0])
2921 desc = res[0]["nTSecurityDescriptor"][0]
2922 desc = ndr_unpack(security.descriptor, desc)
2923 desc_sddl = desc.as_sddl(self.domain_sid)
2924 self.assertTrue("O:S-1-5-21-513G:S-1-5-21-513D:AI(A;;RPWP;;;AU)" in desc_sddl)
2925 finally:
2926 delete_force(self.ldb, user_dn)
2928 def test_security_descriptor_modify(self):
2929 """ Testing ldb.modify_ldif() for nTSecurityDescriptor """
2930 user_name = "testdescriptoruser2"
2931 user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
2933 # Test an empty security descriptor (naturally this shouldn't work)
2935 delete_force(self.ldb, user_dn)
2936 self.ldb.add({"dn": user_dn,
2937 "objectClass": "user",
2938 "sAMAccountName": user_name})
2940 m = Message()
2941 m.dn = Dn(ldb, user_dn)
2942 m["nTSecurityDescriptor"] = MessageElement([], FLAG_MOD_ADD,
2943 "nTSecurityDescriptor")
2944 try:
2945 self.ldb.modify(m)
2946 self.fail()
2947 except LdbError as e:
2948 (num, _) = e.args
2949 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
2951 m = Message()
2952 m.dn = Dn(ldb, user_dn)
2953 m["nTSecurityDescriptor"] = MessageElement([], FLAG_MOD_REPLACE,
2954 "nTSecurityDescriptor")
2955 try:
2956 self.ldb.modify(m)
2957 self.fail()
2958 except LdbError as e:
2959 (num, _) = e.args
2960 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
2962 m = Message()
2963 m.dn = Dn(ldb, user_dn)
2964 m["nTSecurityDescriptor"] = MessageElement([], FLAG_MOD_DELETE,
2965 "nTSecurityDescriptor")
2966 try:
2967 self.ldb.modify(m)
2968 self.fail()
2969 except LdbError as e:
2970 (num, _) = e.args
2971 self.assertEqual(num, ERR_UNWILLING_TO_PERFORM)
2973 delete_force(self.ldb, user_dn)
2975 # Test modify_ldif() with SDDL security descriptor input
2976 # Add ACE to the original descriptor test
2978 try:
2979 self.ldb.add_ldif("""
2980 dn: """ + user_dn + """
2981 objectclass: user
2982 sAMAccountName: """ + user_name)
2983 # Modify descriptor
2984 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2985 desc = res[0]["nTSecurityDescriptor"][0]
2986 desc = ndr_unpack(security.descriptor, desc)
2987 desc_sddl = desc.as_sddl(self.domain_sid)
2988 sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
2989 mod = """
2990 dn: """ + user_dn + """
2991 changetype: modify
2992 replace: nTSecurityDescriptor
2993 nTSecurityDescriptor: """ + sddl
2994 self.ldb.modify_ldif(mod)
2995 # Read modified descriptor
2996 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
2997 desc = res[0]["nTSecurityDescriptor"][0]
2998 desc = ndr_unpack(security.descriptor, desc)
2999 desc_sddl = desc.as_sddl(self.domain_sid)
3000 self.assertEqual(desc_sddl, sddl)
3001 finally:
3002 delete_force(self.ldb, user_dn)
3004 # Test modify_ldif() with SDDL security descriptor input
3005 # New descriptor test
3007 try:
3008 self.ldb.add_ldif("""
3009 dn: """ + user_dn + """
3010 objectclass: user
3011 sAMAccountName: """ + user_name)
3012 # Modify descriptor
3013 sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
3014 mod = """
3015 dn: """ + user_dn + """
3016 changetype: modify
3017 replace: nTSecurityDescriptor
3018 nTSecurityDescriptor: """ + sddl
3019 self.ldb.modify_ldif(mod)
3020 # Read modified descriptor
3021 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
3022 desc = res[0]["nTSecurityDescriptor"][0]
3023 desc = ndr_unpack(security.descriptor, desc)
3024 desc_sddl = desc.as_sddl(self.domain_sid)
3025 self.assertEqual(desc_sddl, sddl)
3026 finally:
3027 delete_force(self.ldb, user_dn)
3029 # Test modify_ldif() with BASE64 security descriptor input
3030 # Add ACE to the original descriptor test
3032 try:
3033 self.ldb.add_ldif("""
3034 dn: """ + user_dn + """
3035 objectclass: user
3036 sAMAccountName: """ + user_name)
3037 # Modify descriptor
3038 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
3039 desc = res[0]["nTSecurityDescriptor"][0]
3040 desc = ndr_unpack(security.descriptor, desc)
3041 desc_sddl = desc.as_sddl(self.domain_sid)
3042 sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
3043 desc = security.descriptor.from_sddl(sddl, self.domain_sid)
3044 desc_base64 = base64.b64encode(ndr_pack(desc)).decode('utf8')
3045 mod = """
3046 dn: """ + user_dn + """
3047 changetype: modify
3048 replace: nTSecurityDescriptor
3049 nTSecurityDescriptor:: """ + desc_base64
3050 self.ldb.modify_ldif(mod)
3051 # Read modified descriptor
3052 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
3053 desc = res[0]["nTSecurityDescriptor"][0]
3054 desc = ndr_unpack(security.descriptor, desc)
3055 desc_sddl = desc.as_sddl(self.domain_sid)
3056 self.assertEqual(desc_sddl, sddl)
3057 finally:
3058 delete_force(self.ldb, user_dn)
3060 # Test modify_ldif() with BASE64 security descriptor input
3061 # New descriptor test
3063 try:
3064 delete_force(self.ldb, user_dn)
3065 self.ldb.add_ldif("""
3066 dn: """ + user_dn + """
3067 objectclass: user
3068 sAMAccountName: """ + user_name)
3069 # Modify descriptor
3070 sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
3071 desc = security.descriptor.from_sddl(sddl, self.domain_sid)
3072 desc_base64 = base64.b64encode(ndr_pack(desc)).decode('utf8')
3073 mod = """
3074 dn: """ + user_dn + """
3075 changetype: modify
3076 replace: nTSecurityDescriptor
3077 nTSecurityDescriptor:: """ + desc_base64
3078 self.ldb.modify_ldif(mod)
3079 # Read modified descriptor
3080 res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
3081 desc = res[0]["nTSecurityDescriptor"][0]
3082 desc = ndr_unpack(security.descriptor, desc)
3083 desc_sddl = desc.as_sddl(self.domain_sid)
3084 self.assertEqual(desc_sddl, sddl)
3085 finally:
3086 delete_force(self.ldb, user_dn)
3088 def test_dsheuristics(self):
3089 """Tests the 'dSHeuristics' attribute"""
3090 # Tests the 'dSHeuristics' attribute"
3092 # Get the current value to restore it later
3093 dsheuristics = self.ldb.get_dsheuristics()
3094 # Perform the length checks: for each decade (except the 0th) we need
3095 # the first index to be the number. This goes till the 9th one, beyond
3096 # there does not seem to be another limitation.
3097 try:
3098 dshstr = ""
3099 for i in range(1, 11):
3100 # This is in the range
3101 self.ldb.set_dsheuristics(dshstr + "x")
3102 self.ldb.set_dsheuristics(dshstr + "xxxxx")
3103 dshstr = dshstr + "xxxxxxxxx"
3104 if i < 10:
3105 # Not anymore in the range, new decade specifier needed
3106 try:
3107 self.ldb.set_dsheuristics(dshstr + "x")
3108 self.fail()
3109 except LdbError as e:
3110 (num, _) = e.args
3111 self.assertEqual(num, ERR_CONSTRAINT_VIOLATION)
3112 dshstr = dshstr + str(i)
3113 else:
3114 # There does not seem to be an upper limit
3115 self.ldb.set_dsheuristics(dshstr + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
3116 # apart from the above, all char values are accepted
3117 self.ldb.set_dsheuristics("123ABC-+!1asdfg@#^")
3118 self.assertEqual(self.ldb.get_dsheuristics(), b"123ABC-+!1asdfg@#^")
3119 finally:
3120 # restore old value
3121 self.ldb.set_dsheuristics(dsheuristics)
3123 def test_ldapControlReturn(self):
3124 """Testing that if we request a control that return a control it
3125 really return something"""
3126 res = self.ldb.search(attrs=["cn"],
3127 controls=["paged_results:1:10"])
3128 self.assertEqual(len(res.controls), 1)
3129 self.assertEqual(res.controls[0].oid, "1.2.840.113556.1.4.319")
3130 s = str(res.controls[0])
3132 def test_operational(self):
3133 """Tests operational attributes"""
3134 # Tests operational attributes"
3136 res = self.ldb.search(self.base_dn, scope=SCOPE_BASE,
3137 attrs=["createTimeStamp", "modifyTimeStamp",
3138 "structuralObjectClass", "whenCreated",
3139 "whenChanged"])
3140 self.assertEqual(len(res), 1)
3141 self.assertTrue("createTimeStamp" in res[0])
3142 self.assertTrue("modifyTimeStamp" in res[0])
3143 self.assertTrue("structuralObjectClass" in res[0])
3144 self.assertTrue("whenCreated" in res[0])
3145 self.assertTrue("whenChanged" in res[0])
3147 def test_timevalues1(self):
3148 """Tests possible syntax of time attributes"""
3150 user_name = "testtimevaluesuser1"
3151 user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
3153 delete_force(self.ldb, user_dn)
3154 self.ldb.add({"dn": user_dn,
3155 "objectClass": "user",
3156 "sAMAccountName": user_name})
3159 # We check the following values:
3161 # 370101000000Z => 20370101000000.0Z
3162 # 20370102000000.*Z => 20370102000000.0Z
3164 ext = ["Z", ".0Z", ".Z", ".000Z", ".RandomIgnoredCharacters...987654321Z"]
3165 for i in range(0, len(ext)):
3166 v_raw = "203701%02d000000" % (i + 1)
3167 if ext[i] == "Z":
3168 v_set = v_raw[2:] + ext[i]
3169 else:
3170 v_set = v_raw + ext[i]
3171 v_get = v_raw + ".0Z"
3173 m = Message()
3174 m.dn = Dn(ldb, user_dn)
3175 m["msTSExpireDate"] = MessageElement([v_set],
3176 FLAG_MOD_REPLACE,
3177 "msTSExpireDate")
3178 self.ldb.modify(m)
3180 res = self.ldb.search(base=user_dn, scope=SCOPE_BASE, attrs=["msTSExpireDate"])
3181 self.assertTrue(len(res) == 1)
3182 self.assertTrue("msTSExpireDate" in res[0])
3183 self.assertTrue(len(res[0]["msTSExpireDate"]) == 1)
3184 self.assertEqual(str(res[0]["msTSExpireDate"][0]), v_get)
3186 def test_ldapSearchNoAttributes(self):
3187 """Testing ldap search with no attributes"""
3189 user_name = "testemptyattributesuser"
3190 user_dn = "CN=%s,%s" % (user_name, self.base_dn)
3191 delete_force(self.ldb, user_dn)
3193 self.ldb.add({"dn": user_dn,
3194 "objectClass": "user",
3195 "sAMAccountName": user_name})
3197 res = self.ldb.search(user_dn, scope=SCOPE_BASE, attrs=[])
3198 delete_force(self.ldb, user_dn)
3200 self.assertEqual(len(res), 1)
3201 self.assertEqual(len(res[0]), 0)
3204 class BaseDnTests(samba.tests.TestCase):
3206 def setUp(self):
3207 super(BaseDnTests, self).setUp()
3208 self.ldb = ldb
3210 def test_rootdse_attrs(self):
3211 """Testing for all rootDSE attributes"""
3212 res = self.ldb.search("", scope=SCOPE_BASE, attrs=[])
3213 self.assertEqual(len(res), 1)
3215 def test_highestcommittedusn(self):
3216 """Testing for highestCommittedUSN"""
3217 res = self.ldb.search("", scope=SCOPE_BASE, attrs=["highestCommittedUSN"])
3218 self.assertEqual(len(res), 1)
3219 self.assertTrue(int(res[0]["highestCommittedUSN"][0]) != 0)
3221 def test_netlogon(self):
3222 """Testing for netlogon via LDAP"""
3223 res = self.ldb.search("", scope=SCOPE_BASE, attrs=["netlogon"])
3224 self.assertEqual(len(res), 0)
3226 def test_netlogon_highestcommitted_usn(self):
3227 """Testing for netlogon and highestCommittedUSN via LDAP"""
3228 res = self.ldb.search("", scope=SCOPE_BASE,
3229 attrs=["netlogon", "highestCommittedUSN"])
3230 self.assertEqual(len(res), 0)
3232 def test_namingContexts(self):
3233 """Testing for namingContexts in rootDSE"""
3234 res = self.ldb.search("", scope=SCOPE_BASE,
3235 attrs=["namingContexts", "defaultNamingContext", "schemaNamingContext", "configurationNamingContext"])
3236 self.assertEqual(len(res), 1)
3238 ncs = set([])
3239 for nc in res[0]["namingContexts"]:
3240 self.assertTrue(nc not in ncs)
3241 ncs.add(nc)
3243 self.assertTrue(res[0]["defaultNamingContext"][0] in ncs)
3244 self.assertTrue(res[0]["configurationNamingContext"][0] in ncs)
3245 self.assertTrue(res[0]["schemaNamingContext"][0] in ncs)
3247 def test_serverPath(self):
3248 """Testing the server paths in rootDSE"""
3249 res = self.ldb.search("", scope=SCOPE_BASE,
3250 attrs=["dsServiceName", "serverName"])
3251 self.assertEqual(len(res), 1)
3253 self.assertTrue("CN=Servers" in str(res[0]["dsServiceName"][0]))
3254 self.assertTrue("CN=Sites" in str(res[0]["dsServiceName"][0]))
3255 self.assertTrue("CN=NTDS Settings" in str(res[0]["dsServiceName"][0]))
3256 self.assertTrue("CN=Servers" in str(res[0]["serverName"][0]))
3257 self.assertTrue("CN=Sites" in str(res[0]["serverName"][0]))
3258 self.assertFalse("CN=NTDS Settings" in str(res[0]["serverName"][0]))
3260 def test_functionality(self):
3261 """Testing the server paths in rootDSE"""
3262 res = self.ldb.search("", scope=SCOPE_BASE,
3263 attrs=["forestFunctionality", "domainFunctionality", "domainControllerFunctionality"])
3264 self.assertEqual(len(res), 1)
3265 self.assertEqual(len(res[0]["forestFunctionality"]), 1)
3266 self.assertEqual(len(res[0]["domainFunctionality"]), 1)
3267 self.assertEqual(len(res[0]["domainControllerFunctionality"]), 1)
3269 self.assertTrue(int(res[0]["forestFunctionality"][0]) <= int(res[0]["domainFunctionality"][0]))
3270 self.assertTrue(int(res[0]["domainControllerFunctionality"][0]) >= int(res[0]["domainFunctionality"][0]))
3272 res2 = self.ldb.search("", scope=SCOPE_BASE,
3273 attrs=["dsServiceName", "serverName"])
3274 self.assertEqual(len(res2), 1)
3275 self.assertEqual(len(res2[0]["dsServiceName"]), 1)
3277 res3 = self.ldb.search(res2[0]["dsServiceName"][0], scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"])
3278 self.assertEqual(len(res3), 1)
3279 self.assertEqual(len(res3[0]["msDS-Behavior-Version"]), 1)
3280 self.assertEqual(int(res[0]["domainControllerFunctionality"][0]), int(res3[0]["msDS-Behavior-Version"][0]))
3282 res4 = self.ldb.search(ldb.domain_dn(), scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"])
3283 self.assertEqual(len(res4), 1)
3284 self.assertEqual(len(res4[0]["msDS-Behavior-Version"]), 1)
3285 self.assertEqual(int(res[0]["domainFunctionality"][0]), int(res4[0]["msDS-Behavior-Version"][0]))
3287 res5 = self.ldb.search("cn=partitions,%s" % ldb.get_config_basedn(), scope=SCOPE_BASE, attrs=["msDS-Behavior-Version"])
3288 self.assertEqual(len(res5), 1)
3289 self.assertEqual(len(res5[0]["msDS-Behavior-Version"]), 1)
3290 self.assertEqual(int(res[0]["forestFunctionality"][0]), int(res5[0]["msDS-Behavior-Version"][0]))
3292 def test_dnsHostname(self):
3293 """Testing the DNS hostname in rootDSE"""
3294 res = self.ldb.search("", scope=SCOPE_BASE,
3295 attrs=["dnsHostName", "serverName"])
3296 self.assertEqual(len(res), 1)
3298 res2 = self.ldb.search(res[0]["serverName"][0], scope=SCOPE_BASE,
3299 attrs=["dNSHostName"])
3300 self.assertEqual(len(res2), 1)
3302 self.assertEqual(res[0]["dnsHostName"][0], res2[0]["dNSHostName"][0])
3304 def test_ldapServiceName(self):
3305 """Testing the ldap service name in rootDSE"""
3306 res = self.ldb.search("", scope=SCOPE_BASE,
3307 attrs=["ldapServiceName", "dnsHostName"])
3308 self.assertEqual(len(res), 1)
3309 self.assertTrue("ldapServiceName" in res[0])
3310 self.assertTrue("dnsHostName" in res[0])
3312 (hostname, _, dns_domainname) = str(res[0]["dnsHostName"][0]).partition(".")
3314 given = str(res[0]["ldapServiceName"][0])
3315 expected = "%s:%s$@%s" % (dns_domainname.lower(), hostname.lower(), dns_domainname.upper())
3316 self.assertEqual(given, expected)
3319 if "://" not in host:
3320 if os.path.isfile(host):
3321 host = "tdb://%s" % host
3322 else:
3323 host = "ldap://%s" % host
3325 ldb = SamDB(host, credentials=creds, session_info=system_session(lp), lp=lp)
3326 if "tdb://" not in host:
3327 gc_ldb = Ldb("%s:3268" % host, credentials=creds,
3328 session_info=system_session(lp), lp=lp)
3329 else:
3330 gc_ldb = None
3332 TestProgram(module=__name__, opts=subunitopts)