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)  

dhcp.py
Go to the documentation of this file.
1# -*- coding: ascii -*-
2"""
3web2ldap plugin classes for attributes defined for DHCP service
4
5See https://datatracker.ietf.org/doc/html/draft-ietf-dhc-ldap-schema
6"""
7
8import ipaddress
9import re
10from typing import Dict
11
12import web2ldapcnf
13
14from ..searchform import (
15 SEARCH_OPT_IS_EQUAL,
16 SEARCH_OPT_BEGINS_WITH,
17)
18from ..schema.syntaxes import (
19 MultilineText,
20 IA5String,
21 SelectList,
22 Integer,
23 BitArrayInteger,
24 MacAddress,
25 DynamicDNSelectList,
26 DNSDomain,
27 syntax_registry,
28)
29
30
32 oid: str = 'DHCPConfigStatement-oid'
33 desc: str = 'DHCP configuration statement'
34 lineSep = b''
35
36 def display(self, vidx, links) -> str:
37 res = ['<code>%s</code>' % (
38 MultilineText.display(self, vidx, links)
39 )]
40 if links:
41 try:
42 dhcp_type, dhcp_value = self.av_u.split(' ', 1)
43 except ValueError:
44 dhcp_type, dhcp_value = self.av_u, ''
45 dhcp_type = dhcp_type.lower().strip()
46 dhcp_value = dhcp_value.replace('"', '').strip()
47 if dhcp_type == 'host-name':
48 host_name = dhcp_value.lower().split('.', 1)[0]
49 res.append(self._app.anchor(
50 'search', 'DNS RR',
51 (
52 ('dn', str(self._app.naming_context)),
53 ('searchform_mode', 'adv'),
54 ('search_mode', '(|%s)'),
55 ('search_attr', 'dc'),
56 ('search_option', SEARCH_OPT_IS_EQUAL),
57 ('search_string', host_name),
58 ('search_attr', 'pTRRecord'),
59 ('search_option', SEARCH_OPT_BEGINS_WITH),
60 ('search_string', host_name+'.'),
61 ('search_attr', 'associatedDomain'),
62 ('search_option', SEARCH_OPT_BEGINS_WITH),
63 ('search_string', host_name+'.'),
64 ),
65 title='Search related DNS RR entry',
66 ))
67 elif dhcp_type == 'fixed-address':
68 search_params = [
69 ('dn', str(self._app.naming_context)),
70 ('searchform_mode', 'adv'),
71 ('search_mode', '(|%s)'),
72 ('search_attr', 'aRecord'),
73 ('search_option', SEARCH_OPT_IS_EQUAL),
74 ('search_string', dhcp_value),
75 ('search_attr', 'aAAARecord'),
76 ('search_option', SEARCH_OPT_IS_EQUAL),
77 ('search_string', dhcp_value),
78 ]
79 try:
80 reverse_dns = ipaddress.ip_address(dhcp_value).reverse_pointer
81 except ValueError:
82 pass
83 else:
84 search_params.extend((
85 ('search_attr', 'associatedDomain'),
86 ('search_option', SEARCH_OPT_IS_EQUAL),
87 ('search_string', reverse_dns),
88 ))
89 res.append(
90 self._app.anchor(
91 'search', 'DNS RRs',
92 search_params,
93 title='Search related DNS RR entries',
94 )
95 )
96 return web2ldapcnf.command_link_separator.join(res)
97
98syntax_registry.reg_at(
99 DHCPConfigStatement.oid, [
100 '2.16.840.1.113719.1.203.4.3', # dhcpStatements
101 '2.16.840.1.113719.1.203.6.9', # dhcpOptions
102 '2.16.840.1.113719.1.203.4.7', # dhcpOption
103 ]
104)
105
106
108 oid: str = 'DHCPServerDN-oid'
109 desc: str = 'DN of DHCP server entry'
110 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpServer)'
111
112syntax_registry.reg_at(
113 DHCPServerDN.oid, [
114 '2.16.840.1.113719.1.203.4.1', # dhcpPrimaryDN
115 '2.16.840.1.113719.1.203.4.2', # dhcpSecondaryDN
116 '2.16.840.1.113719.1.203.4.54', # dhcpFailOverPeerDN
117 ]
118)
119
120
122 oid: str = 'DHCPOptionsDN-oid'
123 desc: str = 'DN of DHCP option object'
124 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpOptions)'
125
126syntax_registry.reg_at(
127 DHCPOptionsDN.oid, [
128 '2.16.840.1.113719.1.203.4.9', # dhcpOptionsDN
129 ]
130)
131
132
134 oid: str = 'DHCPHostDN-oid'
135 desc: str = 'DN of DHCP host object'
136 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpHost)'
137
138syntax_registry.reg_at(
139 DHCPHostDN.oid, [
140 '2.16.840.1.113719.1.203.4.10', # dhcpHostDN
141 '2.16.840.1.113719.1.203.4.31', # dhcpReservedForClient
142 '2.16.840.1.113719.1.203.4.32', # dhcpAssignedToClient
143 ]
144)
145
146
148 oid: str = 'DHCPPoolDN-oid'
149 desc: str = 'DN of DHCP pool object'
150 ldap_url = 'ldap:///_??sub?(objectClass=dhcpPool)'
151
152syntax_registry.reg_at(
153 DHCPPoolDN.oid, [
154 '2.16.840.1.113719.1.203.4.11', # dhcpPoolDN
155 ]
156)
157
158
160 oid: str = 'DHCPGroupDN-oid'
161 desc: str = 'DN of DHCP group object'
162 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpGroup)'
163
164syntax_registry.reg_at(
165 DHCPGroupDN.oid, [
166 '2.16.840.1.113719.1.203.4.12', # dhcpGroupDN
167 ]
168)
169
170
172 oid: str = 'DHCPSubnetDN-oid'
173 desc: str = 'DN of DHCP subnet object'
174 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpSubnet)'
175
176syntax_registry.reg_at(
177 DHCPSubnetDN.oid, [
178 '2.16.840.1.113719.1.203.4.13', # dhcpSubnetDN
179 ]
180)
181
182
184 oid: str = 'DHCPLeasesDN-oid'
185 desc: str = 'DN of DHCP leases object'
186 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpLeases)'
187
188syntax_registry.reg_at(
189 DHCPLeasesDN.oid, [
190 '2.16.840.1.113719.1.203.4.14', # dhcpLeaseDN
191 '2.16.840.1.113719.1.203.4.15', # dhcpLeasesDN
192 ]
193)
194
195
197 oid: str = 'DHCPClassesDN-oid'
198 desc: str = 'DN of DHCP classes object'
199 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpClass)'
200
201syntax_registry.reg_at(
202 DHCPClassesDN.oid, [
203 '2.16.840.1.113719.1.203.4.16', # dhcpClassesDN
204 ]
205)
206
207
209 oid: str = 'DHCPSubclassesDN-oid'
210 desc: str = 'DN of DHCP Subclasses object'
211 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpSubclass)'
212
213syntax_registry.reg_at(
214 DHCPSubclassesDN.oid, [
215 '2.16.840.1.113719.1.203.4.17', # dhcpSubclassesDN
216 ]
217)
218
219
221 oid: str = 'DHCPSharedNetworkDN-oid'
222 desc: str = 'DN of DHCP shared network object'
223 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpSharedNetwork)'
224
225syntax_registry.reg_at(
226 DHCPSharedNetworkDN.oid, [
227 '2.16.840.1.113719.1.203.4.18', # dhcpSharedNetworkDN
228 ]
229)
230
231
233 oid: str = 'DHCPServiceDN-oid'
234 desc: str = 'DN of DHCP service object'
235 ldap_url = 'ldap:///_?cn?sub?(objectClass=dhcpService)'
236
237syntax_registry.reg_at(
238 DHCPServiceDN.oid, [
239 '2.16.840.1.113719.1.203.4.19', # dhcpServiceDN
240 ]
241)
242
243
245 oid: str = 'DHCPHWAddress-oid'
246 desc: str = 'Network classifier and MAC address'
247 max_len: str = 26
248 pattern = re.compile(r'^(ethernet|token-ring|fddi) ([0-9a-fA-F]{2}\:){5}[0-9a-fA-F]{2}$')
249
250 def sanitize(self, attr_value: bytes) -> bytes:
251 attr_value = attr_value.strip()
252 if len(attr_value) == 17:
253 return b'ethernet %s' % attr_value
254 return attr_value
255
256syntax_registry.reg_at(
257 DHCPHWAddress.oid, [
258 '2.16.840.1.113719.1.203.4.34', # dhcpHWAddress
259 ]
260)
261
262
264 oid: str = 'DHCPNetMask-oid'
265 desc: str = 'Network address mask bits'
266 min_value = 0
267 max_value = 32
268 input_size = 15
269
270 def _maxlen(self, fval):
271 return self.input_size
272
273syntax_registry.reg_at(
274 DHCPNetMask.oid, [
275 '2.16.840.1.113719.1.203.4.6', # dhcpNetMask
276 ]
277)
278
279
281 oid: str = 'DHCPRange-oid'
282 desc: str = 'Network address range'
283
284 def _get_ipnetwork(self):
285 name = self._entry['cn'][0].strip().decode('ascii')
286 net_mask = self._entry['dhcpNetMask'][0].strip().decode('ascii')
287 return ipaddress.ip_network(('%s/%s' % (name, net_mask)), strict=False)
288
289 def form_value(self) -> str:
290 fval = IA5String.form_value(self)
291 if not fval:
292 try:
293 ipv4_hosts = self._get_ipnetwork().hosts()
294 first_address = next(ipv4_hosts)
295 try:
296 while True:
297 last_address = next(ipv4_hosts)
298 except StopIteration:
299 pass
300 fval = '{0} {1}'.format(first_address, last_address)
301 except ipaddress.AddressValueError:
302 pass
303 return fval
304
305 def sanitize(self, attr_value: bytes) -> bytes:
306 return attr_value.strip().replace(b' ', b' ').replace(b'-', b' ').replace(b'..', b' ')
307
308 def _validate(self, attr_value: bytes) -> bool:
309 try:
310 l_s, h_s = attr_value.decode(self._app.ls.charset).split(' ', 1)
311 except (IndexError, ValueError):
312 return False
313 try:
314 l_a = ipaddress.ip_address(l_s)
315 h_a = ipaddress.ip_address(h_s)
316 except Exception:
317 return False
318 if l_a > h_a:
319 return False
320 try:
321 ipv4_network = self._get_ipnetwork()
322 except Exception:
323 # Let's simply ignore all parsing issues with network address data here
324 return True
325 return l_a in ipv4_network and h_a in ipv4_network
326
327
328syntax_registry.reg_at(
329 DHCPRange.oid, [
330 '2.16.840.1.113719.1.203.4.4', # dhcpRange
331 ]
332)
333
334
336 oid: str = 'DHCPAddressState-oid'
337 desc: str = 'DHCP address state'
338
339 attr_value_dict: Dict[str, str] = {
340 '': '',
341 'FREE': 'FREE',
342 'ACTIVE': 'ACTIVE',
343 'EXPIRED': 'EXPIRED',
344 'RELEASED': 'RELEASED',
345 'RESET': 'RESET',
346 'ABANDONED': 'ABANDONED',
347 'BACKUP': 'BACKUP',
348 'UNKNOWN': 'UNKNOWN',
349 'RESERVED': 'RESERVED (address managed by DHCP that is reserved for a specific client)',
350 'RESERVED-ACTIVE': 'RESERVED-ACTIVE (same as reserved, but address is currently in use)',
351 'ASSIGNED': 'ASSIGNED (assigned manually or by some other mechanism)',
352 'UNASSIGNED': 'UNASSIGNED',
353 'NOTASSIGNABLE': 'NOTASSIGNABLE',
354 }
355
356
358 """
359 0 (C): name to address (such as A RR) update successfully completed
360 1 (A): Server is controlling A RR on behalf of the client
361 2 (D): address to name (such as PTR RR) update successfully completed (Done)
362 3 (P): Server is controlling PTR RR on behalf of the client
363 4-15 : Must be zero
364 """
365 oid: str = 'DHCPDnsStatus-oid'
366 flag_desc_table = (
367 ('(C): name to address (such as A RR) update successfully completed', 0x0001),
368 ('(A): Server is controlling A RR on behalf of the client', 0x0002),
369 ('(D): address to name (such as PTR RR) update successfully completed (Done)', 0x0004),
370 ('(P): Server is controlling PTR RR on behalf of the client', 0x0008),
371 )
372
373syntax_registry.reg_at(
374 DHCPDnsStatus.oid, [
375 '2.16.840.1.113719.1.203.4.28', # dhcpDnsStatus
376 ]
377)
378
379
380syntax_registry.reg_at(
381 DNSDomain.oid, [
382 '2.16.840.1.113719.1.203.4.27', # dhcpDomainName
383 ]
384)
385
386
387syntax_registry.reg_at(
388 DHCPAddressState.oid, [
389 '2.16.840.1.113719.1.203.4.22', # dhcpAddressState
390 ]
391)
392
393
394# Register all syntax classes in this module
395syntax_registry.reg_syntaxes(__name__)
str display(self, vidx, links)
Definition: dhcp.py:36
bytes sanitize(self, bytes attr_value)
Definition: dhcp.py:250
bool _validate(self, bytes attr_value)
Definition: dhcp.py:308
bytes sanitize(self, bytes attr_value)
Definition: dhcp.py:305