BIND 10 trac1580, updated. 11401abc34828a747f7dd716a1645b143efaf2f8 [1580] Add NSEC3 process for NXDOMAIN.
BIND 10 source code commits
bind10-changes at lists.isc.org
Tue Feb 14 02:21:00 UTC 2012
The branch, trac1580 has been updated
via 11401abc34828a747f7dd716a1645b143efaf2f8 (commit)
via 263d38ef6a1fe8bce1a229acc1cc14144d180c0a (commit)
from 0ad8fea24b58d05e8c57337c7b77f1b76be12015 (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 11401abc34828a747f7dd716a1645b143efaf2f8
Author: Xie Jiagui <xiejiagui at cnnic.cn>
Date: Tue Feb 14 10:19:42 2012 +0800
[1580] Add NSEC3 process for NXDOMAIN.
commit 263d38ef6a1fe8bce1a229acc1cc14144d180c0a
Author: Xie Jiagui <xiejiagui at cnnic.cn>
Date: Fri Feb 10 21:19:00 2012 +0800
[1580] Update NXDOMAIN case to support NSEC3.
-----------------------------------------------------------------------
Summary of changes:
src/bin/auth/query.cc | 53 ++++++++++++++++++++++++++++++++++
src/bin/auth/query.h | 16 ++++++++++
src/bin/auth/tests/query_unittest.cc | 30 +++++++++++++------
3 files changed, 89 insertions(+), 10 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc
index 7fe085e..c9db33f 100644
--- a/src/bin/auth/query.cc
+++ b/src/bin/auth/query.cc
@@ -167,6 +167,55 @@ Query::addNXDOMAINProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
}
}
+// Note: unless the data source client implementation or the zone content
+// is broken, 'nsec3' should be a valid NSEC3 RR. Likewise, the call to
+// findNSEC3() in this method should result an FindNSEC3Result that proves
+// the Closest Encloser Proof and non existent of matching wildcard.
+// If these assumptions aren't met due to a buggy data source implementation
+// or a broken zone, we'll let underlying libdns++ modules throw an exception,
+// which would result in either an SERVFAIL response or just ignoring the query.
+// We at least prevent a complete crash due to such broken behavior.
+void
+Query::addNSEC3NXDOMAINProof(ZoneFinder& finder) {
+ // Firstly get the NSEC3 proves for Closest Encloser Proof
+ const ZoneFinder::FindNSEC3Result fresult1 = finder.findNSEC3(qname_, true);
+ if (fresult1.closest_proof->getRdataCount() == 0) {
+ isc_throw(BadNSEC3,
+ "NSEC3 for NXDOMAIN proving that matches the closest encloser is empty.");
+ }
+ // Add the NSEC3 proving that matches the closest (provable) encloser.
+ response_.addRRset(Message::SECTION_AUTHORITY,
+ boost::const_pointer_cast<AbstractRRset>(fresult1.closest_proof),
+ dnssec_);
+ // Add the NSEC3 RR that covers the "next closer" name to the closest encloser
+ if (fresult1.next_proof) {
+ response_.addRRset(Message::SECTION_AUTHORITY,
+ boost::const_pointer_cast<AbstractRRset>(fresult1.next_proof),
+ dnssec_);
+ }
+ // Next, identify the best possible wildcard name that would match
+ // the query name. It's the longer common suffix with the qname
+ // between the owner or the next domain of the NSEC that proves NXDOMAIN,
+ // prefixed by the wildcard label, "*".
+ const Name wildname(Name("*").concatenate(qname_.split(1)));
+ const ZoneFinder::FindNSEC3Result fresult2 = finder.findNSEC3(wildname, false);
+ if (fresult2.closest_proof->getRdataCount() == 0) {
+ isc_throw(BadNSEC3,
+ "NSEC3 for NXDOMAIN covering the wildcard RR at the closest encloser is empty.");
+ }
+ // Add the (no-) wildcard proof only when it's different from the NSEC
+ // that proves NXDOMAIN; sometimes they can be the same.
+ // Note: name comparison is relatively expensive. When we are at the
+ // stage of performance optimization, we should consider optimizing this
+ // for some optimized data source implementations.
+ if (fresult1.next_proof->getName() != fresult2.closest_proof->getName()) {
+ response_.addRRset(Message::SECTION_AUTHORITY,
+ boost::const_pointer_cast<AbstractRRset>(fresult2.closest_proof),
+ dnssec_);
+
+ }
+}
+
void
Query::addWildcardProof(ZoneFinder& finder) {
// The query name shouldn't exist in the zone if there were no wildcard
@@ -403,6 +452,10 @@ Query::process() {
case ZoneFinder::NXDOMAIN:
response_.setRcode(Rcode::NXDOMAIN());
addSOA(*result.zone_finder);
+ if (dnssec_ && db_result.isNSEC3Signed()) {
+ addNSEC3NXDOMAINProof(zfinder);
+ break;
+ }
if (dnssec_ && db_result.rrset) {
addNXDOMAINProof(zfinder, db_result.rrset);
}
diff --git a/src/bin/auth/query.h b/src/bin/auth/query.h
index be98474..6d831ee 100644
--- a/src/bin/auth/query.h
+++ b/src/bin/auth/query.h
@@ -102,6 +102,11 @@ private:
/// This corresponds to Section 3.1.3.2 of RFC 4035.
void addNXDOMAINProof(isc::datasrc::ZoneFinder& finder,
isc::dns::ConstRRsetPtr nsec);
+
+ /// Add NSEC3 RRs that prove an NXDOMAIN result.
+ ///
+ /// This corresponds to Section 7.2.2 of RFC 5155.
+ void addNSEC3NXDOMAINProof(isc::datasrc::ZoneFinder& finder);
/// Add NSEC RRs that prove a wildcard answer is the best one.
///
@@ -270,6 +275,17 @@ public:
{}
};
+ /// An invalid result is given when a valid NSEC3 is expected
+ ///
+ /// This can only happen when the underlying data source implementation or
+ /// the zone is broken. By throwing an exception we treat such cases
+ /// as SERVFAIL.
+ struct BadNSEC3 : public BadZone {
+ BadNSEC3(const char* file, size_t line, const char* what) :
+ BadZone(file, line, what)
+ {}
+ };
+
/// An invalid result is given when a valid DS records (or NXRRSET) is
/// expected
///
diff --git a/src/bin/auth/tests/query_unittest.cc b/src/bin/auth/tests/query_unittest.cc
index d308faf..3873e55 100644
--- a/src/bin/auth/tests/query_unittest.cc
+++ b/src/bin/auth/tests/query_unittest.cc
@@ -260,6 +260,9 @@ public:
"q00jkcevqvmu85r014c7dkba38o0ji5r";
hash_map_[Name("nxdomain3.example.com")] =
"009mhaveqvm6t7vbl5lop2u3t2rp3tom";
+ hash_map_[Name("*.example.com")] =
+ "r53bq7cc2uvmubfu5ocmm6pers9tk9en";
+
}
virtual isc::dns::Name getOrigin() const { return (origin_); }
virtual isc::dns::RRClass getClass() const { return (rrclass_); }
@@ -1625,19 +1628,26 @@ TEST_F(QueryTest, findNSEC3) {
mock_finder->findNSEC3(Name("nxdomain3.example.com"), false));
}
-// The following are tentative tests until we really add tests for the
-// query logic for these cases. At that point it's probably better to
-// clean them up.
-TEST_F(QueryTest, nxdomainWithNSEC3) {
+TEST_F(QueryTest, nxdomainWithNSEC3Proof) {
mock_finder->setNSEC3Flag(true);
- ZoneFinder::FindResult result = mock_finder->find(
- Name("nxdomain.example.com"), RRType::A(), ZoneFinder::FIND_DNSSEC);
- EXPECT_EQ(ZoneFinder::NXDOMAIN, result.code);
- EXPECT_FALSE(result.rrset);
- EXPECT_TRUE(result.isNSEC3Signed());
- EXPECT_FALSE(result.isWildcard());
+ Query(memory_client, Name("nxdomain.example.com"), qtype,
+ response, true).process();
+ responseCheck(response, Rcode::NXDOMAIN(), AA_FLAG, 0, 6, 0,
+ NULL, (string(soa_txt) +
+ string("example.com. 3600 IN RRSIG ") +
+ getCommonRRSIGText("SOA") + "\n" +
+ string(nsec3_apex_txt) + "\n" +
+ string("0p9mhaveqvm6t7vbl5lop2u3t2rp3tom.example.com. 3600 IN RRSIG ") +
+ getCommonRRSIGText("NSEC3") + "\n" +
+ string(nsec3_www_txt) + "\n" +
+ string("q04jkcevqvmu85r014c7dkba38o0ji5r.example.com. 3600 IN RRSIG ") +
+ getCommonRRSIGText("NSEC3")).c_str(),
+ NULL, mock_finder->getOrigin());
}
+// The following are tentative tests until we really add tests for the
+// query logic for these cases. At that point it's probably better to
+// clean them up.
TEST_F(QueryTest, nxrrsetWithNSEC3) {
mock_finder->setNSEC3Flag(true);
ZoneFinder::FindResult result = mock_finder->find(
More information about the bind10-changes
mailing list