diff options
author | Martin Kosek <mkosek@redhat.com> | 2013-04-02 11:59:16 +0200 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2013-04-02 17:11:57 +0200 |
commit | 30a1bc1f0959e2b89f00a0b4cd661778a0625a89 (patch) | |
tree | bdc6522c5a28a60a21665f5040e3388eac4f5aff | |
parent | 42c401a87795fe3a2067155460ae276ad2d3e360 (diff) | |
download | freeipa-30a1bc1f0959e2b89f00a0b4cd661778a0625a89.tar.gz freeipa-30a1bc1f0959e2b89f00a0b4cd661778a0625a89.tar.xz freeipa-30a1bc1f0959e2b89f00a0b4cd661778a0625a89.zip |
Improve DNAME record validation
Extend DNS RR conflict check and forbid DNAME+NS combination unless
it is done in root DNS zone record.
Add tests to verify this enforced check.
https://fedorahosted.org/freeipa/ticket/3449
-rw-r--r-- | ipalib/plugins/dns.py | 24 | ||||
-rw-r--r-- | tests/test_xmlrpc/test_dns_plugin.py | 90 |
2 files changed, 102 insertions, 12 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py index 7d9956504..3e6ed8357 100644 --- a/ipalib/plugins/dns.py +++ b/ipalib/plugins/dns.py @@ -2267,7 +2267,7 @@ class dnsrecord(LDAPObject): processed.append(rrparam.name) yield rrparam - def check_record_type_collisions(self, old_entry, entry_attrs): + def check_record_type_collisions(self, keys, old_entry, entry_attrs): # Test that only allowed combination of record types was created rrattrs = {} if old_entry is not None: @@ -2298,6 +2298,24 @@ class dnsrecord(LDAPObject): error=_('CNAME record is not allowed to coexist ' 'with any other record (RFC 1034, section 3.6.2)')) + # DNAME record validation + try: + dnames = rrattrs['dnamerecord'] + except KeyError: + pass + else: + if dnames is not None: + if len(dnames) > 1: + raise errors.ValidationError(name='dnamerecord', + error=_('only one DNAME record is allowed per name ' + '(RFC 6672, section 2.4)')) + # DNAME must not coexist with CNAME, but this is already checked earlier + if rrattrs.get('nsrecord') and keys[1] != _dns_zone_record: + raise errors.ValidationError(name='dnamerecord', + error=_('DNAME record is not allowed to coexist with an ' + 'NS record except when located in a zone root ' + 'record (RFC 6672, section 2.3)')) + api.register(dnsrecord) @@ -2459,7 +2477,7 @@ class dnsrecord_add(LDAPCreate): vals = list(entry_attrs[attr]) entry_attrs[attr] = list(set(old_entry.get(attr, []) + vals)) - self.obj.check_record_type_collisions(old_entry, entry_attrs) + self.obj.check_record_type_collisions(keys, old_entry, entry_attrs) return dn def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -2560,7 +2578,7 @@ class dnsrecord_mod(LDAPUpdate): new_dnsvalue = [param._convert_scalar(modified_parts)] entry_attrs[attr] = list(set(old_entry[attr] + new_dnsvalue)) - self.obj.check_record_type_collisions(old_entry, entry_attrs) + self.obj.check_record_type_collisions(keys, old_entry, entry_attrs) return dn def execute(self, *keys, **options): diff --git a/tests/test_xmlrpc/test_dns_plugin.py b/tests/test_xmlrpc/test_dns_plugin.py index 2e7d5466a..fb548bb97 100644 --- a/tests/test_xmlrpc/test_dns_plugin.py +++ b/tests/test_xmlrpc/test_dns_plugin.py @@ -53,6 +53,8 @@ dnsrev2 = u'81' dnsrev2_dn = DN(('idnsname',dnsrev2), revdnszone1_dn) dnsrescname = u'testcnamerec' dnsrescname_dn = DN(('idnsname',dnsrescname), dnszone1_dn) +dnsresdname = u'testdns-dname' +dnsresdname_dn = DN(('idnsname',dnsresdname), dnszone1_dn) class test_dns(Declarative): @@ -223,15 +225,6 @@ class test_dns(Declarative): }, ), - dict( - desc='Delete zone %r' % dnszone2, - command=('dnszone_del', [dnszone2], {}), - expected={ - 'value': dnszone2, - 'summary': None, - 'result': {'failed': u''}, - }, - ), dict( desc='Retrieve zone %r' % dnszone1, @@ -839,6 +832,85 @@ class test_dns(Declarative): ), dict( + desc='Try to add multiple DNAME records to %r using dnsrecord_add' % (dnsresdname), + command=('dnsrecord_add', [dnszone1, dnsres1], {'dnamerecord': + [u'foo-1.example.com.', u'foo-2.example.com.']}), + expected=errors.ValidationError(name='dnamerecord', + error=u'only one DNAME record is allowed per name (RFC 6672, section 2.4)'), + ), + + dict( + desc='Try to add invalid DNAME record %r using dnsrecord_add' % (dnsresdname), + command=('dnsrecord_add', [dnszone1, dnsresdname], {'dnamerecord': u'-.example.com.'}), + expected=errors.ValidationError(name='target', + error=u'invalid domain-name: only letters, numbers, and - ' + + u'are allowed. DNS label may not start or end with -'), + ), + + dict( + desc='Add DNAME record to %r using dnsrecord_add' % (dnsresdname), + command=('dnsrecord_add', [dnszone1, dnsresdname], + {'dnamerecord': u'd.example.com.', 'arecord': u'10.0.0.1'}), + expected={ + 'value': dnsresdname, + 'summary': None, + 'result': { + 'objectclass': objectclasses.dnsrecord, + 'dn': dnsresdname_dn, + 'idnsname': [dnsresdname], + 'dnamerecord': [u'd.example.com.'], + 'arecord': [u'10.0.0.1'], + }, + }, + ), + + dict( + desc='Try to add CNAME record to %r using dnsrecord_add' % (dnsresdname), + command=('dnsrecord_add', [dnszone1, dnsresdname], {'cnamerecord': u'foo-1.example.com.'}), + expected=errors.ValidationError(name='cnamerecord', + error=u'CNAME record is not allowed to coexist with any other ' + u'record (RFC 1034, section 3.6.2)'), + ), + + dict( + desc='Try to add NS record to %r using dnsrecord_add' % (dnsresdname), + command=('dnsrecord_add', [dnszone1, dnsresdname], + {'nsrecord': u'%s.%s.' % (dnsres1, dnszone1)}), + expected=errors.ValidationError(name='dnamerecord', + error=u'DNAME record is not allowed to coexist with an NS ' + u'record except when located in a zone root record (RFC 6672, section 2.3)'), + ), + + dict( + desc='Add NS+DNAME record to %r zone record using dnsrecord_add' % (dnszone2), + command=('dnsrecord_add', [dnszone2, u'@'], + {'dnamerecord': u'd.example.com.', + 'nsrecord': dnszone1_mname}), + expected = { + 'value': u'@', + 'summary': None, + 'result': { + 'objectclass': objectclasses.dnszone, + 'dnamerecord': [u'd.example.com.'], + 'dn': dnszone2_dn, + 'nsrecord': [dnszone2_mname, dnszone1_mname], + 'idnsname': [u'@'] + } + }, + ), + + + dict( + desc='Delete zone %r' % dnszone2, + command=('dnszone_del', [dnszone2], {}), + expected={ + 'value': dnszone2, + 'summary': None, + 'result': {'failed': u''}, + }, + ), + + dict( desc='Try to add invalid KX record %r using dnsrecord_add' % (dnsres1), command=('dnsrecord_add', [dnszone1, dnsres1], {'kxrecord': u'foo-1.example.com' }), expected=errors.ValidationError(name='kx_rec', |