From: Peter van Dijk Date: Sun, 29 Apr 2012 14:38:06 +0000 (+0000) Subject: implement support for NSEC bitmaps covering types above 255. Reported by Michael... X-Git-Tag: auth-3.1-rc3~7 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5b7f65461b656ce554d392e903c92091370a0dfd;p=thirdparty%2Fpdns.git implement support for NSEC bitmaps covering types above 255. Reported by Michael Braunoeder, patch by Aki Tuomi. Includes regression test. git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2590 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/nsecrecords.cc b/pdns/nsecrecords.cc index 670c755b0e..aa16b2b4e9 100644 --- a/pdns/nsecrecords.cc +++ b/pdns/nsecrecords.cc @@ -27,19 +27,32 @@ void NSECRecordContent::toPacket(DNSPacketWriter& pw) pw.xfrLabel(d_next); uint8_t res[34]; - memset(res, 0, sizeof(res)); - set::const_iterator i; - for(i=d_set.begin(); i != d_set.end() && *i<255; ++i){ - res[2+*i/8] |= 1 << (7-(*i%8)); - } - int len=0; - if(!d_set.empty()) - len=1+*--i/8; + int oldWindow = -1; + int window = 0; + int len = 0; + string tmp; - res[1]=len; + for(i=d_set.begin(); i != d_set.end(); ++i){ + uint16_t bit = (*i)%256; + window = static_cast((*i) / 256); - string tmp; + if (window != oldWindow) { + if (oldWindow > -1) { + res[0] = static_cast(oldWindow); + res[1] = static_cast(len); + tmp.assign(res, res+len+2); + pw.xfrBlob(tmp); + } + memset(res, 0, 34); + oldWindow = window; + } + res[2+bit/8] |= 1 << (7-(bit%8)); + len=1+bit/8; + } + + res[0] = static_cast(window); + res[1] = static_cast(len); tmp.assign(res, res+len+2); pw.xfrBlob(tmp); } @@ -50,27 +63,31 @@ NSECRecordContent::DNSRecordContent* NSECRecordContent::make(const DNSRecord &dr pr.xfrLabel(ret->d_next); string bitmap; pr.xfrBlob(bitmap); - + // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left - + if(bitmap.empty()) + return ret; + if(bitmap.size() < 2) throw MOADNSException("NSEC record with impossibly small bitmap"); - if(bitmap[0]) - throw MOADNSException("Can't deal with NSEC mappings > 255 yet"); - - unsigned int len=bitmap[1]; - if(bitmap.size()!=2+len) - throw MOADNSException("Can't deal with multi-part NSEC mappings yet"); - - for(unsigned int n=0 ; n < len ; ++n) { - uint8_t val=bitmap[2+n]; - for(int bit = 0; bit < 8 ; ++bit , val>>=1) - if(val & 1) { - ret->d_set.insert((7-bit) + 8*(n)); + for(unsigned int n = 0; n+1 < bitmap.size();) { + unsigned int window=static_cast(bitmap[n++]); + unsigned int len=static_cast(bitmap[n++]); + + // end if zero padding and ensure packet length + if(window == 0&&len == 0) break; + if(n+len>bitmap.size()) + throw MOADNSException("NSEC record with bitmap length > packet length"); + + for(unsigned int k=0; k < len; k++) { + uint8_t val=bitmap[n++]; + for(int bit = 0; bit < 8 ; ++bit , val>>=1) + if(val & 1) { + ret->d_set.insert((7-bit) + 8*(k) + 256*window); + } } } - return ret; } @@ -129,19 +146,32 @@ void NSEC3RecordContent::toPacket(DNSPacketWriter& pw) pw.xfrBlob(d_nexthash); uint8_t res[34]; - memset(res, 0, sizeof(res)); - set::const_iterator i; - for(i=d_set.begin(); i != d_set.end() && *i<255; ++i){ - res[2+*i/8] |= 1 << (7-(*i%8)); - } - int len=0; - if(!d_set.empty()) - len=1+*--i/8; + int oldWindow = -1; + int window = 0; + int len = 0; + string tmp; - res[1]=len; + for(i=d_set.begin(); i != d_set.end(); ++i){ + uint16_t bit = (*i)%256; + window = static_cast((*i) / 256); - string tmp; + if (window != oldWindow) { + if (oldWindow > -1) { + res[0] = static_cast(oldWindow); + res[1] = static_cast(len); + tmp.assign(res, res+len+2); + pw.xfrBlob(tmp); + } + memset(res, 0, 34); + oldWindow = window; + } + res[2+bit/8] |= 1 << (7-(bit%8)); + len=1+bit/8; + } + + res[0] = static_cast(window); + res[1] = static_cast(len); tmp.assign(res, res+len+2); pw.xfrBlob(tmp); } @@ -170,22 +200,24 @@ NSEC3RecordContent::DNSRecordContent* NSEC3RecordContent::make(const DNSRecord & if(bitmap.size() < 2) throw MOADNSException("NSEC3 record with impossibly small bitmap"); - - if(bitmap[0]) - throw MOADNSException("Can't deal with NSEC3 mappings > 255 yet"); - - unsigned int bitmaplen=bitmap[1]; - if(bitmap.size()!=2+bitmaplen) - throw MOADNSException("Can't deal with multi-part NSEC3 mappings yet"); - - for(unsigned int n=0 ; n < bitmaplen ; ++n) { - uint8_t val=bitmap[2+n]; - for(int bit = 0; bit < 8 ; ++bit , val>>=1) - if(val & 1) { - ret->d_set.insert((7-bit) + 8*(n)); + + for(unsigned int n = 0; n+1 < bitmap.size();) { + unsigned int window=static_cast(bitmap[n++]); + unsigned int len=static_cast(bitmap[n++]); + + // end if zero padding and ensure packet length + if(window == 0&&len == 0) break; + if(n+len>bitmap.size()) + throw MOADNSException("NSEC record with bitmap length > packet length"); + + for(unsigned int k=0; k < len; k++) { + uint8_t val=bitmap[n++]; + for(int bit = 0; bit < 8 ; ++bit , val>>=1) + if(val & 1) { + ret->d_set.insert((7-bit) + 8*(k) + 256*window); + } } } - return ret; } diff --git a/regression-tests/example.com b/regression-tests/example.com index 1d2dc8cf76..62f804371c 100644 --- a/regression-tests/example.com +++ b/regression-tests/example.com @@ -17,6 +17,9 @@ $ORIGIN example.com. ns1 IN A 192.168.1.1 ns2 IN A 192.168.1.2 ; +hightype IN A 192.168.1.5 +hightype IN TYPE65534 \# 5 07ED260001 +; localhost IN A 127.0.0.1 www IN CNAME outpost.example.com. ; diff --git a/regression-tests/nsec-bitmap/command b/regression-tests/nsec-bitmap/command new file mode 100755 index 0000000000..312d4fcdd9 --- /dev/null +++ b/regression-tests/nsec-bitmap/command @@ -0,0 +1,2 @@ +#!/bin/sh +cleandig hightype.example.com NSEC dnssec | egrep 'IN[[:space:]]+NSEC' diff --git a/regression-tests/nsec-bitmap/expected_result b/regression-tests/nsec-bitmap/expected_result new file mode 100644 index 0000000000..992d779aa7 --- /dev/null +++ b/regression-tests/nsec-bitmap/expected_result @@ -0,0 +1 @@ +0 hightype.example.com. IN NSEC 120 host-0.example.com. A RRSIG NSEC TYPE65534 diff --git a/regression-tests/nsec-bitmap/expected_result.nsec3 b/regression-tests/nsec-bitmap/expected_result.nsec3 new file mode 100644 index 0000000000..2882793d3d --- /dev/null +++ b/regression-tests/nsec-bitmap/expected_result.nsec3 @@ -0,0 +1,3 @@ +1 3v4it454kfh142bi7afagnuvigrpfptt.example.com. IN NSEC3 120 1 1 1 abcd 3V4S43RV1GT28N0F2PPJ8I8482ESMUOB A RRSIG TYPE65534 +1 9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com. IN NSEC3 120 1 1 1 abcd 9FDAOFPLLN0FQFU9DP274GOU59QFHSLD A RRSIG +1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN NSEC3 120 1 1 1 abcd VTP9NUQBEH436S7J0K8TI2A32MMKCUUL NS SOA MX RRSIG DNSKEY NSEC3PARAM diff --git a/regression-tests/nsec-bitmap/skip.nodnssec b/regression-tests/nsec-bitmap/skip.nodnssec new file mode 100644 index 0000000000..e69de29bb2