From 267951e643bf68d119d9034006ad3e3f2875edda Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20B=C3=BChler?= Date: Thu, 28 Dec 2017 23:28:32 +0100 Subject: [PATCH] fix xfrIP to reject invalid ips (fixes #6101) - require exactly 3 dots - forbid empty octets --- pdns/rcpgenerator.cc | 19 +++++++++++++------ pdns/test-dnsrecords_cc.cc | 5 ++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/pdns/rcpgenerator.cc b/pdns/rcpgenerator.cc index aea5c4437..0b606424b 100644 --- a/pdns/rcpgenerator.cc +++ b/pdns/rcpgenerator.cc @@ -102,17 +102,22 @@ void RecordTextReader::xfrIP(uint32_t &val) uint32_t octet=0; val=0; char count=0; - + bool last_was_digit = false; + for(;;) { if(d_string.at(d_pos)=='.') { + if (!last_was_digit) + throw RecordTextException(string("unable to parse IP address, dot without previous digit")); + last_was_digit = false; val<<=8; val+=octet; octet=0; count++; if(count > 3) - break; + throw RecordTextException(string("unable to parse IP address, too many dots")); } else if(isdigit(d_string.at(d_pos))) { + last_was_digit = true; octet*=10; octet+=d_string.at(d_pos) - '0'; if(octet > 255) @@ -127,10 +132,12 @@ void RecordTextReader::xfrIP(uint32_t &val) if(d_pos == d_string.length()) break; } - if(count<=3) { - val<<=8; - val+=octet; - } + if (count != 3) + throw RecordTextException(string("unable to parse IP address, not enough dots")); + if (!last_was_digit) + throw RecordTextException(string("unable to parse IP address, trailing dot")); + val<<=8; + val+=octet; val=ntohl(val); } diff --git a/pdns/test-dnsrecords_cc.cc b/pdns/test-dnsrecords_cc.cc index 8efc5284e..b8e3bf8b8 100644 --- a/pdns/test-dnsrecords_cc.cc +++ b/pdns/test-dnsrecords_cc.cc @@ -240,8 +240,11 @@ BOOST_AUTO_TEST_CASE(test_record_types_bad_values) { cases_t cases = boost::assign::list_of (case_t(QType::A, "932.521.256.42", zone, false)) // hollywood IP (case_t(QType::A, "932.521", zone, false)) // truncated hollywood IP - (case_t(QType::A, "10.0", zone, true)) // truncated IP + (case_t(QType::A, "10.0", zone, false)) // truncated IP (case_t(QType::A, "10.0.0.1.", zone, false)) // trailing dot + (case_t(QType::A, "10.0.0.", zone, false)) // trailing dot + (case_t(QType::A, ".0.0.1", zone, false)) // empty octet + (case_t(QType::A, "10..0.1", zone, false)) // empty octet (case_t(QType::A, "\xca\xec\x00", wire, false)) // truncated wire value (case_t(QType::A, "127.0.0.1 evil data", zone, false)) // trailing garbage (case_t(QType::AAAA, "23:00", zone, false)) // time when this test was written -- 2.40.0