From 1e5b9ab91512cfc71d1714185cc80bf8ba69fca9 Mon Sep 17 00:00:00 2001 From: Christian Hofstaedtler Date: Sat, 7 Feb 2015 13:58:08 +0100 Subject: [PATCH] API: be more strict when parsing record contents Fixes #2113. --- pdns/ws-auth.cc | 13 ++++++++++++- regression-tests.api/test_Zones.py | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index d3f63a2b3..67edd8ef7 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -403,10 +403,21 @@ static void gatherRecords(const Value& container, vector& new try { shared_ptr drc(DNSRecordContent::mastermake(rr.qtype.getCode(), 1, rr.content)); string tmp = drc->serialize(rr.qname); + if (rr.qtype.getCode() != QType::AAAA) { + tmp = drc->getZoneRepresentation(); + if (!pdns_iequals(tmp, rr.content)) { + throw std::runtime_error("Not in expected format (parsed as '"+tmp+"')"); + } + } else { + struct in6_addr tmpbuf; + if (inet_pton(AF_INET6, rr.content.c_str(), &tmpbuf) != 1 || rr.content.find('.') != string::npos) { + throw std::runtime_error("Invalid IPv6 address"); + } + } } catch(std::exception& e) { - throw ApiException("Record "+rr.qname+"/"+rr.qtype.getName()+" "+rr.content+": "+e.what()); + throw ApiException("Record "+rr.qname+"/"+rr.qtype.getName()+" '"+rr.content+"': "+e.what()); } if ((rr.qtype.getCode() == QType::A || rr.qtype.getCode() == QType::AAAA) && diff --git a/regression-tests.api/test_Zones.py b/regression-tests.api/test_Zones.py index f05117efc..a9a153dbf 100644 --- a/regression-tests.api/test_Zones.py +++ b/regression-tests.api/test_Zones.py @@ -727,6 +727,30 @@ fred IN A 192.168.0.4 self.assertEquals(r.status_code, 422) self.assertIn('unknown type', r.json()['error']) + def test_create_zone_with_leading_space(self): + # Actual regression. + payload, zone = self.create_zone() + name = payload['name'] + rrset = { + 'changetype': 'replace', + 'name': name, + 'type': 'A', + 'records': [ + { + "name": name, + "type": "A", + "ttl": 3600, + "content": " 4.3.2.1", + "disabled": False + } + ] + } + payload = {'rrsets': [rrset]} + r = self.session.patch(self.url("/servers/localhost/zones/" + name), data=json.dumps(payload), + headers={'content-type': 'application/json'}) + self.assertEquals(r.status_code, 422) + self.assertIn('Not in expected format', r.json()['error']) + def test_zone_rr_delete_out_of_zone(self): payload, zone = self.create_zone() name = payload['name'] -- 2.40.0