]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/dnsparser.cc
dnsdist: Add HTTPStatusAction to return a specific HTTP response
[thirdparty/pdns.git] / pdns / dnsparser.cc
index e8888111365eafc1e3fecde1ea0906f430a73c9b..1f33aac27af712b60064b0b9c4bd22cd18cdf457 100644 (file)
@@ -63,7 +63,7 @@ public:
     str<<"\\# "<<(unsigned int)d_record.size()<<" ";
     char hex[4];
     for(size_t n=0; n<d_record.size(); ++n) {
-      snprintf(hex,sizeof(hex)-1, "%02x", d_record.at(n));
+      snprintf(hex, sizeof(hex), "%02x", d_record.at(n));
       str << hex;
     }
     return str.str();
@@ -278,8 +278,6 @@ void MOADNSParser::init(bool query, const std::string& packet)
         dr.d_content=DNSRecordContent::mastermake(dr, pr, d_header.opcode);
       }
 
-      d_answers.push_back(make_pair(dr, pr.getPosition() - sizeof(dnsheader)));
-
       /* XXX: XPF records should be allowed after TSIG as soon as the actual XPF option code has been assigned:
          if (dr.d_place == DNSResourceRecord::ADDITIONAL && seenTSIG && dr.d_type != QType::XPF)
       */
@@ -295,6 +293,8 @@ void MOADNSParser::init(bool query, const std::string& packet)
         seenTSIG = true;
         d_tsigPos = recordStartPos;
       }
+
+      d_answers.push_back(make_pair(std::move(dr), pr.getPosition() - sizeof(dnsheader)));
     }
 
 #if 0
@@ -484,6 +484,11 @@ string PacketReader::getUnquotedText(bool lenField)
   else
     stop_at = d_recordlen;
 
+  /* think unsigned overflow */
+  if (stop_at < d_pos) {
+    throw std::out_of_range("getUnquotedText out of record range");
+  }
+
   if(stop_at == d_pos)
     return "";
 
@@ -496,10 +501,15 @@ string PacketReader::getUnquotedText(bool lenField)
 void PacketReader::xfrBlob(string& blob)
 try
 {
-  if(d_recordlen && !(d_pos == (d_startrecordpos + d_recordlen)))
+  if(d_recordlen && !(d_pos == (d_startrecordpos + d_recordlen))) {
+    if (d_pos > (d_startrecordpos + d_recordlen)) {
+      throw std::out_of_range("xfrBlob out of record range");
+    }
     blob.assign(&d_content.at(d_pos), &d_content.at(d_startrecordpos + d_recordlen - 1 ) + 1);
-  else
+  }
+  else {
     blob.clear();
+  }
 
   d_pos = d_startrecordpos + d_recordlen;
 }
@@ -515,12 +525,17 @@ void PacketReader::xfrBlobNoSpaces(string& blob, int length) {
 void PacketReader::xfrBlob(string& blob, int length)
 {
   if(length) {
+    if (length < 0) {
+      throw std::out_of_range("xfrBlob out of range (negative length)");
+    }
+
     blob.assign(&d_content.at(d_pos), &d_content.at(d_pos + length - 1 ) + 1 );
-    
+
     d_pos += length;
   }
-  else 
+  else {
     blob.clear();
+  }
 }
 
 
@@ -570,7 +585,11 @@ public:
     : d_packet(packet), d_length(length), d_notyouroffset(12), d_offset(d_notyouroffset)
   {}
   
-  void skipLabel()
+  /*! Advances past a wire-format domain name
+   * The name is not checked for adherence to length restrictions.
+   * Compression pointers are not followed.
+   */
+  void skipDomainName()
   {
     uint8_t len; 
     while((len=get8BitInt())) { 
@@ -581,6 +600,7 @@ public:
       skipBytes(len);
     }
   }
+
   void skipBytes(uint16_t bytes)
   {
     moveOffset(bytes);
@@ -682,13 +702,13 @@ void editDNSPacketTTL(char* packet, size_t length, std::function<uint32_t(uint8_
 
     uint64_t n;
     for(n=0; n < ntohs(dh.qdcount) ; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       /* type and class */
       dpm.skipBytes(4);
     }
 
     for(n=0; n < numrecords; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
 
       uint8_t section = n < ntohs(dh.ancount) ? 1 : (n < (ntohs(dh.ancount) + ntohs(dh.nscount)) ? 2 : 3);
       uint16_t dnstype = dpm.get16BitInt();
@@ -726,13 +746,13 @@ void ageDNSPacket(char* packet, size_t length, uint32_t seconds)
 
     uint64_t n;
     for(n=0; n < dqcount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       /* type and class */
       dpm.skipBytes(4);
     }
    // cerr<<"Skipped "<<n<<" questions, now parsing "<<numrecords<<" records"<<endl;
     for(n=0; n < numrecords; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       
       uint16_t dnstype = dpm.get16BitInt();
       /* class */
@@ -769,13 +789,13 @@ uint32_t getDNSPacketMinTTL(const char* packet, size_t length, bool* seenAuthSOA
 
     const uint16_t qdcount = ntohs(dh->qdcount);
     for(size_t n = 0; n < qdcount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       /* type and class */
       dpm.skipBytes(4);
     }
     const size_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount);
     for(size_t n = 0; n < numrecords; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       const uint16_t dnstype = dpm.get16BitInt();
       /* class */
       const uint16_t dnsclass = dpm.get16BitInt();
@@ -811,18 +831,18 @@ uint32_t getDNSPacketLength(const char* packet, size_t length)
   }
   try
   {
-    const dnsheader* dh = (const dnsheader*) packet;
+    const dnsheader* dh = reinterpret_cast<const dnsheader*>(packet);
     DNSPacketMangler dpm(const_cast<char*>(packet), length);
 
     const uint16_t qdcount = ntohs(dh->qdcount);
     for(size_t n = 0; n < qdcount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       /* type and class */
       dpm.skipBytes(4);
     }
     const size_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount);
     for(size_t n = 0; n < numrecords; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       /* type (2), class (2) and ttl (4) */
       dpm.skipBytes(8);
       dpm.skipRData();
@@ -848,7 +868,7 @@ uint16_t getRecordsOfTypeCount(const char* packet, size_t length, uint8_t sectio
 
     const uint16_t qdcount = ntohs(dh->qdcount);
     for(size_t n = 0; n < qdcount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       if (section == 0) {
         uint16_t dnstype = dpm.get16BitInt();
         if (dnstype == type) {
@@ -863,7 +883,7 @@ uint16_t getRecordsOfTypeCount(const char* packet, size_t length, uint8_t sectio
     }
     const uint16_t ancount = ntohs(dh->ancount);
     for(size_t n = 0; n < ancount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       if (section == 1) {
         uint16_t dnstype = dpm.get16BitInt();
         if (dnstype == type) {
@@ -881,7 +901,7 @@ uint16_t getRecordsOfTypeCount(const char* packet, size_t length, uint8_t sectio
     }
     const uint16_t nscount = ntohs(dh->nscount);
     for(size_t n = 0; n < nscount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       if (section == 2) {
         uint16_t dnstype = dpm.get16BitInt();
         if (dnstype == type) {
@@ -899,7 +919,7 @@ uint16_t getRecordsOfTypeCount(const char* packet, size_t length, uint8_t sectio
     }
     const uint16_t arcount = ntohs(dh->arcount);
     for(size_t n = 0; n < arcount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       if (section == 3) {
         uint16_t dnstype = dpm.get16BitInt();
         if (dnstype == type) {
@@ -938,13 +958,13 @@ bool getEDNSUDPPayloadSizeAndZ(const char* packet, size_t length, uint16_t* payl
 
     const uint16_t qdcount = ntohs(dh->qdcount);
     for(size_t n = 0; n < qdcount; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       /* type and class */
       dpm.skipBytes(4);
     }
     const size_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount);
     for(size_t n = 0; n < numrecords; ++n) {
-      dpm.skipLabel();
+      dpm.skipDomainName();
       const uint16_t dnstype = dpm.get16BitInt();
       const uint16_t dnsclass = dpm.get16BitInt();