From: Christian Hofstaedtler Date: Sun, 11 Jun 2017 20:37:37 +0000 (+0200) Subject: API: Auth: forbid mixing CNAME and other RRsets X-Git-Tag: rec-4.1.0-alpha1~81^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8560f36a38379d5c1529a05320f749f665bd77d0;p=thirdparty%2Fpdns.git API: Auth: forbid mixing CNAME and other RRsets Fixes #5305. --- diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index 2129964dc5..d9402ba088 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -1436,6 +1436,16 @@ static void patchZone(HttpRequest* req, HttpResponse* resp) { } if (replace_records) { + di.backend->lookup(QType(QType::ANY), qname); + DNSResourceRecord rr; + while (di.backend->get(rr)) { + if (qtype.getCode() == QType::CNAME && rr.qtype.getCode() != QType::CNAME) { + throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName()+": Conflicts with pre-existing non-CNAME RRset"); + } else if (qtype.getCode() != QType::CNAME && rr.qtype.getCode() == QType::CNAME) { + throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName()+": Conflicts with pre-existing CNAME RRset"); + } + } + if (!di.backend->replaceRRSet(di.id, qname, qtype, new_records)) { throw ApiException("Hosting backend does not support editing records."); } diff --git a/regression-tests.api/test_Zones.py b/regression-tests.api/test_Zones.py index 11fb3cc441..24d5117972 100644 --- a/regression-tests.api/test_Zones.py +++ b/regression-tests.api/test_Zones.py @@ -918,6 +918,62 @@ fred IN A 192.168.0.4 self.assertEquals(r.status_code, 422) self.assertIn('unknown type', r.json()['error']) + def test_rrset_cname_and_other(self): + name, payload, zone = self.create_zone() + rrset = { + 'changetype': 'replace', + 'name': name, + 'type': 'CNAME', + 'ttl': 3600, + 'records': [ + { + "content": "example.org.", + "disabled": False + } + ] + } + payload = {'rrsets': [rrset]} + r = self.session.patch(self.url("/api/v1/servers/localhost/zones/" + name), data=json.dumps(payload), + headers={'content-type': 'application/json'}) + self.assertEquals(r.status_code, 422) + self.assertIn('Conflicts with pre-existing non-CNAME RRset', r.json()['error']) + + def test_rrset_other_and_cname(self): + name, payload, zone = self.create_zone() + rrset = { + 'changetype': 'replace', + 'name': 'sub.'+name, + 'type': 'CNAME', + 'ttl': 3600, + 'records': [ + { + "content": "example.org.", + "disabled": False + } + ] + } + payload = {'rrsets': [rrset]} + r = self.session.patch(self.url("/api/v1/servers/localhost/zones/" + name), data=json.dumps(payload), + headers={'content-type': 'application/json'}) + self.assert_success(r) + rrset = { + 'changetype': 'replace', + 'name': 'sub.'+name, + 'type': 'A', + 'ttl': 3600, + 'records': [ + { + "content": "1.2.3.4", + "disabled": False + } + ] + } + payload = {'rrsets': [rrset]} + r = self.session.patch(self.url("/api/v1/servers/localhost/zones/" + name), data=json.dumps(payload), + headers={'content-type': 'application/json'}) + self.assertEquals(r.status_code, 422) + self.assertIn('Conflicts with pre-existing CNAME RRset', r.json()['error']) + def test_create_zone_with_leading_space(self): # Actual regression. name, payload, zone = self.create_zone()