]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
API: Auth: forbid mixing CNAME and other RRsets 5389/head
authorChristian Hofstaedtler <christian.hofstaedtler@deduktiva.com>
Sun, 11 Jun 2017 20:37:37 +0000 (22:37 +0200)
committerChristian Hofstaedtler <christian.hofstaedtler@deduktiva.com>
Sun, 11 Jun 2017 20:37:37 +0000 (22:37 +0200)
Fixes #5305.

pdns/ws-auth.cc
regression-tests.api/test_Zones.py

index 2129964dc5919575f85445c094075391f396a984..d9402ba0883716d5f3da9f442d71fa52fb201c52 100644 (file)
@@ -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.");
           }
index 11fb3cc441765b6b688e2f0bb3d68a4d141e7043..24d511797239b68423c2545ab3e40097ddededfb 100644 (file)
@@ -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()