summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorMartin Kosek <mkosek@redhat.com>2012-02-24 09:30:39 +0100
committerMartin Kosek <mkosek@redhat.com>2012-02-24 09:40:43 +0100
commit860579022532ee4133fc74e8f916cb40dc3ea239 (patch)
tree475fa305e89561b10fcd3523d34acd7e8b981f5a /ipalib
parent2cf58937615c28527d1c78f883dad8726331c6df (diff)
downloadfreeipa-860579022532ee4133fc74e8f916cb40dc3ea239.tar.gz
freeipa-860579022532ee4133fc74e8f916cb40dc3ea239.tar.xz
freeipa-860579022532ee4133fc74e8f916cb40dc3ea239.zip
Query and transfer ACLs for DNS zones
Provide a way to specify BIND allow-query and allow-transfer ACLs for DNS zones. IMPORTANT: new bind-dyndb-ldap adds a zone transfer ability. To avoid zone information leaks to unintended places, allow-transfer ACL for every zone is by default set to none and has to be explicitly enabled by an Administrator. This is done both for new DNS zones and old DNS zones during RPM update via new DNS upgrade plugin. https://fedorahosted.org/freeipa/ticket/1211
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/plugins/dns.py87
1 files changed, 85 insertions, 2 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index 495a21b1d..0b54aae04 100644
--- a/ipalib/plugins/dns.py
+++ b/ipalib/plugins/dns.py
@@ -30,7 +30,7 @@ from ipalib.plugins.baseldap import *
from ipalib import _, ngettext
from ipalib.util import validate_zonemgr, normalize_zonemgr, validate_hostname
from ipapython import dnsclient
-from ipapython.ipautil import valid_ip
+from ipapython.ipautil import valid_ip, CheckedIPAddress
from ldap import explode_dn
__doc__ = _("""
@@ -48,6 +48,9 @@ EXAMPLES:
ipa dnszone-mod example.com --dynamic-update=TRUE \\
--update-policy="grant EXAMPLE.COM krb5-self * A; grant EXAMPLE.COM krb5-self * AAAA;"
+ Modify the zone to allow zone transfers for local network only:
+ ipa dnszone-mod example.com --allow-transfer=10.0.0.0/8
+
Add new reverse zone specified by network IP address:
ipa dnszone-add --name-from-ip=80.142.15.0/24 \\
--name-server=nameserver.example.com
@@ -225,6 +228,68 @@ def _validate_ipnet(ugettext, ipnet):
return _('invalid IP network format')
return None
+def _validate_bind_aci(ugettext, bind_acis):
+ if not bind_acis:
+ return
+
+ bind_acis = bind_acis.split(';')
+ if bind_acis[-1]:
+ return _('each ACL element must be terminated with a semicolon')
+ else:
+ bind_acis.pop(-1)
+
+ for bind_aci in bind_acis:
+ if bind_aci in ("any", "none"):
+ continue
+
+ if bind_aci in ("localhost", "localnets"):
+ return _('ACL name "%s" is not supported') % bind_aci
+
+ if bind_aci.startswith('!'):
+ bind_aci = bind_aci[1:]
+
+ try:
+ ip = CheckedIPAddress(bind_aci, parse_netmask=True,
+ allow_network=True)
+ except (netaddr.AddrFormatError, ValueError), e:
+ return unicode(e)
+ except UnboundLocalError:
+ return _(u"invalid address format")
+
+def _normalize_bind_aci(bind_acis):
+ if not bind_acis:
+ return
+ bind_acis = bind_acis.split(';')
+ normalized = []
+ for bind_aci in bind_acis:
+ if not bind_aci:
+ continue
+ if bind_aci in ("any", "none", "localhost", "localnets"):
+ normalized.append(bind_aci)
+ continue
+
+ prefix = ""
+ if bind_aci.startswith('!'):
+ bind_aci = bind_aci[1:]
+ prefix = "!"
+
+ try:
+ ip = CheckedIPAddress(bind_aci, parse_netmask=True,
+ allow_network=True)
+ if '/' in bind_aci: # addr with netmask
+ netmask = "/%s" % ip.prefixlen
+ else:
+ netmask = ""
+ normalized.append(u"%s%s%s" % (prefix, str(ip), netmask))
+ continue
+ except:
+ normalized.append(bind_aci)
+ continue
+
+ acis = u';'.join(normalized)
+ acis += u';'
+ return acis
+
def _domain_name_validator(ugettext, value):
try:
# Allow domain name which is not fully qualified. These are supported
@@ -1150,7 +1215,7 @@ class dnszone(LDAPObject):
default_attributes = [
'idnsname', 'idnszoneactive', 'idnssoamname', 'idnssoarname',
'idnssoaserial', 'idnssoarefresh', 'idnssoaretry', 'idnssoaexpire',
- 'idnssoaminimum'
+ 'idnssoaminimum', 'idnsallowquery', 'idnsallowtransfer'
] + _record_attributes
label = _('DNS Zones')
label_singular = _('DNS Zone')
@@ -1254,6 +1319,24 @@ class dnszone(LDAPObject):
default=False,
autofill=True
),
+ Str('idnsallowquery?',
+ _validate_bind_aci,
+ normalizer=_normalize_bind_aci,
+ cli_name='allow_query',
+ label=_('Allow query'),
+ doc=_('Semicolon separated list of IP addresses or networks which are allowed to issue queries'),
+ default=u'any;', # anyone can issue queries by default
+ autofill=True,
+ ),
+ Str('idnsallowtransfer?',
+ _validate_bind_aci,
+ normalizer=_normalize_bind_aci,
+ cli_name='allow_transfer',
+ label=_('Allow transfer'),
+ doc=_('Semicolon separated list of IP addresses or networks which are allowed to transfer the zone'),
+ default=u'none;', # no one can issue queries by default
+ autofill=True,
+ ),
)
api.register(dnszone)