From df13cdcb974e9f8b161be35fcef9651c2ffe0b5e Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Mon, 2 Apr 2012 14:57:33 +0200 Subject: Forbid public access to DNS tree With a publicly accessible DNS tree in LDAP, anyone with an access to the LDAP server can get all DNS data as with a zone transfer which is already restricted with ACL. Making DNS tree not readable to public is a common security practice and should be applied in FreeIPA as well. This patch adds a new deny rule to forbid access to DNS tree to users or hosts without an appropriate permission or users which are not members of admins group. The new permission/aci is applied both for new installs and upgraded servers. bind-dyndb-ldap plugin is allowed to read DNS tree without any change because its principal is already a member of "DNS Servers" privilege. https://fedorahosted.org/freeipa/ticket/2569 --- install/share/dns.ldif | 12 ++++++++ ipaserver/install/plugins/dns.py | 59 ++++++++++++++++++++++++++++++---------- 2 files changed, 56 insertions(+), 15 deletions(-) diff --git a/install/share/dns.ldif b/install/share/dns.ldif index 3fd8cfb87..a8d27788a 100644 --- a/install/share/dns.ldif +++ b/install/share/dns.ldif @@ -4,6 +4,7 @@ objectClass: idnsConfigObject objectClass: nsContainer objectClass: top cn: dns +aci: (targetattr = "*")(version 3.0; acl "No access to DNS tree without a permission"; deny (read,search,compare) (groupdn != "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX") and (groupdn != "ldap:///cn=read dns entries,cn=permissions,cn=pbac,$SUFFIX");) dn: $SUFFIX changetype: modify @@ -56,6 +57,17 @@ description: Update DNS entries member: cn=DNS Administrators,cn=privileges,cn=pbac,$SUFFIX member: cn=DNS Servers,cn=privileges,cn=pbac,$SUFFIX +dn: cn=read dns entries,cn=permissions,cn=pbac,$SUFFIX +changetype: add +objectClass: top +objectClass: groupofnames +objectClass: ipapermission +cn: read dns entries +description: Read DNS entries +ipapermissiontype: SYSTEM +member: cn=DNS Administrators,cn=privileges,cn=pbac,$SUFFIX +member: cn=DNS Servers,cn=privileges,cn=pbac,$SUFFIX + dn: cn=Write DNS Configuration,cn=permissions,cn=pbac,$SUFFIX changetype: add objectClass: groupofnames diff --git a/ipaserver/install/plugins/dns.py b/ipaserver/install/plugins/dns.py index 84b7b23a5..a9846fa84 100644 --- a/ipaserver/install/plugins/dns.py +++ b/ipaserver/install/plugins/dns.py @@ -87,6 +87,39 @@ class update_dns_permissions(PostUpdate): enabled DNS. LDIF loaded by DNS installer would fail because of duplicate entries otherwise. """ + + _write_dns_perm_dn = DN('cn=Write DNS Configuration', + api.env.container_permission, + api.env.basedn) + _write_dns_perm_entry = ['objectClass:groupofnames', + 'objectClass:top', + 'cn:Write DNS Configuration', + 'description:Write DNS Configuration', + 'member:cn=DNS Administrators,cn=privileges,cn=pbac,%s' \ + % api.env.basedn, + 'member:cn=DNS Servers,cn=privileges,cn=pbac,%s' \ + % api.env.basedn] + + _read_dns_perm_dn = DN('cn=read dns entries', + api.env.container_permission, + api.env.basedn) + _read_dns_perm_entry = ['objectClass:top', + 'objectClass:groupofnames', + 'objectClass:ipapermission', + 'cn:read dns entries', + 'description:Read DNS entries', + 'ipapermissiontype:SYSTEM', + 'member:cn=DNS Administrators,cn=privileges,cn=pbac,%s' \ + % api.env.basedn, + 'member:cn=DNS Servers,cn=privileges,cn=pbac,%s' \ + % api.env.basedn,] + + _write_dns_aci_dn = DN(api.env.basedn) + _write_dns_aci_entry = ['add:aci:\'(targetattr = "idnsforwardpolicy || idnsforwarders || idnsallowsyncptr || idnszonerefresh || idnspersistentsearch")(target = "ldap:///cn=dns,%(realm)s")(version 3.0;acl "permission:Write DNS Configuration";allow (write) groupdn = "ldap:///cn=Write DNS Configuration,cn=permissions,cn=pbac,%(realm)s";)\'' % dict(realm=api.env.basedn)] + + _read_dns_aci_dn = DN(api.env.container_dns, api.env.basedn) + _read_dns_aci_entry = ['add:aci:\'(targetattr = "*")(version 3.0; acl "No access to DNS tree without a permission"; deny (read,search,compare) (groupdn != "ldap:///cn=admins,cn=groups,cn=accounts,%(realm)s") and (groupdn != "ldap:///cn=read dns entries,cn=permissions,cn=pbac,%(realm)s");)\'' % dict(realm=api.env.basedn) ] + def execute(self, **options): ldap = self.obj.backend @@ -94,21 +127,17 @@ class update_dns_permissions(PostUpdate): return (False, False, []) dnsupdates = {} - dn = str(DN('cn=Write DNS Configuration', api.env.container_permission, api.env.basedn)) - entry = ['objectClass:groupofnames', - 'objectClass:top', - 'cn:Write DNS Configuration', - 'description:Write DNS Configuration', - 'member:cn=DNS Administrators,cn=privileges,cn=pbac,%s' % api.env.basedn, - 'member:cn=DNS Servers,cn=privileges,cn=pbac,%s' % api.env.basedn] - # make sure everything is str or otherwise python-ldap will complain - entry = map(str, entry) - dnsupdates[dn] = {'dn' : str(dn), 'default' : entry} - - dn = str(DN(api.env.basedn)) - entry = ['add:aci:\'(targetattr = "idnsforwardpolicy || idnsforwarders || idnsallowsyncptr || idnszonerefresh || idnspersistentsearch")(target = "ldap:///cn=dns,%(realm)s")(version 3.0;acl "permission:Write DNS Configuration";allow (write) groupdn = "ldap:///cn=Write DNS Configuration,cn=permissions,cn=pbac,%(realm)s";)\'' % dict(realm=api.env.basedn)] - entry = map(str, entry) - dnsupdates[dn] = {'dn' : dn, 'updates' : entry} + + # add default and updated entries + for dn, container, entry in ((self._write_dns_perm_dn, 'default', self._write_dns_perm_entry), + (self._read_dns_perm_dn, 'default', self._read_dns_perm_entry), + (self._write_dns_aci_dn, 'updates', self._write_dns_aci_entry), + (self._read_dns_aci_dn, 'updates', self._read_dns_aci_entry)): + + dn = str(dn) + # make sure everything is str or otherwise python-ldap would complain + entry = map(str, entry) + dnsupdates[dn] = {'dn' : dn, container : entry} return (False, True, [dnsupdates]) -- cgit