View | Details | Raw Unified | Return to bug 23945
Collapse All | Expand All

(-)a/branches/ucs-3.0/ucs/management/univention-directory-manager-modules/modules/univention/admin/handlers/dns/__init__.py (+55 lines)
Line 0    Link Here 
1
# vim: set fileencoding=utf-8 et sw=4 ts=4 :
2
3
ARPA_IP4 = '.in-addr.arpa'
4
ARPA_IP6 = '.ip6.arpa'
5
6
def makeContactPerson(obj, arg):
7
    """Create contact Email-address for domain."""
8
    domain = obj.position.getDomain()
9
    return 'root@%s.' % (domain.replace('dc=', '').replace(',','.'),)
10
11
def unescapeSOAemail(email):
12
    r"""
13
    Un-escape Email-address from DNS SOA record.
14
    >>> unescapeSOAemail(r'first\.last.domain.tld')
15
    'first.last@domain.tld'
16
    """
17
    ret = ''
18
    i = 0
19
    while i < len(email):
20
        if email[i] == '\\':
21
            i += 1
22
            if i >= len(email):
23
                raise ValueError()
24
        elif email[i] == '.':
25
            i += 1
26
            if i >= len(email):
27
                raise ValueError()
28
            ret += '@'
29
            ret += email[i:]
30
            return ret
31
        ret += email[i]
32
        i += 1
33
    raise ValueError()
34
35
def escapeSOAemail(email):
36
    r"""
37
    Escape Email-address for DNS SOA record.
38
    >>> escapeSOAemail('first.last@domain.tld')
39
    'first\\.last.domain.tld'
40
    """
41
    SPECIAL_CHARACTERS = set('"(),.:;<>@[\\]')
42
    if not '@' in email:
43
        raise ValueError()
44
    (local, domain) = email.rsplit('@', 1)
45
    tmp = ''
46
    for c in local:
47
        if c in SPECIAL_CHARACTERS:
48
            tmp += '\\'
49
        tmp += c
50
    local = tmp
51
    return local + '.' + domain
52
53
if __name__ == '__main__':
54
    import doctest
55
    doctest.testmod()
(-)a/branches/ucs-3.0/ucs/management/univention-directory-manager-modules/modules/univention/admin/handlers/dns/forward_zone.py (-50 / +12 lines)
 Lines 30-51    Link Here 
30
# /usr/share/common-licenses/AGPL-3; if not, see
30
# /usr/share/common-licenses/AGPL-3; if not, see
31
# <http://www.gnu.org/licenses/>.
31
# <http://www.gnu.org/licenses/>.
32
32
33
import re
34
35
from univention.admin.layout import Tab, Group
33
from univention.admin.layout import Tab, Group
36
from univention.admin import configRegistry
34
from univention.admin import configRegistry
37
35
38
import univention.admin.filter
36
import univention.admin.filter
39
import univention.admin.handlers
37
import univention.admin.handlers
40
import univention.admin.localization
38
import univention.admin.localization
39
from univention.admin.handlers.dns import ARPA_IP4, ARPA_IP6, escapeSOAemail, unescapeSOAemail
41
40
42
translation=univention.admin.localization.translation('univention.admin.handlers.dns')
41
translation=univention.admin.localization.translation('univention.admin.handlers.dns')
43
_=translation.translate
42
_=translation.translate
44
43
45
def makeContactPerson(object, arg):
46
	domain=object.position.getDomain()
47
	return 'root@%s.' %(domain.replace(',dc=','.').replace('dc=',''))
48
49
module='dns/forward_zone'
44
module='dns/forward_zone'
50
operations=['add','edit','remove','search']
45
operations=['add','edit','remove','search']
51
usewizard=1
46
usewizard=1
 Lines 252-289   class object(univention.admin.handlers.simpleLdap): Link Here 
252
247
253
		univention.admin.handlers.simpleLdap.__init__(self, co, lo, position, dn, superordinate, attributes = attributes )
248
		univention.admin.handlers.simpleLdap.__init__(self, co, lo, position, dn, superordinate, attributes = attributes )
254
249
255
	def unescapeSOAemail(self, email):
256
		ret = ''
257
		i = 0
258
		while i < len(email):
259
			if email[i] == '\\':
260
				i += 1
261
				if i >= len(email):
262
					raise ValueError()
263
			elif email[i] == '.':
264
				i += 1
265
				if i >= len(email):
266
					raise ValueError()
267
				ret += '@'
268
				ret += email[i:]
269
				return ret
270
			ret += email[i]
271
			i += 1
272
		raise ValueError()
273
274
	def escapeSOAemail(self, email):
275
		SPECIAL_CHARACTERS = set('"(),.:;<>@[\\]')
276
		if not '@' in email:
277
			raise ValueError()
278
		(local, domain, ) = email.rsplit('@', 1)
279
		tmp = ''
280
		for c in local:
281
			if c in SPECIAL_CHARACTERS:
282
				tmp += '\\'
283
			tmp += c
284
		local = tmp
285
		return local + '.' + domain
286
287
	def open(self):
250
	def open(self):
288
		univention.admin.handlers.simpleLdap.open(self)
251
		univention.admin.handlers.simpleLdap.open(self)
289
		self.info['a'] = []
252
		self.info['a'] = []
 Lines 294-301   class object(univention.admin.handlers.simpleLdap): Link Here 
294
257
295
		soa=self.oldattr.get('sOARecord',[''])[0].split(' ')
258
		soa=self.oldattr.get('sOARecord',[''])[0].split(' ')
296
		if len(soa) > 6:
259
		if len(soa) > 6:
297
			self['contact']=self.unescapeSOAemail(soa[1])
260
			self['contact'] = unescapeSOAemail(soa[1])
298
			self['serial']=soa[2]
261
			self['serial'] = soa[2]
299
			self['refresh'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[3] )
262
			self['refresh'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[3] )
300
			self['retry'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[4] )
263
			self['retry'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[4] )
301
			self['expire'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[5] )
264
			self['expire'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[5] )
 Lines 316-332   class object(univention.admin.handlers.simpleLdap): Link Here 
316
		ml=univention.admin.handlers.simpleLdap._ldap_modlist(self)
279
		ml=univention.admin.handlers.simpleLdap._ldap_modlist(self)
317
		if self.hasChanged(['nameserver', 'contact', 'serial', 'refresh', 'retry', 'expire', 'ttl']):
280
		if self.hasChanged(['nameserver', 'contact', 'serial', 'refresh', 'retry', 'expire', 'ttl']):
318
			if self['contact'] and not self['contact'].endswith('.'):
281
			if self['contact'] and not self['contact'].endswith('.'):
319
				self['contact'] = '%s.' % self['contact']
282
				self['contact'] += '.'
320
			if len (self['nameserver'][0]) > 0 \
283
			if len (self['nameserver'][0]) > 0 \
321
				and self['nameserver'][0].find (':') == -1 \
284
				and ':' not in self['nameserver'][0] \
322
				and self['nameserver'][0].find ('.') != -1 \
285
				and '.' in self['nameserver'][0] \
323
				and not self['nameserver'][0][-1] == '.':
286
				and not self['nameserver'][0].endswith('.'):
324
				self['nameserver'][0] = '%s.' % self['nameserver'][0]
287
				self['nameserver'][0] += '.'
325
			refresh = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'refresh' ] )
288
			refresh = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'refresh' ] )
326
			retry = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'retry' ] )
289
			retry = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'retry' ] )
327
			expire = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'expire' ] )
290
			expire = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'expire' ] )
328
			ttl = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'ttl' ] )
291
			ttl = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'ttl' ] )
329
			soa='%s %s %s %s %s %s %s' % (self['nameserver'][0], self.escapeSOAemail(self['contact']), self['serial'], refresh, retry, expire, ttl )
292
			soa='%s %s %s %s %s %s %s' % (self['nameserver'][0], escapeSOAemail(self['contact']), self['serial'], refresh, retry, expire, ttl )
330
			ml.append(('sOARecord', self.oldattr.get('sOARecord', []), [soa]))
293
			ml.append(('sOARecord', self.oldattr.get('sOARecord', []), [soa]))
331
294
332
		oldAddresses = self.oldinfo.get('a')
295
		oldAddresses = self.oldinfo.get('a')
 Lines 362-369   def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, Link Here 
362
	filter=univention.admin.filter.conjunction('&', [
325
	filter=univention.admin.filter.conjunction('&', [
363
		univention.admin.filter.expression('objectClass', 'dNSZone'),
326
		univention.admin.filter.expression('objectClass', 'dNSZone'),
364
		univention.admin.filter.expression('relativeDomainName', '@'),
327
		univention.admin.filter.expression('relativeDomainName', '@'),
365
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
328
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*%s' % ARPA_IP4)]),
366
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.ip6.arpa')]),
329
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*%s' % ARPA_IP6)]),
367
		])
330
		])
368
331
369
	if filter_s:
332
	if filter_s:
 Lines 376-381   def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, Link Here 
376
		res.append((object(co, lo, None, dn=dn, superordinate=superordinate, attributes = attrs )))
339
		res.append((object(co, lo, None, dn=dn, superordinate=superordinate, attributes = attrs )))
377
	return res
340
	return res
378
341
379
380
def identify(dn, attr, canonical=0):
342
def identify(dn, attr, canonical=0):
381
	return 'dNSZone' in attr.get('objectClass', []) and ['@'] == attr.get('relativeDomainName', []) and not attr['zoneName'][0].endswith('.in-addr.arpa') and not attr['zoneName'][0].endswith('.ip6.arpa')
343
	return 'dNSZone' in attr.get('objectClass', []) and ['@'] == attr.get('relativeDomainName', []) and not attr['zoneName'][0].endswith(ARPA_IP4) and not attr['zoneName'][0].endswith(ARPA_IP6)
(-)a/branches/ucs-3.0/ucs/management/univention-directory-manager-modules/modules/univention/admin/handlers/dns/reverse_zone.py (-19 / +42 lines)
 Lines 30-44    Link Here 
30
# /usr/share/common-licenses/AGPL-3; if not, see
30
# /usr/share/common-licenses/AGPL-3; if not, see
31
# <http://www.gnu.org/licenses/>.
31
# <http://www.gnu.org/licenses/>.
32
32
33
import string
34
import types
35
36
from univention.admin.layout import Tab, Group
33
from univention.admin.layout import Tab, Group
37
from univention.admin import configRegistry
34
from univention.admin import configRegistry
38
35
39
import univention.admin.filter
36
import univention.admin.filter
40
import univention.admin.handlers
37
import univention.admin.handlers
41
import univention.admin.localization
38
import univention.admin.localization
39
from univention.admin.handlers.dns import ARPA_IP4, ARPA_IP6, escapeSOAemail, unescapeSOAemail
42
40
43
translation=univention.admin.localization.translation('univention.admin.handlers.dns')
41
translation=univention.admin.localization.translation('univention.admin.handlers.dns')
44
_=translation.translate
42
_=translation.translate
 Lines 170-193   layout = [ Link Here 
170
]
168
]
171
169
172
def mapSubnet(subnet):
170
def mapSubnet(subnet):
171
	"""
172
	Map subnet to reverse zone.
173
	>>> mapSubnet('0123:4567:89ab:cdef')
174
	'f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa'
175
	>>> mapSubnet('1.2.3')
176
	'3.2.1.in-addr.arpa'
177
	"""
173
	if ':' in subnet: # IPv6
178
	if ':' in subnet: # IPv6
174
		return '.'.join(reversed(subnet.replace(':', ''))) + '.ip6.arpa'
179
		return '%s%s' % ('.'.join(reversed(subnet.replace(':', ''))), ARPA_IP6)
175
	else:
180
	else:
176
		q=subnet.split('.')
181
		q=subnet.split('.')
177
		q.reverse()
182
		q.reverse()
178
		return string.join(q, '.')+'.in-addr.arpa'
183
		return '%s%s' % ('.'.join(q), ARPA_IP4)
179
184
180
def unmapSubnet(zone):
185
def unmapSubnet(zone):
181
	if type(zone) == types.ListType:
186
	"""
187
	Map reverse zone to subnet.
188
	>>> unmapSubnet('f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa')
189
	'0123:4567:89ab:cdef'
190
	>>> unmapSubnet('3.2.1.in-addr.arpa')
191
	'1.2.3'
192
	"""
193
	if isinstance(zone, list):
182
		zone=zone[0]
194
		zone=zone[0]
183
	if '.ip6.arpa' in zone: # IPv6
195
	if zone.endswith(ARPA_IP6): # IPv6
184
		zone = list(reversed(zone.replace('.ip6.arpa', '').split('.')))
196
		zone = zone[:-len(ARPA_IP6)]
197
		zone = list(reversed(zone.split('.')))
185
		return ':'.join([''.join(zone[i:i+4]) for i in xrange(0, len(zone), 4)])
198
		return ':'.join([''.join(zone[i:i+4]) for i in xrange(0, len(zone), 4)])
186
	else:
199
	elif zone.endswith(ARPA_IP4): # IPv4
187
		zone=zone.replace('.in-addr.arpa', '')
200
		zone = zone[:-len(ARPA_IP4)]
188
		q=zone.split('.')
201
		q=zone.split('.')
189
		q.reverse()
202
		q.reverse()
190
		return string.join(q, '.')
203
		return '.'.join(q)
204
	else:
205
		raise ValueError('Neither an IPv4 nor an IPv& address')
191
206
192
mapping=univention.admin.mapping.mapping()
207
mapping=univention.admin.mapping.mapping()
193
mapping.register('subnet', 'zoneName', mapSubnet, unmapSubnet)
208
mapping.register('subnet', 'zoneName', mapSubnet, unmapSubnet)
 Lines 214-220   class object(univention.admin.handlers.simpleLdap): Link Here 
214
229
215
		soa=self.oldattr.get('sOARecord',[''])[0].split(' ')
230
		soa=self.oldattr.get('sOARecord',[''])[0].split(' ')
216
		if len(soa) > 6:
231
		if len(soa) > 6:
217
			self['contact']=soa[1].replace('.','@',1)
232
			self['contact'] = unescapeSOAemail(soa[1])
218
			self['serial'] = soa[2]
233
			self['serial'] = soa[2]
219
			self['refresh'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[3] )
234
			self['refresh'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[3] )
220
			self['retry'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[4] )
235
			self['retry'] = univention.admin.mapping.unmapUNIX_TimeInterval( soa[4] )
 Lines 229-240   class object(univention.admin.handlers.simpleLdap): Link Here 
229
	def _ldap_modlist(self):
244
	def _ldap_modlist(self):
230
		ml=univention.admin.handlers.simpleLdap._ldap_modlist(self)
245
		ml=univention.admin.handlers.simpleLdap._ldap_modlist(self)
231
		if self.hasChanged(['nameserver', 'contact', 'serial', 'refresh', 'retry', 'expire', 'ttl']):
246
		if self.hasChanged(['nameserver', 'contact', 'serial', 'refresh', 'retry', 'expire', 'ttl']):
232
247
			if self['contact'] and not self['contact'].endswith('.'):
248
				self['contact'] += '.'
249
			if len(self['nameserver'][0]) > 0 \
250
				and ':' not in self['nameserver'][0] \
251
				and '.' in self['nameserver'][0] \
252
				and not self['nameserver'][0].endswith('.'):
253
				self['nameserver'][0] += '.'
233
			refresh = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'refresh' ] )
254
			refresh = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'refresh' ] )
234
			retry = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'retry' ] )
255
			retry = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'retry' ] )
235
			expire = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'expire' ] )
256
			expire = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'expire' ] )
236
			ttl = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'ttl' ] )
257
			ttl = univention.admin.mapping.mapUNIX_TimeInterval( self[ 'ttl' ] )
237
			soa = '%s %s %s %s %s %s %s' % ( self[ 'nameserver' ][ 0 ], self[ 'contact' ].replace( '@', '.', 1 ), self[ 'serial' ], refresh, retry, expire, ttl )
258
			soa = '%s %s %s %s %s %s %s' % (self['nameserver'][0], escapeSOAemail(self['contact']), self['serial'], refresh, retry, expire, ttl)
238
			ml.append(('sOARecord', self.oldattr.get('sOARecord', []), soa))
259
			ml.append(('sOARecord', self.oldattr.get('sOARecord', []), soa))
239
		return ml
260
		return ml
240
261
 Lines 266-273   def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, Link Here 
266
		univention.admin.filter.expression('objectClass', 'dNSZone'),
287
		univention.admin.filter.expression('objectClass', 'dNSZone'),
267
		univention.admin.filter.expression('relativeDomainName', '@'),
288
		univention.admin.filter.expression('relativeDomainName', '@'),
268
		univention.admin.filter.conjunction('|', [
289
		univention.admin.filter.conjunction('|', [
269
			univention.admin.filter.expression('zoneName', '*.in-addr.arpa'),
290
			univention.admin.filter.expression('zoneName', '*%s' % ARPA_IP4),
270
			univention.admin.filter.expression('zoneName', '*.ip6.arpa')
291
			univention.admin.filter.expression('zoneName', '*%s' % ARPA_IP6)
271
			]),
292
			]),
272
		])
293
		])
273
294
 Lines 282-292   def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, Link Here 
282
	return res
303
	return res
283
304
284
def identify(dn, attr):
305
def identify(dn, attr):
285
286
	return 'dNSZone' in attr.get('objectClass', []) and\
306
	return 'dNSZone' in attr.get('objectClass', []) and\
287
		['@'] == attr.get('relativeDomainName', []) and\
307
		['@'] == attr.get('relativeDomainName', []) and\
288
		(attr['zoneName'][0].endswith('.in-addr.arpa') or attr['zoneName'][0].endswith('.ip6.arpa'))
308
		(attr['zoneName'][0].endswith(ARPA_IP4) or attr['zoneName'][0].endswith(ARPA_IP6))
289
309
290
def quickDescription(rdn):
310
def quickDescription(rdn):
291
292
	return unmapSubnet(rdn)
311
	return unmapSubnet(rdn)
312
313
if __name__ == '__main__':
314
    import doctest
315
    doctest.testmod()

Return to bug 23945