Skip to content

Commit 881b5b0

Browse files
committed
Reject qname's wirelength > 255, chopOff() handle dot inside labels
1 parent 01cb7bb commit 881b5b0

File tree

3 files changed

+58
-26
lines changed

3 files changed

+58
-26
lines changed

Diff for: pdns/dnsparser.cc

+13-4
Original file line numberDiff line numberDiff line change
@@ -402,8 +402,9 @@ uint8_t PacketReader::get8BitInt()
402402
string PacketReader::getLabel(unsigned int recurs)
403403
{
404404
string ret;
405+
size_t wirelength = 0;
405406
ret.reserve(40);
406-
getLabelFromContent(d_content, d_pos, ret, recurs++);
407+
getLabelFromContent(d_content, d_pos, ret, recurs++, wirelength);
407408
return ret;
408409
}
409410

@@ -453,7 +454,7 @@ string PacketReader::getText(bool multi)
453454
}
454455

455456

456-
void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs)
457+
void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs, size_t& wirelength)
457458
{
458459
if(recurs > 100) // the forward reference-check below should make this test 100% obsolete
459460
throw MOADNSException("Loop");
@@ -462,6 +463,10 @@ void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t&
462463
// it is tempting to call reserve on ret, but it turns out it creates a malloc/free storm in the loop
463464
for(;;) {
464465
unsigned char labellen=content.at(frompos++);
466+
wirelength++;
467+
if (wirelength > 255) {
468+
throw MOADNSException("Overly long DNS name ("+lexical_cast<string>(wirelength)+")");
469+
}
465470

466471
if(!labellen) {
467472
if(ret.empty())
@@ -474,13 +479,17 @@ void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t&
474479

475480
if(offset >= pos)
476481
throw MOADNSException("forward reference during label decompression");
477-
return getLabelFromContent(content, offset, ret, ++recurs);
482+
/* the compression pointer does not count into the wire length */
483+
return getLabelFromContent(content, offset, ret, ++recurs, --wirelength);
478484
}
479485
else if(labellen > 63)
480486
throw MOADNSException("Overly long label during label decompression ("+lexical_cast<string>((unsigned int)labellen)+")");
481487
else {
488+
if (wirelength + labellen > 255) {
489+
throw MOADNSException("Overly long DNS name ("+lexical_cast<string>(wirelength)+")");
490+
}
491+
wirelength += labellen;
482492
// XXX FIXME THIS MIGHT BE VERY SLOW!
483-
484493
for(string::size_type n = 0 ; n < labellen; ++n, frompos++) {
485494
if(content.at(frompos)=='.' || content.at(frompos)=='\\') {
486495
ret.append(1, '\\');

Diff for: pdns/dnsparser.hh

+1-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public:
133133
void xfrHexBlob(string& blob, bool keepReading=false);
134134

135135
static uint16_t get16BitInt(const vector<unsigned char>&content, uint16_t& pos);
136-
static void getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs);
136+
static void getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs, size_t& wirelength);
137137

138138
void getDnsrecordheader(struct dnsrecordheader &ah);
139139
void copyRecord(vector<unsigned char>& dest, uint16_t len);

Diff for: pdns/misc.cc

+44-21
Original file line numberDiff line numberDiff line change
@@ -150,16 +150,27 @@ bool chopOff(string &domain)
150150
if(domain.empty())
151151
return false;
152152

153-
string::size_type fdot=domain.find('.');
154-
155-
if(fdot==string::npos)
156-
domain="";
157-
else {
158-
string::size_type remain = domain.length() - (fdot + 1);
159-
char tmp[remain];
160-
memcpy(tmp, domain.c_str()+fdot+1, remain);
161-
domain.assign(tmp, remain); // don't dare to do this w/o tmp holder :-)
153+
bool escaped = false;
154+
const string::size_type domainLen = domain.length();
155+
for (size_t fdot = 0; fdot < domainLen; fdot++)
156+
{
157+
if (domain[fdot] == '.' && !escaped) {
158+
string::size_type remain = domainLen - (fdot + 1);
159+
char tmp[remain];
160+
memcpy(tmp, domain.c_str()+fdot+1, remain);
161+
domain.assign(tmp, remain); // don't dare to do this w/o tmp holder :-)
162+
163+
return true;
164+
}
165+
else if (domain[fdot] == '\\' && !escaped) {
166+
escaped = true;
167+
}
168+
else {
169+
escaped = false;
170+
}
162171
}
172+
173+
domain = "";
163174
return true;
164175
}
165176

@@ -169,19 +180,31 @@ bool chopOffDotted(string &domain)
169180
if(domain.empty() || (domain.size()==1 && domain[0]=='.'))
170181
return false;
171182

172-
string::size_type fdot=domain.find('.');
173-
if(fdot == string::npos)
174-
return false;
175-
176-
if(fdot==domain.size()-1)
177-
domain=".";
178-
else {
179-
string::size_type remain = domain.length() - (fdot + 1);
180-
char tmp[remain];
181-
memcpy(tmp, domain.c_str()+fdot+1, remain);
182-
domain.assign(tmp, remain);
183+
bool escaped = false;
184+
const string::size_type domainLen = domain.length();
185+
for (size_t fdot = 0; fdot < domainLen; fdot++)
186+
{
187+
if (domain[fdot] == '.' && !escaped) {
188+
if (fdot==domain.size()-1) {
189+
domain=".";
190+
}
191+
else {
192+
string::size_type remain = domainLen - (fdot + 1);
193+
char tmp[remain];
194+
memcpy(tmp, domain.c_str()+fdot+1, remain);
195+
domain.assign(tmp, remain); // don't dare to do this w/o tmp holder :-)
196+
}
197+
return true;
198+
}
199+
else if (domain[fdot] == '\\' && !escaped) {
200+
escaped = true;
201+
}
202+
else {
203+
escaped = false;
204+
}
183205
}
184-
return true;
206+
207+
return false;
185208
}
186209

187210

0 commit comments

Comments
 (0)