web2ldap  1.7.7
About: web2ldap is a full-featured web-based LDAPv3 client.
  Fossies Dox: web2ldap-1.7.7.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

edirectory.py
Go to the documentation of this file.
1# -*- coding: ascii -*-
2"""
3web2ldap plugin classes for Novell eDirectory/DirXML
4(see draft-sermersheim-nds-ldap-schema)
5"""
6
7import uuid
8from binascii import hexlify
9from typing import Dict
10
11import ldap0.filter
12
13import web2ldapcnf
14
15from ..schema.syntaxes import (
16 Binary,
17 BitArrayInteger,
18 DirectoryString,
19 DynamicDNSelectList,
20 Integer,
21 MultilineText,
22 NullTerminatedDirectoryString,
23 OctetString,
24 OID,
25 PostalAddress,
26 PreformattedMultilineText,
27 PrintableString,
28 SelectList,
29 XmlValue,
30 syntax_registry,
31)
32from .x509 import Certificate, CertificateList
33
34
35# FIX ME! Disabled this because of double OID which eDirectory is famous for. :-(
36#class CaseIgnoreList(PostalAddress):
37# oid = '2.16.840.1.113719.1.1.5.1.6'
38# desc = 'Case Ignore List'
39
40
42 oid: str = '2.16.840.1.113719.1.1.5.1.12'
43 desc: str = 'Tagged Data'
44
45
47 oid: str = '2.16.840.1.113719.1.1.5.1.13'
48 desc: str = 'Octet List'
49
50
52 oid: str = '2.16.840.1.113719.1.1.5.1.14'
53 desc: str = 'Tagged String'
54
55
57 oid: str = '2.16.840.1.113719.1.1.5.1.6'
58 desc: str = '$-separated string'
59
60
62 oid: str = 'OctetStringGUID-oid'
63 desc: str = 'GUID of eDirectory entries represented as 16 byte octet string'
64
65 def _validate(self, attr_value: bytes) -> bool:
66 return len(attr_value) == 16
67
68 @staticmethod
70 """
71 format association like Edir2Edir driver: {60445C8E-D8DB-d801-808C-0008028B1EF9}
72 """
73 s1 = hexlify(s).upper()
74 return '{%s}' % (
75 '-'.join((
76 ''.join((s1[6:8], s1[4:6], s1[2:4], s1[0:2])),
77 ''.join((s1[10:12], s1[8:10])),
78 ''.join((s1[14:16].lower(), s1[12:14].lower())),
79 s1[16:20],
80 s1[20:32],
81 ))
82 )
83
84 @staticmethod
86 """
87 format association like entitlement driver: {8E5C4460-DBD8-01D8-808C-0008028B1EF9}
88 """
89 s1 = hexlify(s).upper()
90 return '{%s}' % ('-'.join((
91 s1[0:8],
92 s1[8:12],
93 s1[12:16],
94 s1[16:20],
95 s1[20:32],
96 )))
97
98 @staticmethod
100 """
101 format association like C1 and iManager: 60445C8E-D8DB-d801-808C-0008028B1EF9
102 """
103 s1 = hexlify(s).upper()
104 return ''.join((
105 s1[6:8],
106 s1[4:6],
107 s1[2:4],
108 s1[0:2],
109 s1[10:12],
110 s1[8:10],
111 s1[14:16],
112 s1[12:14],
113 s1[16:32],
114 ))
115
116 def display(self, vidx, links) -> str:
117 if self._at_at == 'GUID':
118 # GUID of an entry is displayed in several variants
119 return """
120 <table summary="GUID representation variants">
121 <tr><td>Octet String</td><td>%s</td></tr>
122 <tr><td>UUID</td><td>%s</td></tr>
123 <tr><td>Edir2Edir driver</td><td>%s</td></tr>
124 <tr><td>entitlement driver</td><td>%s</td></tr>
125 <tr><td>C1/iManager assoc.</td><td>%s</td></tr>
126 </table>
127 """ % (
128 OctetString.display(self, vidx, links),
129 str(uuid.UUID(bytes=self._av)),
130 self._guid2association(self._av),
131 self._guid2assoc(self._av),
132 self._guid2assoc_c1(self._av),
133 )
134 # GUID of an referenced entry is just displayed as in Console 1 / iManager
135 # with a link for searching the entry
136 return web2ldapcnf.command_link_separator.join((
137 self._guid2assoc_c1(self._av),
138 self._app.anchor(
139 'searchform', '&raquo;',
140 [
141 ('dn', self._dn),
142 ('filterstr', ldap0.filter.escape_str(self._av)),
143 ('searchform_mode', 'exp'),
144 ],
145 title='Search entry with this GUID',
146 )
147 ))
148
149
150syntax_registry.reg_at(
151 OctetStringGUID.oid, [
152 '2.16.840.1.113719.1.1.4.1.501', # GUID
153 '2.16.840.1.113719.1.280.4.931.1', # ASAM-inputGUID
154 '2.16.840.1.113719.1.14.4.1.50', # DirXML-ServerGUID
155 '2.16.840.1.113719.1.1.4.1.502', # otherGUID
156 ]
157)
158
159
161 """
162 Version: 0 (reserved for future use)
163 Name: description of index
164 State: 0-suspend, 1-bringing, 2-online, 3-pending
165 Matching Rule: 0-value, 1-presence, 2-substring
166 Type: 0-user defined
167 Value State: 1-added from server
168 NDS Attribute Name
169 """
170 oid: str = 'IndexDefinition-oid'
171 desc: str = 'Index Definition'
172
173 def display(self, vidx, links) -> str:
174 try:
175 (
176 version,
177 index_name,
178 state,
179 matching_rule,
180 index_type,
181 value_state,
182 nds_attribute_name,
183 ) = self._av.split('$')
184 version = int(version)
185 index_name = self._app.ls.uc_decode(index_name)[0]
186 state = int(state)
187 matching_rule = int(matching_rule)
188 index_type = int(index_type)
189 value_state = int(value_state)
190 nds_attribute_name = self._app.ls.uc_decode(nds_attribute_name)[0]
191 except (ValueError, UnicodeDecodeError):
192 return DollarSeparatedMultipleLines.display(self, vidx, links)
193 return """
194 <table>
195 <tr><td>Version:</td><td>%s</td></tr>
196 <tr><td>Name:</td><td>%s</td></tr>
197 <tr><td>State:</td><td>%s</td></tr>
198 <tr><td>Matching Rule:</td><td>%s</td></tr>
199 <tr><td>Type:</td><td>%s</td></tr>
200 <tr><td>Value State:</td><td>%s</td></tr>
201 <tr><td>NDS Attribute Name</td><td>%s</td></tr>
202 </table>""" % (
203 version,
204 index_name.encode(self._app.form.accept_charset),
205 {0:'suspend', 1:'bringing', 2:'online', 3:'pending'}.get(state, str(state)),
206 {0:'value', 1:'presence', 2:'substring'}.get(matching_rule, str(matching_rule)),
207 {0:'user defined'}.get(index_type, str(index_type)),
208 {1:'added from server'}.get(value_state, str(value_state)),
209 nds_attribute_name.encode(self._app.form.accept_charset),
210 )
211
212syntax_registry.reg_at(
213 IndexDefinition.oid, [
214 '2.16.840.1.113719.1.1.4.1.512', # indexDefinition
215 ]
216)
217
218
220 oid: str = '2.16.840.1.113719.1.1.5.1.15'
221 desc: str = 'Tagged Name And String'
222
223 def display(self, vidx, links) -> str:
224 try:
225 ind2 = self._av.rindex('#')
226 ind1 = self._av.rindex('#', 0, ind2-1)
227 except ValueError:
228 return DirectoryString.display(self, vidx, links)
229 dn = self._app.ls.uc_decode(self._av[0:ind1])[0]
230 number = self._av[ind1+1:ind2]
231 dstring = self._av[ind2+1:]
232 try:
233 dstring.decode('utf8')
234 except UnicodeError:
235 dstring_disp = OctetString.display(self, vidx, links)
236 else:
237 dstring_disp = DirectoryString.display(self, vidx, links)
238 return (
239 '<dl>'
240 '<dt>name:</dt><dd>%s</dd>'
241 '<dt>number:</dt><dd>%s</dd>'
242 '<dt>dstring:</dt><dd><code>%s</code></dd>'
243 '</dl>'
244 ) % (
245 self._app.display_dn(dn, links=links),
246 number,
247 dstring_disp,
248 )
249
250
252 oid: str = '2.16.840.1.113719.1.1.5.1.16'
253 desc: str = 'NDS Replica Pointer'
254
255
257 oid: str = '2.16.840.1.113719.1.1.5.1.17'
258 desc: str = 'NDS ACL'
259
260
262 oid: str = '2.16.840.1.113719.1.1.5.1.19'
263 desc: str = 'NDS Timestamp'
264
265
267 oid: str = '2.16.840.1.113719.1.1.5.1.22'
268 desc: str = 'Counter (NDS)'
269
270
272 oid: str = '2.16.840.1.113719.1.1.5.1.23'
273 desc: str = 'Tagged Name'
274
275
277 oid: str = '2.16.840.1.113719.1.1.5.1.25'
278 desc: str = 'Typed Name'
279
280
282 """
283 See
284 """
285 oid: str = 'EntryFlags-oid'
286 flag_desc_table = (
287 ('DS_ALIAS_ENTRY', 0x0001),
288 ('DS_PARTITION_ROOT', 0x0002),
289 ('DS_CONTAINER_ENTRY', 0x0004),
290 ('DS_CONTAINER_ALIAS', 0x0008),
291 ('DS_MATCHES_LIST_FILTER', 0x0010),
292 ('DS_REFERENCE_ENTRY', 0x0020),
293 ('DS_40X_REFERENCE_ENTRY', 0x0040),
294 ('DS_BACKLINKED', 0x0080),
295 ('DS_NEW_ENTRY', 0x0100),
296 ('DS_TEMPORARY_REFERENCE', 0x0200),
297 ('DS_AUDITED', 0x0400),
298 ('DS_ENTRY_NOT_PRESENT', 0x0800),
299 ('DS_ENTRY_VERIFY_CTS', 0x1000),
300 ('DS_ENTRY_DAMAGED', 0x2000),
301 )
302
303syntax_registry.reg_at(
304 EntryFlags.oid, [
305 '2.16.840.1.113719.1.27.4.48', # entryFlags
306 ]
307)
308
309
311 """
312 See http://ldapwiki.willeke.com/wiki/UniversalPasswordSecretBits
313 """
314 oid: str = 'NspmConfigurationOptions-oid'
315 flag_desc_table = (
316 ('On set password request the NDS password hash will be removed by SPM', 0x01),
317 ('On set password request the NDS password hash will not be set by SPM', 0x02),
318 ('On set password request the Simple password will not be set by SPM', 0x04),
319 ('Reserved 0x08', 0x08),
320 ('Allow password retrieval by self (User)', 0x10),
321 ('Allow password retrieval by admin', 0x20),
322 ('Allow password retrieval by password agents (trusted app)', 0x40),
323 ('Reserved 0x80', 0x80),
324 ('Password enabled', 0x100),
325 ('Advanced password policy enabled', 0x200),
326 )
327
328syntax_registry.reg_at(
329 NspmConfigurationOptions.oid, [
330 '2.16.840.1.113719.1.39.43.4.100', # nspmConfigurationOptions
331 ]
332)
333
334
336 oid: str = 'SnmpTrapDescription-oid'
337 desc: str = 'SNMP Trap Description'
338 lineSep = b'\x00'
339 cols = 30
340
341syntax_registry.reg_at(
342 SnmpTrapDescription.oid, [
343 '2.16.840.1.113719.1.6.4.4', # snmpTrapDescription
344 ]
345)
346
347
349 oid: str = 'SASVendorSupport-oid'
350 desc: str = 'SAS Vendor Support'
351 cols = 50
352
353syntax_registry.reg_at(
354 SASVendorSupport.oid, [
355 '2.16.840.1.113719.1.39.42.1.0.12', # sASVendorSupport
356 ]
357)
358
359
361 oid: str = 'NspmPasswordPolicyDN-oid'
362 desc: str = 'DN of the nspmPasswordPolicy entry'
363 ldap_url = 'ldap:///cn=Password Policies,cn=Security?cn?sub?(objectClass=nspmPasswordPolicy)'
364
365syntax_registry.reg_at(
366 NspmPasswordPolicyDN.oid, [
367 '2.16.840.1.113719.1.39.43.4.6', # nspmPasswordPolicyDN
368 ]
369)
370
372 oid: str = 'DirXML-DriverStartOption-oid'
373 desc: str = 'Start option for a DirXML driver'
374 attr_value_dict: Dict[str, str] = {
375 '0': 'disabled',
376 '1': 'manual',
377 '2': 'auto',
378 }
379
380syntax_registry.reg_at(
381 DirXMLDriverStartOption.oid, [
382 '2.16.840.1.113719.1.14.4.1.13', # DirXML-DriverStartOption
383 ]
384)
385
386
388 oid: str = 'DirXML-State-DriverStartOption-oid'
389 desc: str = 'Current state of a DirXML driver'
390 attr_value_dict: Dict[str, str] = {
391 '0': 'stopped',
392 '1': 'starting',
393 '2': 'running',
394 '3': 'stopping',
395 }
396
397syntax_registry.reg_at(
398 DirXMLState.oid, [
399 '2.16.840.1.113719.1.14.4.1.14', # DirXML-State
400 ]
401)
402
403# Workarounds for eDirectory
404
405syntax_registry.reg_at(
406 Certificate.oid, [
407 '2.16.840.1.113719.1.48.4.1.3', # nDSPKIPublicKeyCertificate
408 ]
409)
410
411syntax_registry.reg_at(
412 CertificateList.oid, [
413 # certificateRevocationList in Novell eDirectory
414 '2.16.840.1.113719.1.48.4.1.34',
415 ]
416)
417
418syntax_registry.reg_at(
419 OID.oid,
420 [
421 'supportedGroupingTypes',
422 ]
423)
424
425syntax_registry.reg_at(
426 NullTerminatedDirectoryString.oid, [
427 '2.16.840.1.113719.1.27.4.42', # extensionInfo
428 ]
429)
430
431syntax_registry.reg_at(
432 Binary.oid, [
433 '2.16.840.1.113719.1.48.4.1.4', # nDSPKICertificateChain
434 '2.16.840.1.113719.1.48.4.1.2', # nDSPKIPrivateKey
435 '2.16.840.1.113719.1.48.4.1.1', # nDSPKIPublicKey
436 '2.16.840.1.113719.1.14.4.1.42', # DirXML-Act3
437 '2.16.840.1.113719.1.200.4.1', # bhConfig
438 '2.16.840.1.113719.1.200.4.2', # bhConfigRW
439 '2.16.840.1.113719.1.200.4.3', # bhConfigSecretStore
440 '2.16.840.1.113719.1.1.4.1.84', # publicKey
441 ]
442)
443
444syntax_registry.reg_at(
445 XmlValue.oid, [
446 '2.16.840.1.113719.1.1.4.1.295', # emboxConfig
447 '2.16.840.1.113719.1.14.4.1.3', # XmlData
448 '2.16.840.1.113719.1.14.4.1.8', # DirXML-ShimConfigInfo
449 '2.16.840.1.113719.1.14.4.1.11', # DirXML-DriverFilter
450 '2.16.840.1.113719.1.14.4.1.24', # DirXML-DriverCacheLimit
451 '2.16.840.1.113719.1.14.4.1.29', # DirXML-ApplicationSchema
452 '2.16.840.1.113719.1.14.4.1.54', # DirXML-ConfigValues
453 '2.16.840.1.113719.1.14.4.1.56', # DirXML-ConfigManifest
454 '2.16.840.1.113719.1.14.4.1.58', # DirXML-EngineControlValues
455 '2.16.840.1.113719.1.14.4.1.82', # DirXML-PersistentData
456 '2.16.840.1.113719.1.39.44.4.1', # nsimRequiredQuestions
457 '2.16.840.1.113719.1.39.44.4.2', # nsimRandomQuestions
458 '2.16.840.1.113719.1.39.44.4.7', # nsimForgottenAction
459 '2.16.840.1.113719.1.347.4.1', # NAuditConfiguration
460 ]
461)
462
463
464# Register all syntax classes in this module
465syntax_registry.reg_syntaxes(__name__)
bool _validate(self, bytes attr_value)
Definition: edirectory.py:65