BIND 10 master, updated. 9c690982f24fef19c747a72f43c4298333a58f48 Merge branch 'trac117'
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Feb 17 19:43:09 UTC 2011
The branch, master has been updated
via 9c690982f24fef19c747a72f43c4298333a58f48 (commit)
via aa32fd56bf7b4eb3f1ee13b502f2724af8f7ac4d (commit)
via d0a29d0aa3931ad8091c24665ceeee95b94d58eb (commit)
via 73b2eaec32ef4dbfa93bb5009229e9ca261c3676 (commit)
via 130ba31d0829fa47a5e245490a9ae172d1c91b7c (commit)
via ae9a05a4c5d73b3d32303b622c6b7d0c04d061d3 (commit)
via d7a9547198d61bc455d41ba45f6f14874f05c1d5 (commit)
via 17832da870f12a8bfb6ec4e8f91fda964c1afcbf (commit)
via cf0dac64cd9e7f132ca58f0df3609f00d2cc4a07 (commit)
via a9944090a851bd3be8f459c7185058394d31fd55 (commit)
via 866ae82be92451173b08ff1135c2ffe9ce820271 (commit)
via 634dd02746cd7d5cc6c702b9a3ea690825282c22 (commit)
via 24afa6a4a2bc6d4fb4151a866cb12ff5728db277 (commit)
via 00b804d7100f12f5ea261b4dccb01f1de4cd94cc (commit)
via 75cd27c3b2d1bde61ffef18bb53198cc459910ed (commit)
via b099d028354adfd16fe3dd838f1f36f024c79f40 (commit)
via ccdb524e2fa0b9d2ce5570b73023a3f127756c76 (commit)
via dd59f2ff605abcdb0a1e8b284c219b8d788c0585 (commit)
via 42cd95d56e1f9c71eeeb107284c4762cf1a9a726 (commit)
via e935dae553418e90ef4ac06d598da285e8b20bea (commit)
via 355e2efda4baba2827a9d95a648974ab3f5bcfa3 (commit)
via 9cdddf2713e4e4fe103cb3cdd6e9af44e827c5d8 (commit)
via 2cb4775feeb0be8174565e175c4f800899879c19 (commit)
via d74693d2cb99c839b5efdd7c1bc0188fe39bc86f (commit)
from 96c902f2ffb43d75fbd138a6da15dbbc0d80a71f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 9c690982f24fef19c747a72f43c4298333a58f48
Merge: 96c902f aa32fd5
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Thu Feb 17 11:22:39 2011 -0800
Merge branch 'trac117'
-----------------------------------------------------------------------
Summary of changes:
src/lib/dns/Makefile.am | 3 +
src/lib/dns/rdata/generic/detail/nsec_bitmap.cc | 78 ++++++++++++
src/lib/dns/rdata/generic/detail/nsec_bitmap.h | 51 ++++++++
src/lib/dns/rdata/generic/nsec3_50.cc | 118 +++++++++++--------
src/lib/dns/rdata/generic/nsec3_50.h | 3 +-
src/lib/dns/rdata/generic/nsec_47.cc | 40 +------
src/lib/dns/tests/Makefile.am | 1 +
src/lib/dns/tests/rdata_nsec3_unittest.cc | 127 ++++++++++++++++----
src/lib/dns/tests/rdata_nsec_unittest.cc | 41 +------
...ec_unittest.cc => rdata_nsecbitmap_unittest.cc} | 97 ++++++----------
src/lib/dns/tests/testdata/Makefile.am | 22 +++-
src/lib/dns/tests/testdata/gen-wiredata.py.in | 81 ++++++++++---
.../dns/tests/testdata/rdata_nsec3_fromWire1.spec | 7 +
.../dns/tests/testdata/rdata_nsec3_fromWire10.spec | 8 ++
.../dns/tests/testdata/rdata_nsec3_fromWire11.spec | 8 ++
.../dns/tests/testdata/rdata_nsec3_fromWire12.spec | 9 ++
.../dns/tests/testdata/rdata_nsec3_fromWire13.spec | 9 ++
.../dns/tests/testdata/rdata_nsec3_fromWire14.spec | 9 ++
.../dns/tests/testdata/rdata_nsec3_fromWire15.spec | 10 ++
src/lib/dns/tests/testdata/rdata_nsec3_fromWire2 | 12 --
.../dns/tests/testdata/rdata_nsec3_fromWire2.spec | 9 ++
.../dns/tests/testdata/rdata_nsec3_fromWire4.spec | 9 ++
...c_fromWire5.spec => rdata_nsec3_fromWire5.spec} | 8 +-
.../dns/tests/testdata/rdata_nsec3_fromWire6.spec | 11 ++
...c_fromWire7.spec => rdata_nsec3_fromWire7.spec} | 6 +-
...c_fromWire8.spec => rdata_nsec3_fromWire8.spec} | 6 +-
.../dns/tests/testdata/rdata_nsec3_fromWire9.spec | 10 ++
27 files changed, 535 insertions(+), 258 deletions(-)
create mode 100644 src/lib/dns/rdata/generic/detail/nsec_bitmap.cc
create mode 100644 src/lib/dns/rdata/generic/detail/nsec_bitmap.h
copy src/lib/dns/tests/{rdata_nsec_unittest.cc => rdata_nsecbitmap_unittest.cc} (61%)
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec
delete mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire2
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec
copy src/lib/dns/tests/testdata/{rdata_nsec_fromWire5.spec => rdata_nsec3_fromWire5.spec} (56%)
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec
copy src/lib/dns/tests/testdata/{rdata_nsec_fromWire7.spec => rdata_nsec3_fromWire7.spec} (54%)
copy src/lib/dns/tests/testdata/{rdata_nsec_fromWire8.spec => rdata_nsec3_fromWire8.spec} (51%)
create mode 100644 src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec
-----------------------------------------------------------------------
diff --git a/src/lib/dns/Makefile.am b/src/lib/dns/Makefile.am
index 4b1a64b..c5c5cd1 100644
--- a/src/lib/dns/Makefile.am
+++ b/src/lib/dns/Makefile.am
@@ -85,6 +85,8 @@ libdns___la_SOURCES += rrtype.cc
libdns___la_SOURCES += question.h question.cc
libdns___la_SOURCES += util/sha1.h util/sha1.cc
libdns___la_SOURCES += tsigkey.h tsigkey.cc
+libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
+libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
nodist_libdns___la_SOURCES = rdataclass.cc rrclass.h rrtype.h
nodist_libdns___la_SOURCES += rrparamregistry.cc
@@ -117,5 +119,6 @@ libdns___include_HEADERS = \
tsigkey.h
# Purposely not installing these headers:
# util/*.h: used only internally, and not actually DNS specific
+# rdata/*/detail/*.h: these are internal use only
# rrclass-placeholder.h
# rrtype-placeholder.h
diff --git a/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc b/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc
new file mode 100644
index 0000000..a72058f
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc
@@ -0,0 +1,78 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <stdint.h>
+
+#include <vector>
+
+#include <dns/exceptions.h>
+
+using namespace std;
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+namespace detail {
+namespace nsec {
+void
+checkRRTypeBitmaps(const char* const rrtype_name,
+ const vector<uint8_t>& typebits)
+{
+ bool first = true;
+ unsigned int lastblock = 0;
+ const size_t total_len = typebits.size();
+ size_t i = 0;
+
+ while (i < total_len) {
+ if (i + 2 > total_len) {
+ isc_throw(DNSMessageFORMERR, rrtype_name <<
+ " RDATA from wire: incomplete bit map field");
+ }
+ const unsigned int block = typebits[i];
+ const size_t len = typebits[i + 1];
+ // Check that bitmap window blocks are in the correct order.
+ if (!first && block <= lastblock) {
+ isc_throw(DNSMessageFORMERR, rrtype_name <<
+ " RDATA from wire: Disordered window blocks found: "
+ << lastblock << " then " << block);
+ }
+ // Check for legal length
+ if (len < 1 || len > 32) {
+ isc_throw(DNSMessageFORMERR, rrtype_name <<
+ " RDATA from wire: Invalid bitmap length: " << len);
+ }
+ // Check for overflow.
+ i += 2;
+ if (i + len > total_len) {
+ isc_throw(DNSMessageFORMERR, rrtype_name <<
+ " RDATA from wire: bitmap length too large: " << len);
+ }
+ // The last octet of the bitmap must be non zero.
+ if (typebits[i + len - 1] == 0) {
+ isc_throw(DNSMessageFORMERR, rrtype_name <<
+ " RDATA from wire: bitmap ending an all-zero byte");
+ }
+
+ i += len;
+ lastblock = block;
+ first = false;
+ }
+}
+}
+}
+}
+}
+}
+}
diff --git a/src/lib/dns/rdata/generic/detail/nsec_bitmap.h b/src/lib/dns/rdata/generic/detail/nsec_bitmap.h
new file mode 100644
index 0000000..6431e10
--- /dev/null
+++ b/src/lib/dns/rdata/generic/detail/nsec_bitmap.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <stdint.h>
+
+#include <vector>
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+namespace detail {
+namespace nsec {
+/// Check if a given "type bitmap" for NSEC/NSEC3 is valid.
+///
+/// This helper function checks given wire format data (stored in a
+/// \c std::vector) is a valid type bitmaps used for the NSEC and NSEC3 RRs
+/// according to RFC4034 and RFC5155. The validation logic is the same
+/// for these two RRs, so a unified check function is provided.
+/// This function is essentially private and is only expected to be called
+/// from the \c NSEC and \c NSEC3 class implementations.
+///
+/// \exception DNSMessageFORMERR The bitmap is not valid.
+///
+/// \param rrtype_name Either "NSEC" or "NSEC3"; used as part of exception
+/// messages.
+/// \param typebits The type bitmaps in wire format. The size of vector
+/// is the total length of the bitmaps.
+void checkRRTypeBitmaps(const char* const rrtype_name,
+ const std::vector<uint8_t>& typebits);
+}
+}
+}
+}
+}
+}
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/src/lib/dns/rdata/generic/nsec3_50.cc b/src/lib/dns/rdata/generic/nsec3_50.cc
index c20fda2..01ffefa 100644
--- a/src/lib/dns/rdata/generic/nsec3_50.cc
+++ b/src/lib/dns/rdata/generic/nsec3_50.cc
@@ -30,11 +30,13 @@
#include <dns/rrttl.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/nsec_bitmap.h>
#include <stdio.h>
#include <time.h>
using namespace std;
+using namespace isc::dns::rdata::generic::detail::nsec;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
@@ -61,36 +63,57 @@ NSEC3::NSEC3(const string& nsec3_str) :
{
istringstream iss(nsec3_str);
unsigned int hashalg, flags, iterations;
- string salthex;
+ string iterations_str, salthex, nexthash;
- iss >> hashalg >> flags >> iterations >> salthex;
+ iss >> hashalg >> flags >> iterations_str >> salthex >> nexthash;
if (iss.bad() || iss.fail()) {
- isc_throw(InvalidRdataText, "Invalid NSEC3 text");
+ isc_throw(InvalidRdataText, "Invalid NSEC3 text: " << nsec3_str);
}
- if (hashalg > 0xf) {
- isc_throw(InvalidRdataText, "NSEC3 hash algorithm out of range");
+ if (hashalg > 0xff) {
+ isc_throw(InvalidRdataText,
+ "NSEC3 hash algorithm out of range: " << hashalg);
}
if (flags > 0xff) {
- isc_throw(InvalidRdataText, "NSEC3 flags out of range");
+ isc_throw(InvalidRdataText, "NSEC3 flags out of range: " << flags);
+ }
+ // Convert iteration. To reject an invalid case where there's no space
+ // between iteration and salt, we extract this field as string and convert
+ // to integer.
+ try {
+ iterations = boost::lexical_cast<unsigned int>(iterations_str);
+ } catch (const boost::bad_lexical_cast&) {
+ isc_throw(InvalidRdataText, "Bad NSEC3 iteration: " << iterations_str);
}
if (iterations > 0xffff) {
- isc_throw(InvalidRdataText, "NSEC3 iterations out of range");
+ isc_throw(InvalidRdataText, "NSEC3 iterations out of range: " <<
+ iterations);
}
vector<uint8_t> salt;
- decodeHex(salthex, salt);
+ if (salthex != "-") { // "-" means a 0-length salt
+ decodeHex(salthex, salt);
+ }
+ if (salt.size() > 255) {
+ isc_throw(InvalidRdataText, "NSEC3 salt is too long: "
+ << salt.size() << " bytes");
+ }
- string nextstr;
- iss >> setw(32) >> nextstr;
vector<uint8_t> next;
- if (iss.bad() || iss.fail()) {
- isc_throw(InvalidRdataText, "Invalid NSEC3 hash algorithm");
+ decodeBase32Hex(nexthash, next);
+ if (next.size() > 255) {
+ isc_throw(InvalidRdataText, "NSEC3 hash is too long: "
+ << next.size() << " bytes");
}
- decodeBase32Hex(nextstr, next);
- uint8_t bitmap[8 * 1024]; // 64k bits
- vector<uint8_t> typebits;
+ // For NSEC3 empty bitmap is possible and allowed.
+ if (iss.eof()) {
+ impl_ = new NSEC3Impl(hashalg, flags, iterations, salt, next,
+ vector<uint8_t>());
+ return;
+ }
+ vector<uint8_t> typebits;
+ uint8_t bitmap[8 * 1024]; // 64k bits
memset(bitmap, 0, sizeof(bitmap));
do {
string type;
@@ -104,7 +127,7 @@ NSEC3::NSEC3(const string& nsec3_str) :
isc_throw(InvalidRdataText, "Invalid RRtype in NSEC3");
}
}
- } while(!iss.eof());
+ } while (!iss.eof());
for (int window = 0; window < 256; window++) {
int octet;
@@ -126,56 +149,46 @@ NSEC3::NSEC3(const string& nsec3_str) :
}
NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) {
+ // NSEC3 RR must have at least 5 octets:
+ // hash algorithm(1), flags(1), iteration(2), saltlen(1)
if (rdata_len < 5) {
- isc_throw(InvalidRdataLength, "NSEC3 too short");
+ isc_throw(DNSMessageFORMERR, "NSEC3 too short, length: " << rdata_len);
}
- uint8_t hashalg = buffer.readUint8();
- uint8_t flags = buffer.readUint8();
- uint16_t iterations = buffer.readUint16();
- rdata_len -= 4;
-
- uint8_t saltlen = buffer.readUint8();
- --rdata_len;
+ const uint8_t hashalg = buffer.readUint8();
+ const uint8_t flags = buffer.readUint8();
+ const uint16_t iterations = buffer.readUint16();
+ const uint8_t saltlen = buffer.readUint8();
+ rdata_len -= 5;
if (rdata_len < saltlen) {
- isc_throw(InvalidRdataLength, "NSEC3 salt too short");
+ isc_throw(DNSMessageFORMERR, "NSEC3 salt length is too large: " <<
+ static_cast<unsigned int>(saltlen));
}
vector<uint8_t> salt(saltlen);
- buffer.readData(&salt[0], saltlen);
- rdata_len -= saltlen;
+ if (saltlen > 0) {
+ buffer.readData(&salt[0], saltlen);
+ rdata_len -= saltlen;
+ }
- uint8_t nextlen = buffer.readUint8();
+ const uint8_t nextlen = buffer.readUint8();
--rdata_len;
-
- if (rdata_len < nextlen) {
- isc_throw(InvalidRdataLength, "NSEC3 next hash too short");
+ if (nextlen == 0 || rdata_len < nextlen) {
+ isc_throw(DNSMessageFORMERR, "NSEC3 invalid hash length: " <<
+ static_cast<unsigned int>(nextlen));
}
vector<uint8_t> next(nextlen);
buffer.readData(&next[0], nextlen);
rdata_len -= nextlen;
- if (rdata_len == 0) {
- isc_throw(InvalidRdataLength, "NSEC3 type bitmap too short");
- }
-
vector<uint8_t> typebits(rdata_len);
- buffer.readData(&typebits[0], rdata_len);
-
- int len = 0;
- for (int i = 0; i < typebits.size(); i += len) {
- if (i + 2 > typebits.size()) {
- isc_throw(DNSMessageFORMERR, "Invalid rdata: "
- "bad NSEC3 type bitmap");
- }
- len = typebits[i + 1];
- if (len > 31) {
- isc_throw(DNSMessageFORMERR, "Invalid rdata: "
- "bad NSEC3 type bitmap");
- }
- i += 2;
+ if (rdata_len > 0) {
+ // Read and parse the bitmaps only when they exist; empty bitmap
+ // is possible for NSEC3.
+ buffer.readData(&typebits[0], rdata_len);
+ checkRRTypeBitmaps("NSEC3", typebits);
}
impl_ = new NSEC3Impl(hashalg, flags, iterations, salt, next, typebits);
@@ -327,10 +340,15 @@ NSEC3::getIterations() const {
return (impl_->iterations_);
}
-vector<uint8_t>&
+const vector<uint8_t>&
NSEC3::getSalt() const {
return (impl_->salt_);
}
+const vector<uint8_t>&
+NSEC3::getNext() const {
+ return (impl_->next_);
+}
+
// END_RDATA_NAMESPACE
// END_ISC_NAMESPACE
diff --git a/src/lib/dns/rdata/generic/nsec3_50.h b/src/lib/dns/rdata/generic/nsec3_50.h
index 5532071..c766ade 100644
--- a/src/lib/dns/rdata/generic/nsec3_50.h
+++ b/src/lib/dns/rdata/generic/nsec3_50.h
@@ -43,7 +43,8 @@ public:
uint8_t getHashalg() const;
uint8_t getFlags() const;
uint16_t getIterations() const;
- std::vector<uint8_t>& getSalt() const;
+ const std::vector<uint8_t>& getSalt() const;
+ const std::vector<uint8_t>& getNext() const;
private:
NSEC3Impl* impl_;
diff --git a/src/lib/dns/rdata/generic/nsec_47.cc b/src/lib/dns/rdata/generic/nsec_47.cc
index 0859edd..5d92528 100644
--- a/src/lib/dns/rdata/generic/nsec_47.cc
+++ b/src/lib/dns/rdata/generic/nsec_47.cc
@@ -26,11 +26,13 @@
#include <dns/rrttl.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
+#include <dns/rdata/generic/detail/nsec_bitmap.h>
#include <stdio.h>
#include <time.h>
using namespace std;
+using namespace isc::dns::rdata::generic::detail::nsec;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
@@ -103,43 +105,7 @@ NSEC::NSEC(InputBuffer& buffer, size_t rdata_len) {
vector<uint8_t> typebits(rdata_len);
buffer.readData(&typebits[0], rdata_len);
-
- int len = 0;
- bool first = true;
- unsigned int block, lastblock = 0;
- for (int i = 0; i < rdata_len; i += len) {
- if (i + 2 > rdata_len) {
- isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: "
- "incomplete bit map field");
- }
- block = typebits[i];
- len = typebits[i + 1];
- // Check that bitmap window blocks are in the correct order.
- if (!first && block <= lastblock) {
- isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: Disordered "
- "window blocks found: " << lastblock <<
- " then " << block);
- }
- // Check for legal length
- if (len < 1 || len > 32) {
- isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: Invalid bitmap "
- "length: " << len);
- }
- // Check for overflow.
- i += 2;
- if (i + len > rdata_len) {
- isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: bitmap length "
- "too large: " << len);
- }
- // The last octet of the bitmap must be non zero.
- if (typebits[i + len - 1] == 0) {
- isc_throw(DNSMessageFORMERR, "NSEC RDATA from wire: bitmap ending "
- "an all-zero byte");
- }
-
- lastblock = block;
- first = false;
- }
+ checkRRTypeBitmaps("NSEC", typebits);
impl_ = new NSECImpl(nextname, typebits);
}
diff --git a/src/lib/dns/tests/Makefile.am b/src/lib/dns/tests/Makefile.am
index 48e4650..246adb7 100644
--- a/src/lib/dns/tests/Makefile.am
+++ b/src/lib/dns/tests/Makefile.am
@@ -36,6 +36,7 @@ run_unittests_SOURCES += rdata_dnskey_unittest.cc
run_unittests_SOURCES += rdata_ds_unittest.cc
run_unittests_SOURCES += rdata_nsec_unittest.cc
run_unittests_SOURCES += rdata_nsec3_unittest.cc
+run_unittests_SOURCES += rdata_nsecbitmap_unittest.cc
run_unittests_SOURCES += rdata_nsec3param_unittest.cc
run_unittests_SOURCES += rdata_rrsig_unittest.cc
run_unittests_SOURCES += rdata_tsig_unittest.cc
diff --git a/src/lib/dns/tests/rdata_nsec3_unittest.cc b/src/lib/dns/tests/rdata_nsec3_unittest.cc
index 6b3a0b5..749e262 100644
--- a/src/lib/dns/tests/rdata_nsec3_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec3_unittest.cc
@@ -46,59 +46,136 @@ public:
string nsec3_txt;
};
+TEST_F(Rdata_NSEC3_Test, fromText) {
+ // A normal case: the test constructor should successfully parse the
+ // text and construct nsec3_txt. It will be tested against the wire format
+ // representation in the createFromWire test.
+
+ // Numeric parameters have possible maximum values. Unusual, but must
+ // be accepted.
+ EXPECT_NO_THROW(generic::NSEC3("255 255 65535 D399EAAB "
+ "H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+ "NS SOA RRSIG DNSKEY NSEC3PARAM"));
+
+ // 0-length salt
+ EXPECT_EQ(0, generic::NSEC3("1 1 1 - H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+ "A").getSalt().size());
+
+ // salt that has the possible max length
+ EXPECT_EQ(255, generic::NSEC3("1 1 1 " + string(255 * 2, '0') +
+ " H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+ "NS").getSalt().size());
+
+ // hash that has the possible max length (see badText about the magic
+ // numbers)
+ EXPECT_EQ(255, generic::NSEC3("1 1 1 D399EAAB " +
+ string((255 * 8) / 5, '0') +
+ " NS").getNext().size());
+
+ // type bitmap is empty. it's possible and allowed for NSEC3.
+ EXPECT_NO_THROW(generic::NSEC3(
+ "1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6"));
+}
+
TEST_F(Rdata_NSEC3_Test, toText) {
const generic::NSEC3 rdata_nsec3(nsec3_txt);
EXPECT_EQ(nsec3_txt, rdata_nsec3.toText());
}
TEST_F(Rdata_NSEC3_Test, badText) {
- EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEEE "
- "0123456789ABCDEFGHIJKLMNOPQRSTUV "
- "BIFF POW SPOON"),
+ EXPECT_THROW(generic::NSEC3("1 1 1 ADDAFEEE "
+ "0123456789ABCDEFGHIJKLMNOPQRSTUV "
+ "BIFF POW SPOON"),
InvalidRdataText);
- EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEE "
- "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW "
- "A NS SOA"),
+ EXPECT_THROW(generic::NSEC3("1 1 1 ADDAFEE "
+ "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW A NS SOA"),
BadValue); // bad hex
- EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1 ADDAFEEE "
- "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW "
- "A NS SOA"),
+ EXPECT_THROW(generic::NSEC3("1 1 1 -- H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
+ "A"),
+ BadValue); // this shouldn't be confused a valid empty salt
+ EXPECT_THROW(generic::NSEC3("1 1 1 ADDAFEEE "
+ "WXYZWXYZWXYZ=WXYZWXYZ==WXYZWXYZW A NS SOA"),
BadValue); // bad base32hex
- EXPECT_THROW(generic::NSEC3 rdata_nsec3("1000000 1 1 ADDAFEEE "
- "0123456789ABCDEFGHIJKLMNOPQRSTUV "
- "A NS SOA"),
+ EXPECT_THROW(generic::NSEC3("1000000 1 1 ADDAFEEE "
+ "0123456789ABCDEFGHIJKLMNOPQRSTUV A NS SOA"),
InvalidRdataText);
- EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1000000 1 ADDAFEEE "
- "0123456789ABCDEFGHIJKLMNOPQRSTUV "
- "A NS SOA"),
+ EXPECT_THROW(generic::NSEC3("1 1000000 1 ADDAFEEE "
+ "0123456789ABCDEFGHIJKLMNOPQRSTUV A NS SOA"),
InvalidRdataText);
- EXPECT_THROW(generic::NSEC3 rdata_nsec3("1 1 1000000 ADDAFEEE "
- "0123456789ABCDEFGHIJKLMNOPQRSTUV "
- "A NS SOA"),
+ EXPECT_THROW(generic::NSEC3("1 1 1000000 ADDAFEEE "
+ "0123456789ABCDEFGHIJKLMNOPQRSTUV A NS SOA"),
InvalidRdataText);
-}
-TEST_F(Rdata_NSEC3_Test, DISABLED_badText) { // this currently fails
+ // There should be a space between "1" and "D399EAAB" (salt)
EXPECT_THROW(generic::NSEC3(
"1 1 1D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 "
"NS SOA RRSIG DNSKEY NSEC3PARAM"), InvalidRdataText);
+
+ // Salt is too long (possible max + 1 bytes)
+ EXPECT_THROW(generic::NSEC3("1 1 1 " + string(256 * 2, '0') +
+ " H9RSFB7FPF2L8HG35CMPC765TDK23RP6 NS"),
+ InvalidRdataText);
+
+ // Hash is too long. Max = 255 bytes, base32-hex converts each 5 bytes
+ // of the original to 8 characters, so 260 * 8 / 5 is the smallest length
+ // of the encoded string that exceeds the max and doesn't require padding.
+ EXPECT_THROW(generic::NSEC3("1 1 1 D399EAAB " + string((260 * 8) / 5, '0') +
+ " NS"),
+ InvalidRdataText);
}
TEST_F(Rdata_NSEC3_Test, createFromWire) {
+ // Normal case
const generic::NSEC3 rdata_nsec3(nsec3_txt);
EXPECT_EQ(0, rdata_nsec3.compare(
*rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
"rdata_nsec3_fromWire1")));
- // Too short RDLENGTH
+ // A valid NSEC3 RR with empty type bitmap.
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire15.wire"));
+
+ // Too short RDLENGTH: it doesn't even contain the first 5 octets.
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
- "rdata_nsec3_fromWire2"),
- InvalidRdataLength);
+ "rdata_nsec3_fromWire2.wire"),
+ DNSMessageFORMERR);
+
+ // Invalid bitmap cases are tested in Rdata_NSECBITMAP_Test.
- // Invalid type bits
+ // salt length is too large
EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
- "rdata_nsec3_fromWire3"),
+ "rdata_nsec3_fromWire11.wire"),
DNSMessageFORMERR);
+
+ // empty salt. unusual, but valid.
+ ConstRdataPtr rdata =
+ rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire13.wire");
+ EXPECT_EQ(0, dynamic_cast<const generic::NSEC3&>(*rdata).getSalt().size());
+
+ // hash length is too large
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire12.wire"),
+ DNSMessageFORMERR);
+
+ // empty hash. invalid.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire14.wire"),
+ DNSMessageFORMERR);
+
+ //
+ // Short buffer cases. The data is valid NSEC3 RDATA, but the buffer
+ // is trimmed at the end. All cases should result in an exception from
+ // the buffer class.
+ vector<uint8_t> data;
+ UnitTestUtil::readWireData("rdata_nsec3_fromWire1", data);
+ const uint16_t rdlen = (data.at(0) << 8) + data.at(1);
+ for (int i = 0; i < rdlen; ++i) {
+ // intentionally construct a short buffer
+ InputBuffer b(&data[0] + 2, i);
+ EXPECT_THROW(createRdata(RRType::NSEC3(), RRClass::IN(), b, 39),
+ InvalidBufferPosition);
+ }
}
TEST_F(Rdata_NSEC3_Test, toWireRenderer) {
diff --git a/src/lib/dns/tests/rdata_nsec_unittest.cc b/src/lib/dns/tests/rdata_nsec_unittest.cc
index f9ad027..8286dee 100644
--- a/src/lib/dns/tests/rdata_nsec_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec_unittest.cc
@@ -62,46 +62,7 @@ TEST_F(Rdata_NSEC_Test, createFromWire_NSEC) {
"rdata_nsec_fromWire2"),
DNSMessageFORMERR);
- EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire3"),
- DNSMessageFORMERR);
-
- // A malformed NSEC bitmap length field that could cause overflow.
- EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire4.wire"),
- DNSMessageFORMERR);
-
- // The bitmap field is incomplete (only the first byte is included)
- EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire5.wire"),
- DNSMessageFORMERR);
-
- // Bitmap length is 0, which is invalid.
- EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire6.wire"),
- DNSMessageFORMERR);
-
- // A boundary case: longest possible bitmaps (32 maps). This should be
- // accepted.
- EXPECT_NO_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire7.wire"));
-
- // Another boundary condition: 33 bitmaps, which should be rejected.
- EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire8.wire"),
- DNSMessageFORMERR);
-
- // Disordered bitmap window blocks.
- EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire9.wire"),
- DNSMessageFORMERR);
-
- // Bitmap ending with all-zero bytes. Not necessarily harmful except
- // the additional overhead of parsing, but invalid according to the
- // spec anyway.
- EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
- "rdata_nsec_fromWire10.wire"),
- DNSMessageFORMERR);
+ // Invalid bitmap cases are tested in Rdata_NSECBITMAP_Test.
}
TEST_F(Rdata_NSEC_Test, toWireRenderer_NSEC) {
diff --git a/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc
new file mode 100644
index 0000000..8a90878
--- /dev/null
+++ b/src/lib/dns/tests/rdata_nsecbitmap_unittest.cc
@@ -0,0 +1,103 @@
+// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <dns/exceptions.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/rdata_unittest.h>
+
+using namespace isc::dns;
+using namespace isc::dns::rdata;
+
+namespace {
+class Rdata_NSECBITMAP_Test : public RdataTest {
+ // there's nothing to specialize
+};
+
+// Tests against various types of bogus NSEC/NSEC3 type bitmaps.
+// The syntax and semantics are common for both RR types, and our
+// implementation of that part is shared, so in theory it should be sufficient
+// to test for only one RR type. But we check for both just in case.
+TEST_F(Rdata_NSECBITMAP_Test, createFromWire_NSEC) {
+ // A malformed NSEC bitmap length field that could cause overflow.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire4.wire"),
+ DNSMessageFORMERR);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire4.wire"),
+ DNSMessageFORMERR);
+
+ // The bitmap field is incomplete (only the first byte is included)
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire5.wire"),
+ DNSMessageFORMERR);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire5.wire"),
+ DNSMessageFORMERR);
+
+ // Bitmap length is 0, which is invalid.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire6.wire"),
+ DNSMessageFORMERR);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire6.wire"),
+ DNSMessageFORMERR);
+
+ // Too large bitmap length with a short buffer.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire3"),
+ DNSMessageFORMERR);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire3"),
+ DNSMessageFORMERR);
+
+ // A boundary case: longest possible bitmaps (32 maps). This should be
+ // accepted.
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire7.wire"));
+ EXPECT_NO_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire7.wire"));
+
+ // Another boundary condition: 33 bitmaps, which should be rejected.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire8.wire"),
+ DNSMessageFORMERR);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire8.wire"),
+ DNSMessageFORMERR);
+
+ // Disordered bitmap window blocks.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire9.wire"),
+ DNSMessageFORMERR);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire9.wire"),
+ DNSMessageFORMERR);
+
+ // Bitmap ending with all-zero bytes. Not necessarily harmful except
+ // the additional overhead of parsing, but invalid according to the
+ // spec anyway.
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC(), RRClass::IN(),
+ "rdata_nsec_fromWire10.wire"),
+ DNSMessageFORMERR);
+ EXPECT_THROW(rdataFactoryFromFile(RRType::NSEC3(), RRClass::IN(),
+ "rdata_nsec3_fromWire10.wire"),
+ DNSMessageFORMERR);
+}
+}
diff --git a/src/lib/dns/tests/testdata/Makefile.am b/src/lib/dns/tests/testdata/Makefile.am
index f6eb90b..bbba8ed 100644
--- a/src/lib/dns/tests/testdata/Makefile.am
+++ b/src/lib/dns/tests/testdata/Makefile.am
@@ -8,9 +8,16 @@ BUILT_SOURCES += rdata_nsec_fromWire4.wire rdata_nsec_fromWire5.wire
BUILT_SOURCES += rdata_nsec_fromWire6.wire rdata_nsec_fromWire7.wire
BUILT_SOURCES += rdata_nsec_fromWire8.wire rdata_nsec_fromWire9.wire
BUILT_SOURCES += rdata_nsec_fromWire10.wire
+BUILT_SOURCES += rdata_nsec3_fromWire2.wire
+BUILT_SOURCES += rdata_nsec3_fromWire4.wire rdata_nsec3_fromWire5.wire
+BUILT_SOURCES += rdata_nsec3_fromWire6.wire rdata_nsec3_fromWire7.wire
+BUILT_SOURCES += rdata_nsec3_fromWire8.wire rdata_nsec3_fromWire9.wire
+BUILT_SOURCES += rdata_nsec3_fromWire10.wire rdata_nsec3_fromWire11.wire
+BUILT_SOURCES += rdata_nsec3_fromWire12.wire rdata_nsec3_fromWire13.wire
+BUILT_SOURCES += rdata_nsec3_fromWire14.wire rdata_nsec3_fromWire15.wire
BUILT_SOURCES += rdata_rrsig_fromWire2.wire
BUILT_SOURCES += rdata_soa_toWireUncompressed.wire
-BUILT_SOURCES += rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire
+BUILT_SOURCES += rdata_txt_fromWire2.wire rdata_txt_fromWire3.wire
BUILT_SOURCES += rdata_txt_fromWire4.wire rdata_txt_fromWire5.wire
BUILT_SOURCES += rdata_tsig_fromWire1.wire rdata_tsig_fromWire2.wire
BUILT_SOURCES += rdata_tsig_fromWire3.wire rdata_tsig_fromWire4.wire
@@ -44,13 +51,19 @@ EXTRA_DIST += question_fromWire question_toWire1 question_toWire2
EXTRA_DIST += rdata_cname_fromWire rdata_dname_fromWire rdata_dnskey_fromWire
EXTRA_DIST += rdata_ds_fromWire rdata_in_a_fromWire rdata_in_aaaa_fromWire
EXTRA_DIST += rdata_mx_fromWire rdata_mx_toWire1 rdata_ns_fromWire
-EXTRA_DIST += rdata_nsec3_fromWire1 rdata_nsec3_fromWire2 rdata_nsec3_fromWire3
-EXTRA_DIST += rdata_nsec3param_fromWire1 rdata_nsec_fromWire1
-EXTRA_DIST += rdata_nsec_fromWire2 rdata_nsec_fromWire3
+EXTRA_DIST += rdata_nsec_fromWire1 rdata_nsec_fromWire2 rdata_nsec_fromWire3
EXTRA_DIST += rdata_nsec_fromWire4.spec rdata_nsec_fromWire5.spec
EXTRA_DIST += rdata_nsec_fromWire6.spec rdata_nsec_fromWire7.spec
EXTRA_DIST += rdata_nsec_fromWire8.spec rdata_nsec_fromWire9.spec
EXTRA_DIST += rdata_nsec_fromWire10.spec
+EXTRA_DIST += rdata_nsec3param_fromWire1
+EXTRA_DIST += rdata_nsec3_fromWire1 rdata_nsec3_fromWire3
+EXTRA_DIST += rdata_nsec3_fromWire4.spec rdata_nsec3_fromWire5.spec
+EXTRA_DIST += rdata_nsec3_fromWire6.spec rdata_nsec3_fromWire7.spec
+EXTRA_DIST += rdata_nsec3_fromWire8.spec rdata_nsec3_fromWire9.spec
+EXTRA_DIST += rdata_nsec3_fromWire10.spec rdata_nsec3_fromWire11.spec
+EXTRA_DIST += rdata_nsec3_fromWire12.spec rdata_nsec3_fromWire13.spec
+EXTRA_DIST += rdata_nsec3_fromWire14.spec rdata_nsec3_fromWire15.spec
EXTRA_DIST += rdata_opt_fromWire rdata_rrsig_fromWire1
EXTRA_DIST += rdata_rrsig_fromWire2.spec
EXTRA_DIST += rdata_soa_fromWire rdata_soa_toWireUncompressed.spec
@@ -68,6 +81,7 @@ EXTRA_DIST += rdata_tsig_fromWire9.spec
EXTRA_DIST += rdata_tsig_toWire1.spec rdata_tsig_toWire2.spec
EXTRA_DIST += rdata_tsig_toWire3.spec rdata_tsig_toWire4.spec
EXTRA_DIST += rdata_tsig_toWire5.spec
+EXTRA_DIST += rdata_nsec3_fromWire2.spec
.spec.wire:
./gen-wiredata.py -o $@ $<
diff --git a/src/lib/dns/tests/testdata/gen-wiredata.py.in b/src/lib/dns/tests/testdata/gen-wiredata.py.in
index e59063f..645430c 100755
--- a/src/lib/dns/tests/testdata/gen-wiredata.py.in
+++ b/src/lib/dns/tests/testdata/gen-wiredata.py.in
@@ -52,8 +52,11 @@ rdict_rrclass = dict([(dict_rrclass[k], k.upper()) for k in \
dict_rrclass.keys()])
dict_algorithm = { 'rsamd5' : 1, 'dh' : 2, 'dsa' : 3, 'ecc' : 4,
'rsasha1' : 5 }
+dict_nsec3_algorithm = { 'reserved' : 0, 'sha1' : 1 }
rdict_algorithm = dict([(dict_algorithm[k], k.upper()) for k in \
dict_algorithm.keys()])
+rdict_nsec3_algorithm = dict([(dict_nsec3_algorithm[k], k.upper()) for k in \
+ dict_nsec3_algorithm.keys()])
header_xtables = { 'qr' : dict_qr, 'opcode' : dict_opcode,
'rcode' : dict_rcode }
@@ -274,14 +277,16 @@ class TXT:
' ' if len(wirestring_list[i]) > 0 else '',
wirestring_list[i]))
-class NSEC:
- rdlen = -1 # auto-calculate
- nextname = 'next.example.com'
+class NSECBASE:
+ '''Implements rendering NSEC/NSEC3 type bitmaps commonly used for
+ these RRs. The NSEC and NSEC3 classes will be inherited from this
+ class.'''
nbitmap = 1 # number of bitmaps
block = 0
- maplen = -1 # default bitmap length, auto-calculate
+ maplen = None # default bitmap length, auto-calculate
bitmap = '040000000003' # an arbtrarily chosen bitmap sample
def dump(self, f):
+ # first, construct the bitmpa data
block_list = []
maplen_list = []
bitmap_list = []
@@ -296,30 +301,72 @@ class NSEC:
maplen_list.append(self.__dict__[key_maplen])
else:
maplen_list.append(self.maplen)
- if maplen_list[-1] < 0:
+ if maplen_list[-1] is None: # calculate it if not specified
maplen_list[-1] = int(len(bitmap_list[-1]) / 2)
key_block = 'block' + str(i)
if key_block in self.__dict__:
block_list.append(self.__dict__[key_block])
else:
block_list.append(self.block)
+
+ # dump RR-type specific part (NSEC or NSEC3)
+ self.dump_fixedpart(f, 2 * self.nbitmap + \
+ int(len(''.join(bitmap_list)) / 2))
+
+ # dump the bitmap
+ for i in range(0, self.nbitmap):
+ f.write('# Bitmap: Block=%d, Length=%d\n' %
+ (block_list[i], maplen_list[i]))
+ f.write('%02x %02x %s\n' %
+ (block_list[i], maplen_list[i], bitmap_list[i]))
+
+class NSEC(NSECBASE):
+ rdlen = None # auto-calculate
+ nextname = 'next.example.com'
+ def dump_fixedpart(self, f, bitmap_totallen):
name_wire = encode_name(self.nextname)
- rdlen = self.rdlen
- if rdlen < 0:
+ if self.rdlen is None:
# if rdlen needs to be calculated, it must be based on the bitmap
# length, because the configured maplen can be fake.
- rdlen = int(len(name_wire) / 2) + 2 * self.nbitmap
- rdlen = rdlen + int(len(''.join(bitmap_list)) / 2)
- f.write('\n# NSEC RDATA (RDLEN=%d)\n' % rdlen)
- f.write('%04x\n' % rdlen);
+ self.rdlen = int(len(name_wire) / 2) + bitmap_totallen
+ f.write('\n# NSEC RDATA (RDLEN=%d)\n' % self.rdlen)
+ f.write('%04x\n' % self.rdlen);
f.write('# Next Name=%s (%d bytes)\n' % (self.nextname,
int(len(name_wire) / 2)))
f.write('%s\n' % name_wire)
- for i in range(0, self.nbitmap):
- f.write('# Bitmap: Block=%d, Length=%d\n' %
- (block_list[i], maplen_list[i]))
- f.write('%02x %02x %s\n' %
- (block_list[i], maplen_list[i], bitmap_list[i]))
+
+class NSEC3(NSECBASE):
+ rdlen = None # auto-calculate
+ hashalg = 1 # SHA-1
+ optout = False # opt-out flag
+ mbz = 0 # other flag fields (none defined yet)
+ iterations = 1
+ saltlen = 5
+ salt = 's' * saltlen
+ hashlen = 20
+ hash = 'h' * hashlen
+ def dump_fixedpart(self, f, bitmap_totallen):
+ if self.rdlen is None:
+ # if rdlen needs to be calculated, it must be based on the bitmap
+ # length, because the configured maplen can be fake.
+ self.rdlen = 4 + 1 + len(self.salt) + 1 + len(self.hash) \
+ + bitmap_totallen
+ f.write('\n# NSEC3 RDATA (RDLEN=%d)\n' % self.rdlen)
+ f.write('%04x\n' % self.rdlen)
+ optout_val = 1 if self.optout else 0
+ f.write('# Hash Alg=%s, Opt-Out=%d, Other Flags=%0x, Iterations=%d\n' %
+ (code_totext(self.hashalg, rdict_nsec3_algorithm),
+ optout_val, self.mbz, self.iterations))
+ f.write('%02x %02x %04x\n' %
+ (self.hashalg, (self.mbz << 1) | optout_val, self.iterations))
+ f.write("# Salt Len=%d, Salt='%s'\n" % (self.saltlen, self.salt))
+ f.write('%02x%s%s\n' % (self.saltlen,
+ ' ' if len(self.salt) > 0 else '',
+ encode_string(self.salt)))
+ f.write("# Hash Len=%d, Hash='%s'\n" % (self.hashlen, self.hash))
+ f.write('%02x%s%s\n' % (self.hashlen,
+ ' ' if len(self.hash) > 0 else '',
+ encode_string(self.hash)))
class RRSIG:
rdlen = -1 # auto-calculate
@@ -415,7 +462,7 @@ def get_config_param(section):
'question' : (DNSQuestion, question_xtables),
'edns' : (EDNS, {}), 'soa' : (SOA, {}), 'txt' : (TXT, {}),
'rrsig' : (RRSIG, {}), 'nsec' : (NSEC, {}),
- 'tsig' : (TSIG, {}) }
+ 'nsec3' : (NSEC3, {}), 'tsig' : (TSIG, {}) }
s = section
m = re.match('^([^:]+)/\d+$', section)
if m:
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec
new file mode 100644
index 0000000..39a78d7
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire1.spec
@@ -0,0 +1,7 @@
+#
+# A malformed NSEC3 RDATA: bit map length is too large, causing overflow
+#
+
+[custom]
+sections: nsec3
+[nsec3]
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec
new file mode 100644
index 0000000..30417f5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire10.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC3 RDATA: a bitmap block containing empty bytes
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+bitmap: '01000000'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec
new file mode 100644
index 0000000..80ec59f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire11.spec
@@ -0,0 +1,8 @@
+#
+# An invalid NSEC3 RDATA: Saltlen is too large
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 7
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec
new file mode 100644
index 0000000..1e01655
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire12.spec
@@ -0,0 +1,9 @@
+#
+# An invalid NSEC3 RDATA: Hash length is too large
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+# only contains the first byte of hash
+rdlen: 12
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec
new file mode 100644
index 0000000..fcc9d53
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire13.spec
@@ -0,0 +1,9 @@
+#
+# A valid (but unusual) NSEC3 RDATA: salt is empty.
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+saltlen: 0
+salt: ''
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec
new file mode 100644
index 0000000..a0550d5
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire14.spec
@@ -0,0 +1,9 @@
+#
+# An invalid NSEC3 RDATA: empty hash
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+hashlen: 0
+hash: ''
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec
new file mode 100644
index 0000000..4993e03
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire15.spec
@@ -0,0 +1,10 @@
+#
+# NSEC3 RDATA with empty type bitmap. It's okay.
+# The test data includes bytes for a bitmap field, but RDLEN indicates
+# it's not part of the RDATA and so it will be ignored.
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 31
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2 b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2
deleted file mode 100644
index 0965a27..0000000
--- a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# NSEC3 RDATA with a bogus RDLEN (too short)
-#
-
-# RDLENGTH, 29 bytes (should be 39)
-00 1e
-
-# NSEC3 record:
-# 1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6 NS SOA RRSIG DNSKEY NSEC3PARAM
-01 01 00 01 04 d3 99 ea ab 14 8a 77 c7 ac ef cb
-c5 54 46 03 2b 2d 96 1c c5 eb 68 21 ef 26 00 07
-22 00 00 00 00 02 90
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec
new file mode 100644
index 0000000..0b6a5af
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire2.spec
@@ -0,0 +1,9 @@
+#
+# A malformed NSEC3 RDATA: RDLEN indicates it doesn't even contain the fixed
+# 5 octects
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 4
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec
new file mode 100644
index 0000000..06d6eb4
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire4.spec
@@ -0,0 +1,9 @@
+#
+# A malformed NSEC3 RDATA: bit map length is too large, causing overflow
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+maplen: 31
+bitmap: '01'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.spec
new file mode 100644
index 0000000..2d5713c
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire5.spec
@@ -0,0 +1,13 @@
+#
+# A malformed NSEC3 RDATA: incomplete bit map field
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+# only containing the block field of the bitmap
+rdlen: 32
+#dummy data
+maplen: 31
+#dummy data
+bitmap: '00'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec
new file mode 100644
index 0000000..36e9e59
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire6.spec
@@ -0,0 +1,11 @@
+#
+# A malformed NSEC3 RDATA: bit map length being 0
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+rdlen: 33
+maplen: 0
+# dummy data:
+bitmap: '01'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.spec
new file mode 100644
index 0000000..338c0c9
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire7.spec
@@ -0,0 +1,9 @@
+#
+# NSEC3 RDATA with a longest bitmap field (32 bitmap bytes)
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+maplen: 32
+bitmap: '0101010101010101010101010101010101010101010101010101010101010101'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.spec
new file mode 100644
index 0000000..041714e
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire8.spec
@@ -0,0 +1,9 @@
+#
+# An invalid NSEC3 RDATA with an oversized bitmap field (33 bitmap bytes)
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+maplen: 33
+bitmap: '010101010101010101010101010101010101010101010101010101010101010101'
diff --git a/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec
new file mode 100644
index 0000000..b04c84f
--- /dev/null
+++ b/src/lib/dns/tests/testdata/rdata_nsec3_fromWire9.spec
@@ -0,0 +1,10 @@
+#
+# An invalid NSEC3 RDATA: disordered bitmap blocks
+#
+
+[custom]
+sections: nsec3
+[nsec3]
+nbitmap: 2
+block0: 2
+block1: 1
More information about the bind10-changes
mailing list