File CVE-2020-17482.patch of Package pdns.13121
diff -ur pdns-4.1.13/pdns/dnsparser.cc pdns-4.1.13-2020-05/pdns/dnsparser.cc
--- pdns-4.1.13/pdns/dnsparser.cc 2019-08-08 09:49:19.000000000 +0200
+++ pdns-4.1.13-2020-05/pdns/dnsparser.cc 2020-09-07 12:40:17.587304688 +0200
@@ -40,17 +40,29 @@
// parse the input
vector<string> parts;
stringtok(parts, zone);
- if(parts.size()!=3 && !(parts.size()==2 && equals(parts[1],"0")) )
- throw MOADNSException("Unknown record was stored incorrectly, need 3 fields, got "+std::to_string(parts.size())+": "+zone );
- const string& relevant=(parts.size() > 2) ? parts[2] : "";
- unsigned int total=pdns_stou(parts[1]);
- if(relevant.size() % 2 || relevant.size() / 2 != total)
+ // we need exactly 3 parts, except if the length field is set to 0 then we only need 2
+ if (parts.size() != 3 && !(parts.size() == 2 && equals(parts.at(1), "0"))) {
+ throw MOADNSException("Unknown record was stored incorrectly, need 3 fields, got " + std::to_string(parts.size()) + ": " + zone);
+ }
+
+ if (parts.at(0) != "\\#") {
+ throw MOADNSException("Unknown record was stored incorrectly, first part should be '\\#', got '" + parts.at(0) + "'");
+ }
+
+ const string& relevant = (parts.size() > 2) ? parts.at(2) : "";
+ unsigned int total = pdns_stou(parts.at(1));
+ if (relevant.size() % 2 || (relevant.size() / 2) != total) {
throw MOADNSException((boost::format("invalid unknown record length: size not equal to length field (%d != 2 * %d)") % relevant.size() % total).str());
+ }
+
string out;
- out.reserve(total+1);
- for(unsigned int n=0; n < total; ++n) {
+ out.reserve(total + 1);
+
+ for (unsigned int n = 0; n < total; ++n) {
int c;
- sscanf(relevant.c_str()+2*n, "%02x", &c);
+ if (sscanf(&relevant.at(2*n), "%02x", &c) != 1) {
+ throw MOADNSException("unable to read data at position " + std::to_string(2 * n) + " from unknown record of size " + std::to_string(relevant.size()));
+ }
out.append(1, (char)c);
}
diff -ur pdns-4.1.13/pdns/test-dnsrecords_cc.cc pdns-4.1.13-2020-05/pdns/test-dnsrecords_cc.cc
--- pdns-4.1.13/pdns/test-dnsrecords_cc.cc 2019-08-08 09:49:19.000000000 +0200
+++ pdns-4.1.13-2020-05/pdns/test-dnsrecords_cc.cc 2020-09-07 12:40:17.587304688 +0200
@@ -327,4 +327,39 @@
BOOST_CHECK_EQUAL(makeHexDump(std::string(pak.begin(),pak.end())), makeHexDump(packet));
}
+// special record test, because Unknown record types are the worst
+BOOST_AUTO_TEST_CASE(test_unknown_records_in) {
+
+ auto validUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 42");
+
+ // we need at least two parts
+ BOOST_CHECK_THROW(auto notEnoughPartsUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\#"), MOADNSException);
+
+ // two parts are OK when the RDATA size is 0, not OK otherwise
+ auto validEmptyUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 0");
+ BOOST_CHECK_THROW(auto twoPartsNotZeroUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1"), MOADNSException);
+
+ // the first part has to be "\#"
+ BOOST_CHECK_THROW(auto invalidFirstPartUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\$ 0"), MOADNSException);
+
+ // RDATA length is not even
+ BOOST_CHECK_THROW(auto unevenUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 A"), MOADNSException);
+
+ // RDATA length is not equal to the expected size
+ BOOST_CHECK_THROW(auto wrongRDATASizeUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 2 AA"), MOADNSException);
+
+ // RDATA is invalid (invalid hex value)
+ try {
+ auto invalidRDATAUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 JJ");
+ // we should not reach that code
+ BOOST_CHECK(false);
+ // but if we do let's see what we got (likely what was left over on the stack)
+ BOOST_CHECK_EQUAL(invalidRDATAUnknown->getZoneRepresentation(), "\\# 1 jj");
+ }
+ catch (const MOADNSException& e)
+ {
+ // it's expected to end up there
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()