diff options
author | Martin Kosek <mkosek@redhat.com> | 2011-11-23 16:03:51 +0100 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2011-11-29 17:14:28 +0100 |
commit | 3f0eb1417ca0162861a05e3ced6a532b3cfba2ab (patch) | |
tree | 5aad0cfa7025aea4c526f61390567a2ede6cd292 | |
parent | 1039653a1b51f095175eeee3380a59e7303585f6 (diff) | |
download | freeipa-3f0eb1417ca0162861a05e3ced6a532b3cfba2ab.tar.gz freeipa-3f0eb1417ca0162861a05e3ced6a532b3cfba2ab.tar.xz freeipa-3f0eb1417ca0162861a05e3ced6a532b3cfba2ab.zip |
Improve zonemgr validator and normalizer
The validator has been improved to support better both SOA format
(e-mail address in a domain name format, without '@') and standard
e-mail format. Allow '\.' character in a SOA format encoding the
standard '.' in the local-part of an e-mail. Normalization code
has been moved to one common function.
https://fedorahosted.org/freeipa/ticket/2053
-rw-r--r-- | ipalib/plugins/dns.py | 11 | ||||
-rw-r--r-- | ipalib/util.py | 50 | ||||
-rw-r--r-- | ipaserver/install/bindinstance.py | 15 |
3 files changed, 49 insertions, 27 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py index bfc8090ca..e3522c903 100644 --- a/ipalib/plugins/dns.py +++ b/ipalib/plugins/dns.py @@ -27,7 +27,7 @@ from ipalib import Command from ipalib import Flag, Bool, Int, List, Str, StrEnum from ipalib.plugins.baseldap import * from ipalib import _, ngettext -from ipalib.util import validate_zonemgr, validate_hostname +from ipalib.util import validate_zonemgr, normalize_zonemgr, validate_hostname from ipapython import dnsclient from ipapython.ipautil import valid_ip from ldap import explode_dn @@ -152,13 +152,6 @@ def _rname_validator(ugettext, zonemgr): return unicode(e) return None -# normalizer for admin email -def _rname_normalizer(value): - value = value.replace('@', '.') - if not value.endswith('.'): - value += '.' - return value - def _create_zone_serial(**kwargs): """Generate serial number for zones.""" return int('%s01' % time.strftime('%Y%d%m')) @@ -678,7 +671,7 @@ class dnszone(LDAPObject): label=_('Administrator e-mail address'), doc=_('Administrator e-mail address'), default_from=lambda idnsname: 'root.%s' % idnsname, - normalizer=_rname_normalizer, + normalizer=normalize_zonemgr, ), Int('idnssoaserial?', cli_name='serial', diff --git a/ipalib/util.py b/ipalib/util.py index b0574f949..ffa275942 100644 --- a/ipalib/util.py +++ b/ipalib/util.py @@ -196,33 +196,63 @@ def check_writable_file(filename): except (IOError, OSError), e: raise errors.FileError(reason=str(e)) +def normalize_zonemgr(zonemgr): + if not zonemgr: + # do not normalize empty or None value + return zonemgr + if '@' in zonemgr: + # local-part needs to be normalized + name, at, domain = zonemgr.partition('@') + name = name.replace('.', '\\.') + zonemgr = u''.join((name, u'.', domain)) + + if not zonemgr.endswith('.'): + zonemgr = zonemgr + u'.' + + return zonemgr def validate_zonemgr(zonemgr): """ See RFC 1033, 1035 """ - regex_domain = re.compile(r'^[a-z0-9][a-z0-9-]*$', re.IGNORECASE) - regex_name = re.compile(r'^[a-z0-9][a-z0-9-_]*$', re.IGNORECASE) + regex_domain = re.compile(r'^[a-z0-9]([a-z0-9-]?[a-z0-9])*$', re.IGNORECASE) + regex_local_part = re.compile(r'^[a-z0-9]([a-z0-9-_\.]?[a-z0-9])*$', + re.IGNORECASE) + + local_part_errmsg = _('mail account may only include letters, numbers, -, _ and a dot. There may not be consecutive -, _ and . characters') if len(zonemgr) > 255: raise ValueError(_('cannot be longer that 255 characters')) + if zonemgr.endswith('.'): + zonemgr = zonemgr[:-1] + if zonemgr.count('@') == 1: - name, dot, domain = zonemgr.partition('@') + local_part, dot, domain = zonemgr.partition('@') + if not regex_local_part.match(local_part): + raise ValueError(local_part_errmsg) elif zonemgr.count('@') > 1: raise ValueError(_('too many \'@\' characters')) else: - # address in SOA format already (without @) - name, dot, domain = zonemgr.partition('.') + last_fake_sep = zonemgr.rfind('\\.') + if last_fake_sep != -1: # there is a 'fake' local-part/domain separator + sep = zonemgr.find('.', last_fake_sep+2) + if sep == -1: + raise ValueError(_('address domain is not fully qualified ' \ + '("example.com" instead of just "example")')) + local_part = zonemgr[:sep] + domain = zonemgr[sep+1:] + + if not all(regex_local_part.match(part) for part in local_part.split('\\.')): + raise ValueError(local_part_errmsg) + else: + local_part, dot, domain = zonemgr.partition('.') - if domain.endswith('.'): - domain = domain[:-1] + if not regex_local_part.match(local_part): + raise ValueError(local_part_errmsg) if '.' not in domain: raise ValueError(_('address domain is not fully qualified ' \ '("example.com" instead of just "example")')) - if not regex_name.match(name): - raise ValueError(_('mail account may only include letters, numbers, -, and _')) - if not all(regex_domain.match(part) for part in domain.split(".")): raise ValueError(_('domain name may only include letters, numbers, and -')) diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py index 7da4a891b..0b4a8d579 100644 --- a/ipaserver/install/bindinstance.py +++ b/ipaserver/install/bindinstance.py @@ -32,7 +32,7 @@ from ipapython import sysrestore from ipapython import ipautil from ipalib.constants import DNS_ZONE_REFRESH from ipalib.parameters import IA5Str -from ipalib.util import validate_zonemgr +from ipalib.util import validate_zonemgr, normalize_zonemgr from ipapython.ipa_log_manager import * import ipalib @@ -187,6 +187,9 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres if update_policy is None: update_policy = "grant %(realm)s krb5-self * A; grant %(realm)s krb5-self * AAAA;" % dict(realm=api.env.realm) + if zonemgr is None: + zonemgr = 'root.%s' % name + if ns_hostname is None: # automatically retrieve list of DNS masters dns_masters = api.Object.dnsrecord.get_dns_masters() @@ -298,10 +301,6 @@ def zonemgr_callback(option, opt_str, value, parser): except ValueError, e: parser.error("invalid zonemgr: " + unicode(e)) - name = opt_str.replace('--','') - v = unicode(value, 'utf-8') - ia = IA5Str(name) - ia._convert_scalar(v) parser.values.zonemgr = value class DnsBackup(object): @@ -387,10 +386,10 @@ class BindInstance(service.Service): self.zone_refresh = zone_refresh self.zone_notif = zone_notif - if zonemgr: - self.zonemgr = zonemgr.replace('@','.') - else: + if not zonemgr: self.zonemgr = 'root.%s.%s' % (self.host, self.domain) + else: + self.zonemgr = normalize_zonemgr(zonemgr) self.__setup_sub_dict() |