From 99bbbc7bdf675509caf61f41464a1ae62c09f342 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Wed, 4 Jan 2017 11:48:47 +0100 Subject: [PATCH] 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. --- pdns/dnsname.cc | 4 +++- pdns/test-dnsname_cc.cc | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index 07214efb1..8c6bf150f 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 fc63ccee2..cb24308f7 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); -- 2.40.0