summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Kosek <mkosek@redhat.com>2013-04-02 11:59:16 +0200
committerMartin Kosek <mkosek@redhat.com>2013-04-02 17:11:57 +0200
commit30a1bc1f0959e2b89f00a0b4cd661778a0625a89 (patch)
treebdc6522c5a28a60a21665f5040e3388eac4f5aff
parent42c401a87795fe3a2067155460ae276ad2d3e360 (diff)
downloadfreeipa.git-30a1bc1f0959e2b89f00a0b4cd661778a0625a89.tar.gz
freeipa.git-30a1bc1f0959e2b89f00a0b4cd661778a0625a89.tar.xz
freeipa.git-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.py24
-rw-r--r--tests/test_xmlrpc/test_dns_plugin.py90
2 files changed, 102 insertions, 12 deletions
diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py
index 7d995650..3e6ed835 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 2e7d5466..fb548bb9 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',