summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/dns.py
diff options
context:
space:
mode:
authorMartin Basti <mbasti@redhat.com>2014-01-31 15:42:31 +0100
committerMartin Kosek <mkosek@redhat.com>2014-02-11 17:21:11 +0100
commit8ede71fd8404a6e49e564a47b6dc7171d63cc8db (patch)
tree8dfb6b946bf935a27db75fa5251daa3446aca9ad /ipalib/plugins/dns.py
parent11505d9bce3a375af7f22686ef2a9e3a3a70e397 (diff)
downloadfreeipa-8ede71fd8404a6e49e564a47b6dc7171d63cc8db.tar.gz
freeipa-8ede71fd8404a6e49e564a47b6dc7171d63cc8db.tar.xz
freeipa-8ede71fd8404a6e49e564a47b6dc7171d63cc8db.zip
DNS classless support for reverse domains
Now users can add reverse zones in classless form: 0/25.1.168.192.in-addr.arpa. 0-25.1.168.192.in-addr.arpa. 128/25 NS ns.example.com. 10 CNAME 10.128/25.1.168.192.in-addr.arpa. Ticket: https://fedorahosted.org/freeipa/ticket/4143 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Diffstat (limited to 'ipalib/plugins/dns.py')
-rw-r--r--ipalib/plugins/dns.py45
1 files changed, 34 insertions, 11 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index afd47be31..caaeaf167 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -368,25 +368,31 @@ def _normalize_bind_aci(bind_acis):
acis += u';'
return acis
-def _bind_hostname_validator(ugettext, value):
+def _bind_hostname_validator(ugettext, value, allow_slash=False):
if value == _dns_zone_record:
return
try:
# Allow domain name which is not fully qualified. These are supported
# in bind and then translated as <non-fqdn-name>.<domain>.
- validate_hostname(value, check_fqdn=False, allow_underscore=True)
+ validate_hostname(value, check_fqdn=False, allow_underscore=True, allow_slash=allow_slash)
except ValueError, e:
return _('invalid domain-name: %s') \
% unicode(e)
return None
+def _bind_cname_hostname_validator(ugettext, value):
+ """
+ Validator for CNAME allows classless domain names (25/0.0.10.in-addr.arpa.)
+ """
+ return _bind_hostname_validator(ugettext, value, allow_slash=True)
+
def _dns_record_name_validator(ugettext, value):
if value == _dns_zone_record:
return
try:
- map(lambda label:validate_dns_label(label, allow_underscore=True), \
+ map(lambda label:validate_dns_label(label, allow_underscore=True, allow_slash=True), \
value.split(u'.'))
except ValueError, e:
return unicode(e)
@@ -411,7 +417,10 @@ def _validate_bind_forwarder(ugettext, forwarder):
def _domain_name_validator(ugettext, value):
try:
- validate_domain_name(value)
+ #classless reverse zones can contain slash '/'
+ normalized_zone = normalize_zone(value)
+ validate_domain_name(value, allow_slash=zone_is_reverse(normalized_zone))
+
except ValueError, e:
return unicode(e)
@@ -939,7 +948,7 @@ class CNAMERecord(DNSRecord):
rfc = 1035
parts = (
Str('hostname',
- _bind_hostname_validator,
+ _bind_cname_hostname_validator,
label=_('Hostname'),
doc=_('A hostname which this alias hostname points to'),
),
@@ -960,7 +969,7 @@ class DNAMERecord(DNSRecord):
rfc = 2672
parts = (
Str('target',
- _bind_hostname_validator,
+ _bind_cname_hostname_validator,
label=_('Target'),
),
)
@@ -2131,6 +2140,14 @@ class dnsrecord(LDAPObject):
doc=_('Parse all raw DNS records and return them in a structured way'),
)
+ def _idnsname_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
+ if not self.is_pkey_zone_record(*keys):
+ zone, addr = normalize_zone(keys[-2]), keys[-1]
+ try:
+ validate_domain_name(addr, allow_underscore=True, allow_slash=zone_is_reverse(zone))
+ except ValueError, e:
+ raise errors.ValidationError(name='idnsname', error=unicode(e))
+
def _nsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
nsrecords = entry_attrs.get('nsrecord')
@@ -2144,6 +2161,7 @@ class dnsrecord(LDAPObject):
ptrrecords = entry_attrs.get('ptrrecord')
if ptrrecords is None:
return
+
zone = keys[-2]
if self.is_pkey_zone_record(*keys):
addr = u''
@@ -2165,11 +2183,16 @@ class dnsrecord(LDAPObject):
error=unicode(_('Reverse zone for PTR record should be a sub-zone of one the following fully qualified domains: %s') % allowed_zones))
addr_len = len(addr.split('.')) if addr else 0
- ip_addr_comp_count = addr_len + len(zone.split('.'))
- if ip_addr_comp_count != zone_len:
- raise errors.ValidationError(name='ptrrecord',
- error=unicode(_('Reverse zone %(name)s requires exactly %(count)d IP address components, %(user_count)d given')
- % dict(name=zone_name, count=zone_len, user_count=ip_addr_comp_count)))
+
+ #Classless zones (0/25.0.0.10.in-addr.arpa.) -> skip check
+ #zone has to be checked without reverse domain suffix (in-addr.arpa.)
+ if ('/' not in addr and '/' not in zone and
+ '-' not in addr and '-' not in zone):
+ ip_addr_comp_count = addr_len + len(zone.split('.'))
+ if ip_addr_comp_count != zone_len:
+ raise errors.ValidationError(name='ptrrecord',
+ error=unicode(_('Reverse zone %(name)s requires exactly %(count)d IP address components, %(user_count)d given')
+ % dict(name=zone_name, count=zone_len, user_count=ip_addr_comp_count)))
def run_precallback_validators(self, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)