2 # -*- coding: utf-8 -*-
3 # Tests for LDAP syntaxes
11 sys
.path
.insert(0, "bin/python")
13 samba
.ensure_external_module("testtools", "testtools")
14 samba
.ensure_external_module("subunit", "subunit/python")
16 import samba
.getopt
as options
18 from samba
.auth
import system_session
19 from ldb
import SCOPE_BASE
, SCOPE_SUBTREE
, LdbError
20 from ldb
import ERR_CONSTRAINT_VIOLATION
21 from ldb
import ERR_INVALID_ATTRIBUTE_SYNTAX
22 from ldb
import ERR_ENTRY_ALREADY_EXISTS
24 from subunit
.run
import SubunitTestRunner
29 parser
= optparse
.OptionParser("ldap [options] <host>")
30 sambaopts
= options
.SambaOptions(parser
)
31 parser
.add_option_group(sambaopts
)
32 parser
.add_option_group(options
.VersionOptions(parser
))
33 # use command line creds if available
34 credopts
= options
.CredentialsOptions(parser
)
35 parser
.add_option_group(credopts
)
36 opts
, args
= parser
.parse_args()
43 lp
= sambaopts
.get_loadparm()
44 creds
= credopts
.get_credentials(lp
)
47 class SyntaxTests(samba
.tests
.TestCase
):
50 super(SyntaxTests
, self
).setUp()
52 self
.base_dn
= ldb
.domain_dn()
53 self
.schema_dn
= ldb
.get_schema_basedn().get_linearized()
54 self
._setup
_dn
_string
_test
()
55 self
._setup
_dn
_binary
_test
()
57 def _setup_dn_string_test(self
):
58 """Testing DN+String syntax"""
59 attr_name
= "test-Attr-DN-String" + time
.strftime("%s", time
.gmtime())
60 attr_ldap_display_name
= attr_name
.replace("-", "")
63 dn: CN=%s,%s""" % (attr_name
, self
.schema_dn
) + """
64 ldapDisplayName: """ + attr_ldap_display_name
+ """
66 objectClass: attributeSchema
67 cn: """ + attr_name
+ """
68 attributeId: 1.2.840.""" + str(random
.randint(1,100000)) + """.1.5.9940
69 attributeSyntax: 2.5.5.14
71 omObjectClass: \x2A\x86\x48\x86\xF7\x14\x01\x01\x01\x0C
73 schemaIdGuid: """ + str(uuid
.uuid4()) + """
76 self
.ldb
.add_ldif(ldif
)
78 # search for created attribute
80 res
= self
.ldb
.search("cn=%s,%s" % (attr_name
, self
.schema_dn
), scope
=SCOPE_BASE
, attrs
=["*"])
81 self
.assertEquals(len(res
), 1)
82 self
.assertEquals(res
[0]["lDAPDisplayName"][0], attr_ldap_display_name
)
83 self
.assertTrue("schemaIDGUID" in res
[0])
85 class_name
= "test-Class-DN-String" + time
.strftime("%s", time
.gmtime())
86 class_ldap_display_name
= class_name
.replace("-", "")
89 dn: CN=%s,%s""" % (class_name
, self
.schema_dn
) + """
91 objectClass: classSchema
92 adminDescription: """ + class_name
+ """
93 adminDisplayName: """ + class_name
+ """
94 cn: """ + class_name
+ """
95 governsId: 1.2.840.""" + str(random
.randint(1,100000)) + """.1.5.9939
96 schemaIdGuid: """ + str(uuid
.uuid4()) + """
97 objectClassCategory: 1
98 subClassOf: organizationalPerson
99 systemMayContain: """ + attr_ldap_display_name
+ """
102 self
.ldb
.add_ldif(ldif
)
104 # search for created objectclass
106 res
= self
.ldb
.search("cn=%s,%s" % (class_name
, self
.schema_dn
), scope
=SCOPE_BASE
, attrs
=["*"])
107 self
.assertEquals(len(res
), 1)
108 self
.assertEquals(res
[0]["lDAPDisplayName"][0], class_ldap_display_name
)
109 self
.assertEquals(res
[0]["defaultObjectCategory"][0], res
[0]["distinguishedName"][0])
110 self
.assertTrue("schemaIDGUID" in res
[0])
112 # store the class and the attribute
113 self
.dn_string_class_ldap_display_name
= class_ldap_display_name
114 self
.dn_string_attribute
= attr_ldap_display_name
115 self
.dn_string_class_name
= class_name
117 def _setup_dn_binary_test(self
):
118 """Testing DN+Binary syntaxes"""
119 attr_name
= "test-Attr-DN-Binary" + time
.strftime("%s", time
.gmtime())
120 attr_ldap_display_name
= attr_name
.replace("-", "")
123 dn: CN=%s,%s""" % (attr_name
, self
.schema_dn
) + """
124 ldapDisplayName: """ + attr_ldap_display_name
+ """
126 objectClass: attributeSchema
127 cn: """ + attr_name
+ """
128 attributeId: 1.2.840.""" + str(random
.randint(1,100000)) + """.1.5.9940
129 attributeSyntax: 2.5.5.7
131 omObjectClass: \x2A\x86\x48\x86\xF7\x14\x01\x01\x01\x0B
132 isSingleValued: FALSE
133 schemaIdGuid: """ + str(uuid
.uuid4()) + """
136 self
.ldb
.add_ldif(ldif
)
138 # search for created attribute
140 res
= self
.ldb
.search("cn=%s,%s" % (attr_name
, self
.schema_dn
), scope
=SCOPE_BASE
, attrs
=["*"])
141 self
.assertEquals(len(res
), 1)
142 self
.assertEquals(res
[0]["lDAPDisplayName"][0], attr_ldap_display_name
)
143 self
.assertTrue("schemaIDGUID" in res
[0])
145 class_name
= "test-Class-DN-Binary" + time
.strftime("%s", time
.gmtime())
146 class_ldap_display_name
= class_name
.replace("-", "")
149 dn: CN=%s,%s""" % (class_name
, self
.schema_dn
) + """
151 objectClass: classSchema
152 adminDescription: """ + class_name
+ """
153 adminDisplayName: """ + class_name
+ """
154 cn: """ + class_name
+ """
155 governsId: 1.2.840.""" + str(random
.randint(1,100000)) + """.1.5.9939
156 schemaIdGuid: """ + str(uuid
.uuid4()) + """
157 objectClassCategory: 1
158 subClassOf: organizationalPerson
159 systemMayContain: """ + attr_ldap_display_name
+ """
162 self
.ldb
.add_ldif(ldif
)
164 # search for created objectclass
166 res
= self
.ldb
.search("cn=%s,%s" % (class_name
, self
.schema_dn
), scope
=SCOPE_BASE
, attrs
=["*"])
167 self
.assertEquals(len(res
), 1)
168 self
.assertEquals(res
[0]["lDAPDisplayName"][0], class_ldap_display_name
)
169 self
.assertEquals(res
[0]["defaultObjectCategory"][0], res
[0]["distinguishedName"][0])
170 self
.assertTrue("schemaIDGUID" in res
[0])
172 # store the class and the attribute
173 self
.dn_binary_class_ldap_display_name
= class_ldap_display_name
174 self
.dn_binary_attribute
= attr_ldap_display_name
175 self
.dn_binary_class_name
= class_name
177 def _get_object_ldif(self
, object_name
, class_name
, class_ldap_display_name
, attr_name
, attr_value
):
178 # add object with correct syntax
180 dn: CN=%s,CN=Users,%s"""% (object_name
, self
.base_dn
) + """
181 objectClass: organizationalPerson
183 objectClass: """ + class_ldap_display_name
+ """
185 cn: """ + object_name
+ """
187 objectCategory: CN=%s,%s"""% (class_name
, self
.schema_dn
) + """
188 distinguishedName: CN=%s,CN=Users,%s"""% (object_name
, self
.base_dn
) + """
189 name: """ + object_name
+ """
190 """ + attr_name
+ attr_value
+ """
194 def test_dn_string(self
):
195 # add obeject with correct value
196 object_name1
= "obj-DN-String1" + time
.strftime("%s", time
.gmtime())
197 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
198 self
.dn_string_attribute
, ": S:5:ABCDE:" + self
.base_dn
)
199 self
.ldb
.add_ldif(ldif
)
201 # search by specifying the DN part only
202 res
= ldb
.search(base
=self
.base_dn
,
204 expression
="(%s=%s)" % (self
.dn_string_attribute
, self
.base_dn
))
205 self
.assertEquals(len(res
), 0)
207 # search by specifying the string part only
208 res
= ldb
.search(base
=self
.base_dn
,
210 expression
="(%s=S:5:ABCDE)" % self
.dn_string_attribute
)
211 self
.assertEquals(len(res
), 0)
213 # search by DN+Stirng
214 res
= ldb
.search(base
=self
.base_dn
,
216 expression
="(%s=S:5:ABCDE:%s)" % (self
.dn_string_attribute
, self
.base_dn
))
217 self
.assertEquals(len(res
), 1)
219 # add object with wrong format
220 object_name2
= "obj-DN-String2" + time
.strftime("%s", time
.gmtime())
221 ldif
= self
._get
_object
_ldif
(object_name2
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
222 self
.dn_string_attribute
, ": S:5:ABCD:" + self
.base_dn
)
224 self
.ldb
.add_ldif(ldif
)
225 except LdbError
, (num
, _
):
226 self
.assertEquals(num
, ERR_INVALID_ATTRIBUTE_SYNTAX
)
228 # add object with the same dn but with different string value in case
229 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
230 self
.dn_string_attribute
, ": S:5:abcde:" + self
.base_dn
)
232 self
.ldb
.add_ldif(ldif
)
233 except LdbError
, (num
, _
):
234 self
.assertEquals(num
, ERR_ENTRY_ALREADY_EXISTS
)
236 # add object with the same dn but with different string value
237 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
238 self
.dn_string_attribute
, ": S:5:FGHIJ:" + self
.base_dn
)
240 self
.ldb
.add_ldif(ldif
)
241 except LdbError
, (num
, _
):
242 self
.assertEquals(num
, ERR_ENTRY_ALREADY_EXISTS
)
244 # add object with the same dn but with different dn and string value
245 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
246 self
.dn_string_attribute
, ": S:5:FGHIJ:" + self
.schema_dn
)
248 self
.ldb
.add_ldif(ldif
)
249 except LdbError
, (num
, _
):
250 self
.assertEquals(num
, ERR_ENTRY_ALREADY_EXISTS
)
252 # add object with the same dn but with different dn value
253 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
254 self
.dn_string_attribute
, ": S:5:ABCDE:" + self
.schema_dn
)
256 self
.ldb
.add_ldif(ldif
)
257 except LdbError
, (num
, _
):
258 self
.assertEquals(num
, ERR_ENTRY_ALREADY_EXISTS
)
260 # add object with GUID instead of DN
261 object_name3
= "obj-DN-String3" + time
.strftime("%s", time
.gmtime())
262 ldif
= self
._get
_object
_ldif
(object_name3
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
263 self
.dn_string_attribute
, ": S:5:ABCDE:<GUID=%s>" % str(uuid
.uuid4()))
265 self
.ldb
.add_ldif(ldif
)
266 except LdbError
, (num
, _
):
267 self
.assertEquals(num
, ERR_CONSTRAINT_VIOLATION
)
269 # add object with SID instead of DN
270 object_name4
= "obj-DN-String4" + time
.strftime("%s", time
.gmtime())
271 ldif
= self
._get
_object
_ldif
(object_name4
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
272 self
.dn_string_attribute
, ": S:5:ABCDE:<SID=%s>" % self
.ldb
.get_domain_sid())
274 self
.ldb
.add_ldif(ldif
)
275 except LdbError
, (num
, _
):
276 self
.assertEquals(num
, ERR_CONSTRAINT_VIOLATION
)
278 # add object with random string instead of DN
279 object_name5
= "obj-DN-String5" + time
.strftime("%s", time
.gmtime())
280 ldif
= self
._get
_object
_ldif
(object_name5
, self
.dn_string_class_name
, self
.dn_string_class_ldap_display_name
,
281 self
.dn_string_attribute
, ": S:5:ABCDE:randomSTRING")
283 self
.ldb
.add_ldif(ldif
)
284 except LdbError
, (num
, _
):
285 self
.assertEquals(num
, ERR_CONSTRAINT_VIOLATION
)
288 def test_dn_binary(self
):
289 # add obeject with correct value
290 object_name1
= "obj-DN-Binary1" + time
.strftime("%s", time
.gmtime())
291 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
292 self
.dn_binary_attribute
, ": B:4:1234:" + self
.base_dn
)
293 self
.ldb
.add_ldif(ldif
)
295 # search by specifyingthe DN part
296 res
= ldb
.search(base
=self
.base_dn
,
298 expression
="(%s=%s)" % (self
.dn_binary_attribute
, self
.base_dn
))
299 self
.assertEquals(len(res
), 0)
301 # search by specifying the binary part
302 res
= ldb
.search(base
=self
.base_dn
,
304 expression
="(%s=B:4:1234)" % self
.dn_binary_attribute
)
305 self
.assertEquals(len(res
), 0)
307 # search by DN+Binary
308 res
= ldb
.search(base
=self
.base_dn
,
310 expression
="(%s=B:4:1234:%s)" % (self
.dn_binary_attribute
, self
.base_dn
))
311 self
.assertEquals(len(res
), 1)
313 # add object with wrong format - 5 bytes instead of 4, 8, 16, 32...
314 object_name2
= "obj-DN-Binary2" + time
.strftime("%s", time
.gmtime())
315 ldif
= self
._get
_object
_ldif
(object_name2
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
316 self
.dn_binary_attribute
, ": B:5:67890:" + self
.base_dn
)
318 self
.ldb
.add_ldif(ldif
)
319 except LdbError
, (num
, _
):
320 self
.assertEquals(num
, ERR_INVALID_ATTRIBUTE_SYNTAX
)
322 # add object with the same dn but with different binary value
323 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
324 self
.dn_binary_attribute
, ": B:4:5678:" + self
.base_dn
)
326 self
.ldb
.add_ldif(ldif
)
327 except LdbError
, (num
, _
):
328 self
.assertEquals(num
, ERR_ENTRY_ALREADY_EXISTS
)
330 # add object with the same dn but with different binary and dn value
331 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
332 self
.dn_binary_attribute
, ": B:4:5678:" + self
.schema_dn
)
334 self
.ldb
.add_ldif(ldif
)
335 except LdbError
, (num
, _
):
336 self
.assertEquals(num
, ERR_ENTRY_ALREADY_EXISTS
)
338 # add object with the same dn but with different dn value
339 ldif
= self
._get
_object
_ldif
(object_name1
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
340 self
.dn_binary_attribute
, ": B:4:1234:" + self
.schema_dn
)
342 self
.ldb
.add_ldif(ldif
)
343 except LdbError
, (num
, _
):
344 self
.assertEquals(num
, ERR_ENTRY_ALREADY_EXISTS
)
346 # add object with GUID instead of DN
347 object_name3
= "obj-DN-Binary3" + time
.strftime("%s", time
.gmtime())
348 ldif
= self
._get
_object
_ldif
(object_name3
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
349 self
.dn_binary_attribute
, ": B:4:1234:<GUID=%s>" % str(uuid
.uuid4()))
351 self
.ldb
.add_ldif(ldif
)
352 except LdbError
, (num
, _
):
353 self
.assertEquals(num
, ERR_CONSTRAINT_VIOLATION
)
355 # add object with SID instead of DN
356 object_name4
= "obj-DN-Binary4" + time
.strftime("%s", time
.gmtime())
357 ldif
= self
._get
_object
_ldif
(object_name4
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
358 self
.dn_binary_attribute
, ": B:4:1234:<SID=%s>" % self
.ldb
.get_domain_sid())
360 self
.ldb
.add_ldif(ldif
)
361 except LdbError
, (num
, _
):
362 self
.assertEquals(num
, ERR_CONSTRAINT_VIOLATION
)
364 # add object with random string instead of DN
365 object_name5
= "obj-DN-Binary5" + time
.strftime("%s", time
.gmtime())
366 ldif
= self
._get
_object
_ldif
(object_name5
, self
.dn_binary_class_name
, self
.dn_binary_class_ldap_display_name
,
367 self
.dn_binary_attribute
, ": B:4:1234:randomSTRING")
369 self
.ldb
.add_ldif(ldif
)
370 except LdbError
, (num
, _
):
371 self
.assertEquals(num
, ERR_CONSTRAINT_VIOLATION
)
374 ldb
= samba
.tests
.connect_samdb(host
, credentials
=creds
, session_info
=system_session(lp
), lp
=lp
)
375 runner
= SubunitTestRunner()
377 if not runner
.run(unittest
.makeSuite(SyntaxTests
)).wasSuccessful():