]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
DNSName: Check that both first two bits are set in compressed labels 4852/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 4 Jan 2017 10:48:47 +0000 (11:48 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 4 Jan 2017 10:48:47 +0000 (11:48 +0100)
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
pdns/test-dnsname_cc.cc

index 07214efb1fcf53166a6c2d58d1d0b0aa5f4a5f02..8c6bf150ff9a39e949900b60d764d9ef1ed18d12 100644 (file)
@@ -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);
index fc63ccee22e17ef05beb064b8c8f9d1c74474904..cb24308f76f80eee3ba81613443fe9287d4cca29 100644 (file)
@@ -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);