From 9114819cc4c5dad50ba92c8a9ab8d852811db365 Mon Sep 17 00:00:00 2001 From: Kees Monshouwer Date: Mon, 4 May 2015 22:56:06 +0200 Subject: [PATCH] add redirect loop safeguard in dnsname --- pdns/dnsname.cc | 7 +++++-- pdns/dnsname.hh | 1 + pdns/test-dnsname_cc.cc | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pdns/dnsname.cc b/pdns/dnsname.cc index 8f1bb5b0f5..a3d2778e9d 100644 --- a/pdns/dnsname.cc +++ b/pdns/dnsname.cc @@ -20,6 +20,7 @@ DNSName::DNSName(const char* p) DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass, unsigned int* consumed) { + d_recurse = 0; packetParser(pos, len, offset, uncompress, qtype, qclass, consumed); } @@ -38,9 +39,11 @@ void DNSName::packetParser(const char* pos, int len, int offset, bool uncompress labellen &= (~0xc0); int newpos = (labellen << 8) + *(const unsigned char*)pos; - if(newpos < offset) + if(newpos < offset) { + if (++d_recurse > 100) + throw std::range_error("Abort label decompression after 100 redirects"); packetParser(opos, len, newpos, true); - else + } else throw std::range_error("Found a forward reference during label decompression"); pos++; break; diff --git a/pdns/dnsname.hh b/pdns/dnsname.hh index f2b83a6d67..de5623502c 100644 --- a/pdns/dnsname.hh +++ b/pdns/dnsname.hh @@ -60,6 +60,7 @@ private: // typedef __gnu_cxx::__sso_string string_t; typedef std::string string_t; string_t d_storage; + int d_recurse; void packetParser(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0, unsigned int* consumed=0); static std::string escapeLabel(const std::string& orig); diff --git a/pdns/test-dnsname_cc.cc b/pdns/test-dnsname_cc.cc index 547ab32385..a457a9e12f 100644 --- a/pdns/test-dnsname_cc.cc +++ b/pdns/test-dnsname_cc.cc @@ -410,5 +410,21 @@ BOOST_AUTO_TEST_CASE(test_compression_loop1) { // Compression loop (pointer loop BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 0, true), std::range_error); } +BOOST_AUTO_TEST_CASE(test_compression_loop2) { // Compression loop (deep recursion) + + int i; + string name("\x00\xc0\x00", 3); + for (i=0; i<98; ++i) { + name.append( 1, ((i >> 7) & 0xff) | 0xc0); + name.append( 1, ((i << 1) & 0xff) | 0x01); + } + BOOST_CHECK_NO_THROW(DNSName dn(name.c_str(), name.size(), name.size()-2, true)); + + ++i; + name.append( 1, ((i >> 7) & 0xff) | 0xc0); + name.append( 1, ((i << 1) & 0xff) | 0x01); + + BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), name.size()-2, true), std::range_error); +} BOOST_AUTO_TEST_SUITE_END() -- 2.47.2