Skip to content

Commit

Permalink
Merge pull request #1 from nenolod/insp20
Browse files Browse the repository at this point in the history
DNS resolver hardening (insp20 branch)
  • Loading branch information
Sir Pogsalot committed Mar 21, 2012
2 parents eba7e66 + eac05f8 commit fe7dbd2
Showing 1 changed file with 38 additions and 10 deletions.
48 changes: 38 additions & 10 deletions src/dns.cpp
Expand Up @@ -38,6 +38,8 @@ looks like this, walks like this or tastes like this.
#include "configreader.h"
#include "socket.h"

#define DN_COMP_BITMASK 0xC000 /* highest 6 bits in a DN label header */

/** Masks to mask off the responses we get from the DNSRequest methods
*/
enum QueryInfo
Expand Down Expand Up @@ -98,7 +100,7 @@ class DNSRequest

DNSRequest(DNS* dns, int id, const std::string &original);
~DNSRequest();
DNSInfo ResultIsReady(DNSHeader &h, int length);
DNSInfo ResultIsReady(DNSHeader &h, unsigned length);
int SendRequests(const DNSHeader *header, const int length, QueryType qt);
};

Expand Down Expand Up @@ -161,7 +163,10 @@ int CachedQuery::CalcTTLRemaining()
/* Allocate the processing buffer */
DNSRequest::DNSRequest(DNS* dns, int rid, const std::string &original) : dnsobj(dns)
{
res = new unsigned char[512];
/* hardening against overflow here: make our work buffer twice the theoretical
* maximum size so that hostile input doesn't screw us over.
*/
res = new unsigned char[sizeof(DNSHeader) * 2];
*res = 0;
orig = original;
RequestTimeout* RT = new RequestTimeout(ServerInstance->Config->dns_timeout ? ServerInstance->Config->dns_timeout : 5, this, rid);
Expand Down Expand Up @@ -688,11 +693,11 @@ DNSResult DNS::GetResult()
}

/** A result is ready, process it */
DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, unsigned length)
{
int i = 0;
unsigned i = 0, o;
int q = 0;
int curanswer, o;
int curanswer;
ResourceRecord rr;
unsigned short ptr;

Expand Down Expand Up @@ -790,17 +795,31 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)

switch (rr.type)
{
/*
* CNAME and PTR are compressed. We need to decompress them.
*/
case DNS_QUERY_CNAME:
/* CNAME and PTR have the same processing code */
case DNS_QUERY_PTR:
o = 0;
q = 0;
while (q == 0 && i < length && o + 256 < 1023)
{
/* DN label found (byte over 63) */
if (header.payload[i] > 63)
{
memcpy(&ptr,&header.payload[i],2);
i = ntohs(ptr) - 0xC000 - 12;

i = ntohs(ptr);

/* check that highest two bits are set. if not, we've been had */
if (!(i & DN_COMP_BITMASK))
return std::make_pair((unsigned char *) NULL, "DN label decompression header is bogus");

/* mask away the two highest bits. */
i &= ~DN_COMP_BITMASK;

/* and decrease length by 12 bytes. */
i =- 12;
}
else
{
Expand All @@ -813,7 +832,11 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
res[o] = 0;
if (o != 0)
res[o++] = '.';
memcpy(&res[o],&header.payload[i + 1],header.payload[i]);

if (o + header.payload[i] > sizeof(DNSHeader))
return std::make_pair((unsigned char *) NULL, "DN label decompression is impossible -- malformed/hostile packet?");

memcpy(&res[o], &header.payload[i + 1], header.payload[i]);
o += header.payload[i];
i += header.payload[i] + 1;
}
Expand All @@ -822,16 +845,21 @@ DNSInfo DNSRequest::ResultIsReady(DNSHeader &header, int length)
res[o] = 0;
break;
case DNS_QUERY_AAAA:
if (rr.rdlength != sizeof(struct in6_addr))
return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 16 bytes for an ipv6 entry -- malformed/hostile packet?");

memcpy(res,&header.payload[i],rr.rdlength);
res[rr.rdlength] = 0;
break;
case DNS_QUERY_A:
if (rr.rdlength != sizeof(struct in_addr))
return std::make_pair((unsigned char *) NULL, "rr.rdlength is larger than 4 bytes for an ipv4 entry -- malformed/hostile packet?");

memcpy(res,&header.payload[i],rr.rdlength);
res[rr.rdlength] = 0;
break;
default:
memcpy(res,&header.payload[i],rr.rdlength);
res[rr.rdlength] = 0;
return std::make_pair((unsigned char *) NULL, "don't know how to handle undefined type (" + ConvToStr(rr.type) + ") -- rejecting");
break;
}
return std::make_pair(res,"No error");
Expand Down

0 comments on commit fe7dbd2

Please sign in to comment.