From: Charles-Henri Bruyand Date: Thu, 23 Aug 2018 09:11:10 +0000 (+0200) Subject: auth: api - Check if the DNSNames that should be hostnames, are hostnames X-Git-Tag: auth-4.2.0-alpha1~48^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=819509305906d366b722f07b785ef8e33090f865;p=thirdparty%2Fpdns.git auth: api - Check if the DNSNames that should be hostnames, are hostnames --- diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index 1df76b1668..6d16b591a9 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -1723,6 +1723,31 @@ static void patchZone(HttpRequest* req, HttpResponse* resp) { if (rr.qtype.getCode() == QType::SOA && rr.qname==zonename) { soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind); } + + // Check if the DNSNames that should be hostnames, are hostnames + if (rr.qtype.getCode() == QType::NS || rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) { + DNSName toCheck; + if (rr.qtype.getCode() == QType::SRV) { + vector parts; + stringtok(parts, rr.getZoneRepresentation()); + if (parts.size() == 4) toCheck = DNSName(parts[3]); + } else if (rr.qtype.getCode() == QType::MX) { + vector parts; + stringtok(parts, rr.getZoneRepresentation()); + if (parts.size() == 2) toCheck = DNSName(parts[1]); + } else { + toCheck = DNSName(rr.content); + } + + if (toCheck.empty()) { + throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName() + " unable to extract hostname from content."); + } + else if ((rr.qtype.getCode() == QType::MX || rr.qtype.getCode() == QType::SRV) && toCheck == g_rootdnsname) { + // allow null MX/SRV + } else if(!toCheck.isHostname()) { + throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName() + " record has non-hostname content '" + toCheck.toString() + "'."); + } + } } checkDuplicateRecords(new_records); } diff --git a/regression-tests.api/test_Zones.py b/regression-tests.api/test_Zones.py index ef481ffeda..6081cc52f9 100644 --- a/regression-tests.api/test_Zones.py +++ b/regression-tests.api/test_Zones.py @@ -985,6 +985,31 @@ fred IN A 192.168.0.4 data = self.session.get(self.url("/api/v1/servers/localhost/zones/" + name)).json() self.assertEquals(get_rrset(data, name, 'MX')['records'], rrset['records']) + def test_zone_rr_update_invalid_mx(self): + name, payload, zone = self.create_zone() + # do a replace (= update) + rrset = { + 'changetype': 'replace', + 'name': name, + 'type': 'MX', + 'ttl': 3600, + 'records': [ + { + "content": "10 mail@mx.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('record has non-hostname content', r.json()['error']) + data = self.session.get(self.url("/api/v1/servers/localhost/zones/" + name)).json() + self.assertIsNone(get_rrset(data, name, 'MX')) + def test_zone_rr_update_opt(self): name, payload, zone = self.create_zone() # do a replace (= update)