From: Remi Gacogne Date: Wed, 4 Jan 2017 10:48:47 +0000 (+0100) Subject: DNSName: Check that both first two bits are set in compressed labels X-Git-Tag: rec-4.1.0-alpha1~356^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F4852%2Fhead;p=thirdparty%2Fpdns.git DNSName: Check that both first two bits are set in compressed labels We checked that at least one of the first two bits was set, but the 10 and 01 are combinations do not indicate a compressed label and are reserved for future use. --- diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index 07214efb1f..8c6bf150ff 100644 --- a/pdns/dnsname.cc +++ b/pdns/dnsname.cc @@ -113,7 +113,7 @@ void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompres const unsigned char* end = pos + len; pos += offset; while((labellen=*pos++) && pos < end) { // "scan and copy" - if(labellen & 0xc0) { + if(labellen >= 0xc0) { if(!uncompress) throw std::range_error("Found compressed label, instructed not to follow"); @@ -130,6 +130,8 @@ void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompres throw std::range_error("Found a forward reference during label decompression"); pos++; break; + } else if(labellen & 0xc0) { + throw std::range_error("Found an invalid label length in qname (only one of the first two bits is set)"); } if (pos + labellen < end) { appendRawLabel((const char*)pos, labellen); diff --git a/pdns/test-dnsname_cc.cc b/pdns/test-dnsname_cc.cc index fc63ccee22..cb24308f76 100644 --- a/pdns/test-dnsname_cc.cc +++ b/pdns/test-dnsname_cc.cc @@ -768,10 +768,28 @@ BOOST_AUTO_TEST_CASE(test_compression_qtype_qclass) { // Compression test with Q string name("\x03""com\x00""\x07""example\xc1""\x00""\x03""www\xc1""\x05""\x00""\x01""\x00", 24); name.insert(0, 256, '0'); - BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 271, true, &qtype, &qclass), std::range_error);; + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 271, true, &qtype, &qclass), std::range_error); } } +BOOST_AUTO_TEST_CASE(test_compression_single_bit_set) { // first 2 bits as 10 or 01, not 11 + + // first 2 bits: 10 + { + string name("\x03""com\x00""\x07""example\x80""\x00""\x03""www\x80""\x05", 21); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true), std::range_error); + } + + // first 2 bits: 01 + { + string name("\x03""com\x00""\x07""example\x40""\x00""\x03""www\x40""\x05", 21); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true), std::range_error); + } + +} + BOOST_AUTO_TEST_CASE(test_pointer_pointer_root) { // Pointer to pointer to root string name("\x00""\xc0""\x00""\x03""com\xc0""\x01",9);