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

(cherry picked from commit 99bbbc7bdf675509caf61f41464a1ae62c09f342)

pdns/dnsname.cc
pdns/test-dnsname_cc.cc

index 62869eb5d90d5ac3dfa4784ef86dbe7aab913615..cb8530bffcf93ed37abf056b83385a141e87ad02 100644 (file)
@@ -111,7 +111,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");
 
@@ -128,6 +128,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 cbbe5380be197ade11e41bb63e54a359ca89151a..328e3a928d6ffae218bcdea8e8e8f233575f77f1 100644 (file)
@@ -645,10 +645,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);