mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
DNSSEC: fix DS record validation
Part of: https://fedorahosted.org/freeipa/ticket/3801 Reviewed-By: Petr Spacek <pspacek@redhat.com> Reviewed-By: Martin Kosek <mkosek@redhat.com>
This commit is contained in:
parent
78b2a7abbb
commit
734883282e
@ -2601,6 +2601,14 @@ class dnsrecord(LDAPObject):
|
|||||||
doc=_('Parse all raw DNS records and return them in a structured way'),
|
doc=_('Parse all raw DNS records and return them in a structured way'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _dsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||||
|
assert isinstance(dn, DN)
|
||||||
|
dsrecords = entry_attrs.get('dsrecord')
|
||||||
|
if dsrecords and self.is_pkey_zone_record(*keys):
|
||||||
|
raise errors.ValidationError(
|
||||||
|
name='dsrecord',
|
||||||
|
error=unicode(_('DS record must not be in zone apex (RFC 4035 section 2.4)')))
|
||||||
|
|
||||||
def _nsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
def _nsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||||
assert isinstance(dn, DN)
|
assert isinstance(dn, DN)
|
||||||
nsrecords = entry_attrs.get('nsrecord')
|
nsrecords = entry_attrs.get('nsrecord')
|
||||||
@ -2846,8 +2854,9 @@ class dnsrecord(LDAPObject):
|
|||||||
processed.append(rrparam.name)
|
processed.append(rrparam.name)
|
||||||
yield rrparam
|
yield rrparam
|
||||||
|
|
||||||
def check_record_type_collisions(self, keys, old_entry, entry_attrs):
|
def updated_rrattrs(self, old_entry, entry_attrs):
|
||||||
# Test that only allowed combination of record types was created
|
"""Returns updated RR attributes
|
||||||
|
"""
|
||||||
rrattrs = {}
|
rrattrs = {}
|
||||||
if old_entry is not None:
|
if old_entry is not None:
|
||||||
old_rrattrs = dict((key, value) for key, value in old_entry.iteritems()
|
old_rrattrs = dict((key, value) for key, value in old_entry.iteritems()
|
||||||
@ -2858,42 +2867,53 @@ class dnsrecord(LDAPObject):
|
|||||||
if key in self.params and
|
if key in self.params and
|
||||||
isinstance(self.params[key], DNSRecord))
|
isinstance(self.params[key], DNSRecord))
|
||||||
rrattrs.update(new_rrattrs)
|
rrattrs.update(new_rrattrs)
|
||||||
|
return rrattrs
|
||||||
|
|
||||||
|
def check_record_type_collisions(self, keys, rrattrs):
|
||||||
|
# Test that only allowed combination of record types was created
|
||||||
|
|
||||||
# CNAME record validation
|
# CNAME record validation
|
||||||
try:
|
cnames = rrattrs.get('cnamerecord')
|
||||||
cnames = rrattrs['cnamerecord']
|
if cnames is not None:
|
||||||
except KeyError:
|
if len(cnames) > 1:
|
||||||
pass
|
raise errors.ValidationError(name='cnamerecord',
|
||||||
else:
|
error=_('only one CNAME record is allowed per name '
|
||||||
if cnames is not None:
|
'(RFC 2136, section 1.1.5)'))
|
||||||
if len(cnames) > 1:
|
if any(rrvalue is not None
|
||||||
raise errors.ValidationError(name='cnamerecord',
|
and rrattr != 'cnamerecord'
|
||||||
error=_('only one CNAME record is allowed per name '
|
for rrattr, rrvalue in rrattrs.iteritems()):
|
||||||
'(RFC 2136, section 1.1.5)'))
|
raise errors.ValidationError(name='cnamerecord',
|
||||||
if any(rrvalue is not None
|
error=_('CNAME record is not allowed to coexist '
|
||||||
and rrattr != 'cnamerecord'
|
'with any other record (RFC 1034, section 3.6.2)'))
|
||||||
for rrattr, rrvalue in rrattrs.iteritems()):
|
|
||||||
raise errors.ValidationError(name='cnamerecord',
|
|
||||||
error=_('CNAME record is not allowed to coexist '
|
|
||||||
'with any other record (RFC 1034, section 3.6.2)'))
|
|
||||||
|
|
||||||
# DNAME record validation
|
# DNAME record validation
|
||||||
try:
|
dnames = rrattrs.get('dnamerecord')
|
||||||
dnames = rrattrs['dnamerecord']
|
if dnames is not None:
|
||||||
except KeyError:
|
if len(dnames) > 1:
|
||||||
pass
|
raise errors.ValidationError(name='dnamerecord',
|
||||||
else:
|
error=_('only one DNAME record is allowed per name '
|
||||||
if dnames is not None:
|
'(RFC 6672, section 2.4)'))
|
||||||
if len(dnames) > 1:
|
# DNAME must not coexist with CNAME, but this is already checked earlier
|
||||||
raise errors.ValidationError(name='dnamerecord',
|
if rrattrs.get('nsrecord') and not keys[1].is_empty():
|
||||||
error=_('only one DNAME record is allowed per name '
|
raise errors.ValidationError(name='dnamerecord',
|
||||||
'(RFC 6672, section 2.4)'))
|
error=_('DNAME record is not allowed to coexist with an '
|
||||||
# DNAME must not coexist with CNAME, but this is already checked earlier
|
'NS record except when located in a zone root '
|
||||||
if rrattrs.get('nsrecord') and not keys[1].is_empty():
|
'record (RFC 6672, section 2.3)'))
|
||||||
raise errors.ValidationError(name='dnamerecord',
|
|
||||||
error=_('DNAME record is not allowed to coexist with an '
|
def check_record_type_dependencies(self, keys, rrattrs):
|
||||||
'NS record except when located in a zone root '
|
# Test that all record type dependencies are satisfied
|
||||||
'record (RFC 6672, section 2.3)'))
|
|
||||||
|
# DS record validation
|
||||||
|
# DS record requires to coexists with NS record
|
||||||
|
dsrecords = rrattrs.get('dsrecord')
|
||||||
|
nsrecords = rrattrs.get('nsrecord')
|
||||||
|
# DS record cannot be in zone apex, checked in pre-callback validators
|
||||||
|
if dsrecords and not nsrecords:
|
||||||
|
raise errors.ValidationError(
|
||||||
|
name='dsrecord',
|
||||||
|
error=_('DS record requires to coexist with an '
|
||||||
|
'NS record (RFC 4592 section 4.6, RFC 4035 section 2.4)'))
|
||||||
|
|
||||||
|
|
||||||
def _entry2rrsets(self, entry_attrs, dns_name, dns_domain):
|
def _entry2rrsets(self, entry_attrs, dns_name, dns_domain):
|
||||||
'''Convert entry_attrs to a dictionary {rdtype: rrset}.
|
'''Convert entry_attrs to a dictionary {rdtype: rrset}.
|
||||||
@ -3238,7 +3258,9 @@ class dnsrecord_add(LDAPCreate):
|
|||||||
vals = list(entry_attrs[attr])
|
vals = list(entry_attrs[attr])
|
||||||
entry_attrs[attr] = list(set(old_entry.get(attr, []) + vals))
|
entry_attrs[attr] = list(set(old_entry.get(attr, []) + vals))
|
||||||
|
|
||||||
self.obj.check_record_type_collisions(keys, old_entry, entry_attrs)
|
rrattrs = self.obj.updated_rrattrs(old_entry, entry_attrs)
|
||||||
|
self.obj.check_record_type_dependencies(keys, rrattrs)
|
||||||
|
self.obj.check_record_type_collisions(keys, rrattrs)
|
||||||
context.dnsrecord_entry_mods = getattr(context, 'dnsrecord_entry_mods',
|
context.dnsrecord_entry_mods = getattr(context, 'dnsrecord_entry_mods',
|
||||||
{})
|
{})
|
||||||
context.dnsrecord_entry_mods[(keys[0], keys[1])] = entry_attrs.copy()
|
context.dnsrecord_entry_mods[(keys[0], keys[1])] = entry_attrs.copy()
|
||||||
@ -3346,7 +3368,9 @@ class dnsrecord_mod(LDAPUpdate):
|
|||||||
new_dnsvalue = [param._convert_scalar(modified_parts)]
|
new_dnsvalue = [param._convert_scalar(modified_parts)]
|
||||||
entry_attrs[attr] = list(set(old_entry[attr] + new_dnsvalue))
|
entry_attrs[attr] = list(set(old_entry[attr] + new_dnsvalue))
|
||||||
|
|
||||||
self.obj.check_record_type_collisions(keys, old_entry, entry_attrs)
|
rrattrs = self.obj.updated_rrattrs(old_entry, entry_attrs)
|
||||||
|
self.obj.check_record_type_dependencies(keys, rrattrs)
|
||||||
|
self.obj.check_record_type_collisions(keys, rrattrs)
|
||||||
|
|
||||||
context.dnsrecord_entry_mods = getattr(context, 'dnsrecord_entry_mods',
|
context.dnsrecord_entry_mods = getattr(context, 'dnsrecord_entry_mods',
|
||||||
{})
|
{})
|
||||||
@ -3518,6 +3542,9 @@ class dnsrecord_del(LDAPUpdate):
|
|||||||
raise errors.AttrValueNotFound(attr=attr_name, value=val)
|
raise errors.AttrValueNotFound(attr=attr_name, value=val)
|
||||||
entry_attrs[attr] = list(set(old_entry[attr]))
|
entry_attrs[attr] = list(set(old_entry[attr]))
|
||||||
|
|
||||||
|
rrattrs = self.obj.updated_rrattrs(old_entry, entry_attrs)
|
||||||
|
self.obj.check_record_type_dependencies(keys, rrattrs)
|
||||||
|
|
||||||
del_all = False
|
del_all = False
|
||||||
if not self.obj.is_pkey_zone_record(*keys):
|
if not self.obj.is_pkey_zone_record(*keys):
|
||||||
record_found = False
|
record_found = False
|
||||||
|
Loading…
Reference in New Issue
Block a user