BIND 10 trac2387, updated. 9926f9b8f9f9ed697975752c62a46e34bf45e3ca [2387] Add more NSEC3 unittests
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Mar 11 06:48:18 UTC 2013
The branch, trac2387 has been updated
via 9926f9b8f9f9ed697975752c62a46e34bf45e3ca (commit)
via 947d85d0e851a6fee3c34c734e3bd21065b57ca4 (commit)
via 61068e227821fa32305d4edd142b2dcc6ca74eb4 (commit)
via 2f41159cd685809c1dea5f079e99c5ecb90e1893 (commit)
via 8a91e6ec6c257a9e630e0408ac1a5f464d769a55 (commit)
via 240e5333012a0a60e9b42f8741c44450eae22ea2 (commit)
from 22362bbf67afbd7851f731f6bbd337333267a939 (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 9926f9b8f9f9ed697975752c62a46e34bf45e3ca
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon Mar 11 12:11:13 2013 +0530
[2387] Add more NSEC3 unittests
commit 947d85d0e851a6fee3c34c734e3bd21065b57ca4
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon Mar 11 12:04:34 2013 +0530
[2387] Fix empty bitmap case
commit 61068e227821fa32305d4edd142b2dcc6ca74eb4
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon Mar 11 11:48:26 2013 +0530
[2387] Remove now unused buildBitmapsFromText()
commit 2f41159cd685809c1dea5f079e99c5ecb90e1893
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon Mar 11 11:46:04 2013 +0530
[2387] Add namespace to argument's type
commit 8a91e6ec6c257a9e630e0408ac1a5f464d769a55
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon Mar 11 11:45:46 2013 +0530
[2387] Add NSEC3 string RDATA constructor
commit 240e5333012a0a60e9b42f8741c44450eae22ea2
Author: Mukund Sivaraman <muks at isc.org>
Date: Mon Mar 11 09:28:47 2013 +0530
[2387] Add NSEC3 lexer constructor implementation
-----------------------------------------------------------------------
Summary of changes:
src/lib/dns/gen-rdatacode.py.in | 1 +
.../dns/rdata/generic/detail/nsec3param_common.cc | 43 ++++++++++++++++
.../dns/rdata/generic/detail/nsec3param_common.h | 6 +++
src/lib/dns/rdata/generic/detail/nsec_bitmap.cc | 45 ----------------
src/lib/dns/rdata/generic/detail/nsec_bitmap.h | 23 ---------
src/lib/dns/rdata/generic/dnskey_48.h | 2 +-
src/lib/dns/rdata/generic/nsec3_50.cc | 54 +++++++++++++++-----
src/lib/dns/rdata/generic/nsec3_50.h | 3 ++
src/lib/dns/tests/rdata_nsec3_unittest.cc | 27 ++++++++++
9 files changed, 123 insertions(+), 81 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dns/gen-rdatacode.py.in b/src/lib/dns/gen-rdatacode.py.in
index 5c23eba..fac1bb1 100755
--- a/src/lib/dns/gen-rdatacode.py.in
+++ b/src/lib/dns/gen-rdatacode.py.in
@@ -43,6 +43,7 @@ new_rdata_factory_users = [('a', 'in'), ('aaaa', 'in'),
('mx', 'generic'),
('ns', 'generic'),
('nsec', 'generic'),
+ ('nsec3', 'generic'),
('ptr', 'generic'),
('soa', 'generic'),
('spf', 'generic'),
diff --git a/src/lib/dns/rdata/generic/detail/nsec3param_common.cc b/src/lib/dns/rdata/generic/detail/nsec3param_common.cc
index 6eea2c7..0ce6bca 100644
--- a/src/lib/dns/rdata/generic/detail/nsec3param_common.cc
+++ b/src/lib/dns/rdata/generic/detail/nsec3param_common.cc
@@ -89,6 +89,49 @@ parseNSEC3ParamText(const char* const rrtype_name,
}
ParseNSEC3ParamResult
+parseNSEC3ParamFromLexer(const char* const rrtype_name,
+ MasterLexer& lexer, vector<uint8_t>& salt)
+{
+ const uint32_t hashalg =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (hashalg > 0xff) {
+ isc_throw(InvalidRdataText, rrtype_name <<
+ " hash algorithm out of range: " << hashalg);
+ }
+
+ const uint32_t flags =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (flags > 0xff) {
+ isc_throw(InvalidRdataText, rrtype_name << " flags out of range: " <<
+ flags);
+ }
+
+ const uint32_t iterations =
+ lexer.getNextToken(MasterToken::NUMBER).getNumber();
+ if (iterations > 0xffff) {
+ isc_throw(InvalidRdataText, rrtype_name <<
+ " iterations out of range: " <<
+ iterations);
+ }
+
+ const string salthex =
+ lexer.getNextToken(MasterToken::STRING).getString();
+
+ // Salt is up to 255 bytes, and space is not allowed in the HEX encoding,
+ // so the encoded string cannot be longer than the double of max length
+ // of the actual salt.
+ if (salthex.size() > 255 * 2) {
+ isc_throw(InvalidRdataText, rrtype_name << " salt is too long: "
+ << salthex.size() << " (encoded) bytes");
+ }
+ if (salthex != "-") { // "-" means a 0-length salt
+ decodeHex(salthex, salt);
+ }
+
+ return (ParseNSEC3ParamResult(hashalg, flags, iterations));
+}
+
+ParseNSEC3ParamResult
parseNSEC3ParamWire(const char* const rrtype_name,
InputBuffer& buffer,
size_t& rdata_len, std::vector<uint8_t>& salt)
diff --git a/src/lib/dns/rdata/generic/detail/nsec3param_common.h b/src/lib/dns/rdata/generic/detail/nsec3param_common.h
index 1891fae..4d55ada 100644
--- a/src/lib/dns/rdata/generic/detail/nsec3param_common.h
+++ b/src/lib/dns/rdata/generic/detail/nsec3param_common.h
@@ -15,6 +15,8 @@
#ifndef NSEC3PARAM_COMMON_H
#define NSEC3PARAM_COMMON_H 1
+#include <dns/master_lexer.h>
+
#include <util/buffer.h>
#include <stdint.h>
@@ -90,6 +92,10 @@ ParseNSEC3ParamResult parseNSEC3ParamText(const char* const rrtype_name,
std::istringstream& iss,
std::vector<uint8_t>& salt);
+ParseNSEC3ParamResult parseNSEC3ParamFromLexer(const char* const rrtype_name,
+ isc::dns::MasterLexer& lexer,
+ std::vector<uint8_t>& salt);
+
/// \brief Extract NSEC3 parameters from wire-format data.
///
/// This function takes an input buffer that stores wire-format NSEC3 or
diff --git a/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc b/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc
index 319056e..5ca313c 100644
--- a/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc
+++ b/src/lib/dns/rdata/generic/detail/nsec_bitmap.cc
@@ -78,51 +78,6 @@ checkRRTypeBitmaps(const char* const rrtype_name,
}
void
-buildBitmapsFromText(const char* const rrtype_name,
- istringstream& iss, vector<uint8_t>& typebits)
-{
- uint8_t bitmap[8 * 1024]; // 64k bits
- memset(bitmap, 0, sizeof(bitmap));
-
- do {
- string type;
- iss >> type;
- if (iss.bad() || iss.fail()) {
- isc_throw(InvalidRdataText, "Unexpected input for "
- << rrtype_name << " bitmap");
- }
- try {
- const int code = RRType(type).getCode();
- bitmap[code / 8] |= (0x80 >> (code % 8));
- } catch (const InvalidRRType&) {
- isc_throw(InvalidRdataText, "Invalid RRtype in "
- << rrtype_name << " bitmap: " << type);
- }
- } while (!iss.eof());
-
- for (int window = 0; window < 256; ++window) {
- int octet;
- for (octet = 31; octet >= 0; octet--) {
- if (bitmap[window * 32 + octet] != 0) {
- break;
- }
- }
- if (octet < 0) {
- continue;
- }
- typebits.push_back(window);
- typebits.push_back(octet + 1);
- for (int i = 0; i <= octet; ++i) {
- typebits.push_back(bitmap[window * 32 + i]);
- }
- }
-}
-
-// Note: this function shares common code with buildBitmapsFromText()
-// above, but it is expected that buildBitmapsFromText() will be deleted
-// entirely once the transition to MasterLexer is done for all dependent
-// RR types. So a common method is not made from the two.
-void
buildBitmapsFromLexer(const char* const rrtype_name,
MasterLexer& lexer, vector<uint8_t>& typebits)
{
diff --git a/src/lib/dns/rdata/generic/detail/nsec_bitmap.h b/src/lib/dns/rdata/generic/detail/nsec_bitmap.h
index ea5cad0..7468225 100644
--- a/src/lib/dns/rdata/generic/detail/nsec_bitmap.h
+++ b/src/lib/dns/rdata/generic/detail/nsec_bitmap.h
@@ -54,29 +54,6 @@ namespace nsec {
void checkRRTypeBitmaps(const char* const rrtype_name,
const std::vector<uint8_t>& typebits);
-/// \brief Convert textual sequence of RR types into type bitmaps.
-///
-/// This function extracts a sequence of strings, converts each sequence
-/// into an RR type, and builds NSEC/NSEC3 type bitmaps with the corresponding
-/// bits for the extracted types being on. The resulting bitmaps (which are
-/// in the wire format according to RFC4034 and RFC5155) are stored in the
-/// given vector. This function expects the given string stream ends with
-/// the sequence.
-///
-/// \exception InvalidRdataText The given input stream does not meet the
-/// assumption (e.g. including invalid form of RR type, not ending with
-/// an RR type string).
-///
-/// \param rrtype_name Either "NSEC" or "NSEC3"; used as part of exception
-/// messages.
-/// \param iss Input stream that consists of a complete sequence of textual
-/// RR types for which the corresponding bits are set.
-/// \param typebits A placeholder for the resulting bitmaps. Expected to be
-/// empty, but it's not checked.
-void buildBitmapsFromText(const char* const rrtype_name,
- std::istringstream& iss,
- std::vector<uint8_t>& typebits);
-
/// \brief Convert textual sequence of RR types read from a lexer into
/// type bitmaps.
///
diff --git a/src/lib/dns/rdata/generic/dnskey_48.h b/src/lib/dns/rdata/generic/dnskey_48.h
index 1e48782..d8a6b4d 100644
--- a/src/lib/dns/rdata/generic/dnskey_48.h
+++ b/src/lib/dns/rdata/generic/dnskey_48.h
@@ -48,7 +48,7 @@ public:
uint8_t getAlgorithm() const;
private:
- void constructFromLexer(MasterLexer& lexer);
+ void constructFromLexer(isc::dns::MasterLexer& lexer);
DNSKEYImpl* impl_;
};
diff --git a/src/lib/dns/rdata/generic/nsec3_50.cc b/src/lib/dns/rdata/generic/nsec3_50.cc
index fb92246..cb312ec 100644
--- a/src/lib/dns/rdata/generic/nsec3_50.cc
+++ b/src/lib/dns/rdata/generic/nsec3_50.cc
@@ -67,21 +67,42 @@ struct NSEC3Impl {
NSEC3::NSEC3(const std::string& nsec3_str) :
impl_(NULL)
{
- istringstream iss(nsec3_str);
+ try {
+ std::istringstream ss(nsec3_str);
+ MasterLexer lexer;
+ lexer.pushSource(ss);
+
+ constructFromLexer(lexer);
+
+ if (lexer.getNextToken().getType() != MasterToken::END_OF_FILE) {
+ isc_throw(InvalidRdataText,
+ "Extra input text for NSEC3: " << nsec3_str);
+ }
+ } catch (const MasterLexer::LexerError& ex) {
+ isc_throw(InvalidRdataText,
+ "Failed to construct NSEC3 from '" << nsec3_str << "': "
+ << ex.what());
+ }
+}
+
+NSEC3::NSEC3(MasterLexer& lexer, const Name*, MasterLoader::Options,
+ MasterLoaderCallbacks&) :
+ impl_(NULL)
+{
+ constructFromLexer(lexer);
+}
+
+void
+NSEC3::constructFromLexer(MasterLexer& lexer) {
vector<uint8_t> salt;
const ParseNSEC3ParamResult params =
- parseNSEC3ParamText("NSEC3", nsec3_str, iss, salt);
+ parseNSEC3ParamFromLexer("NSEC3", lexer, salt);
- // Extract Next hash. It must be an unpadded base32hex string.
- string nexthash;
- iss >> nexthash;
- if (iss.bad() || iss.fail()) {
- isc_throw(InvalidRdataText, "Invalid NSEC3 text: " << nsec3_str);
- }
- assert(!nexthash.empty());
+ const string nexthash = lexer.getNextToken(MasterToken::STRING).getString();
if (*nexthash.rbegin() == '=') {
- isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nsec3_str);
+ isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nexthash);
}
+
vector<uint8_t> next;
decodeBase32Hex(nexthash, next);
if (next.size() > 255) {
@@ -90,7 +111,16 @@ NSEC3::NSEC3(const std::string& nsec3_str) :
}
// For NSEC3 empty bitmap is possible and allowed.
- if (iss.eof()) {
+ bool empty_bitmap = false;
+ const MasterToken token = lexer.getNextToken();
+ if ((token.getType() == MasterToken::END_OF_LINE) ||
+ (token.getType() == MasterToken::END_OF_FILE)) {
+ empty_bitmap = true;
+ }
+
+ lexer.ungetToken();
+
+ if (empty_bitmap) {
impl_ = new NSEC3Impl(params.algorithm, params.flags,
params.iterations, salt, next,
vector<uint8_t>());
@@ -98,7 +128,7 @@ NSEC3::NSEC3(const std::string& nsec3_str) :
}
vector<uint8_t> typebits;
- buildBitmapsFromText("NSEC3", iss, typebits);
+ buildBitmapsFromLexer("NSEC3", lexer, typebits);
impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations,
salt, next, typebits);
diff --git a/src/lib/dns/rdata/generic/nsec3_50.h b/src/lib/dns/rdata/generic/nsec3_50.h
index c766ade..0990bd5 100644
--- a/src/lib/dns/rdata/generic/nsec3_50.h
+++ b/src/lib/dns/rdata/generic/nsec3_50.h
@@ -21,6 +21,7 @@
#include <dns/rrtype.h>
#include <dns/rrttl.h>
#include <dns/rdata.h>
+#include <dns/master_lexer.h>
// BEGIN_HEADER_GUARD
@@ -47,6 +48,8 @@ public:
const std::vector<uint8_t>& getNext() const;
private:
+ void constructFromLexer(isc::dns::MasterLexer& lexer);
+
NSEC3Impl* impl_;
};
diff --git a/src/lib/dns/tests/rdata_nsec3_unittest.cc b/src/lib/dns/tests/rdata_nsec3_unittest.cc
index 0fec3eb..e459eaf 100644
--- a/src/lib/dns/tests/rdata_nsec3_unittest.cc
+++ b/src/lib/dns/tests/rdata_nsec3_unittest.cc
@@ -68,6 +68,9 @@ TEST_F(Rdata_NSEC3_Test, fromText) {
// type bitmap is empty. it's possible and allowed for NSEC3.
EXPECT_NO_THROW(generic::NSEC3(
"1 1 1 D399EAAB H9RSFB7FPF2L8HG35CMPC765TDK23RP6"));
+
+ // empty salt is also okay.
+ EXPECT_NO_THROW(const generic::NSEC3 rdata_nosalt_nsec3(nsec3_nosalt_txt));
}
TEST_F(Rdata_NSEC3_Test, badText) {
@@ -136,7 +139,31 @@ TEST_F(Rdata_NSEC3_Test, createFromLexer) {
*test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
nsec3_txt)));
+ // empty salt is also okay.
+ const generic::NSEC3 rdata_nosalt_nsec3(nsec3_nosalt_txt);
+ EXPECT_EQ(0, rdata_nosalt_nsec3.compare(
+ *test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+ nsec3_nosalt_txt)));
+
// Exceptions cause NULL to be returned.
+
+ // hash algorithm out of range
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+ "256 1 1 D399EAAB H9RSFB7FPF2L8"
+ "HG35CMPC765TDK23RP6"));
+ // flags out of range
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+ "1 256 1 D399EAAB H9RSFB7FPF2L8"
+ "HG35CMPC765TDK23RP6"));
+ // iterations out of range
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+ "1 1 65536 D399EAAB H9RSFB7FPF2L8"
+ "HG35CMPC765TDK23RP6"));
+ // space is not allowed in salt
+ EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
+ "1 1 1 D399 EAAB H9RSFB7FPF2L8"
+ "HG35CMPC765TDK23RP6"));
+ // Next hash is padded.
EXPECT_FALSE(test::createRdataUsingLexer(RRType::NSEC3(), RRClass::IN(),
"1 1 1 ADDAFEEE CPNMU=== "
"A NS SOA"));
More information about the bind10-changes
mailing list