BIND 10 master, updated. b7e1847c3a1979d3ac593de435e142335cbc7188 [master] Merge branch 'trac1309'
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Nov 2 18:12:38 UTC 2011
The branch, master has been updated
via b7e1847c3a1979d3ac593de435e142335cbc7188 (commit)
via b3af32e148d004ef5010d37eddccf6df57bdb257 (commit)
via 76bbf34210a5cf70853337a9a9f064c07c7aca76 (commit)
via d27f4125c99d13a7a73dee8c196a0d95050a4b62 (commit)
via 081271155ea18a33a135711a983e8882a2f56eea (commit)
from 1c8dfb0cdb80841bea487ee355ce85c749223810 (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 b7e1847c3a1979d3ac593de435e142335cbc7188
Merge: 1c8dfb0 b3af32e
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Wed Nov 2 11:09:53 2011 -0700
[master] Merge branch 'trac1309'
-----------------------------------------------------------------------
Summary of changes:
src/bin/auth/query.cc | 39 ++++++++++-
src/bin/auth/query.h | 5 ++
src/bin/auth/tests/query_unittest.cc | 122 +++++++++++++++++++++++++++++++++-
3 files changed, 161 insertions(+), 5 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/auth/query.cc b/src/bin/auth/query.cc
index 547a4ff..b2e0234 100644
--- a/src/bin/auth/query.cc
+++ b/src/bin/auth/query.cc
@@ -168,6 +168,24 @@ Query::addNXDOMAINProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
}
void
+Query::addWildcardProof(ZoneFinder& finder) {
+ // The query name shouldn't exist in the zone if there were no wildcard
+ // substitution. Confirm that by specifying NO_WILDCARD. It should result
+ // in NXDOMAIN and an NSEC RR that proves it should be returned.
+ const ZoneFinder::FindResult fresult =
+ finder.find(qname_, RRType::NSEC(), NULL,
+ dnssec_opt_ | ZoneFinder::NO_WILDCARD);
+ if (fresult.code != ZoneFinder::NXDOMAIN || !fresult.rrset ||
+ fresult.rrset->getRdataCount() == 0) {
+ isc_throw(BadNSEC, "Unexpected result for wildcard proof");
+ return;
+ }
+ response_.addRRset(Message::SECTION_AUTHORITY,
+ boost::const_pointer_cast<RRset>(fresult.rrset),
+ dnssec_);
+}
+
+void
Query::addAuthAdditional(ZoneFinder& finder) {
// Fill in authority and addtional sections.
ZoneFinder::FindResult ns_result = finder.find(finder.getOrigin(),
@@ -259,6 +277,7 @@ Query::process() {
break;
}
case ZoneFinder::CNAME:
+ case ZoneFinder::WILDCARD_CNAME:
/*
* We don't do chaining yet. Therefore handling a CNAME is
* mostly the same as handling SUCCESS, but we didn't get
@@ -271,8 +290,15 @@ Query::process() {
response_.addRRset(Message::SECTION_ANSWER,
boost::const_pointer_cast<RRset>(db_result.rrset),
dnssec_);
+
+ // If the answer is a result of wildcard substitution,
+ // add a proof that there's no closer name.
+ if (dnssec_ && db_result.code == ZoneFinder::WILDCARD_CNAME) {
+ addWildcardProof(*result.zone_finder);
+ }
break;
case ZoneFinder::SUCCESS:
+ case ZoneFinder::WILDCARD:
if (qtype_is_any) {
// If quety type is ANY, insert all RRs under the domain
// into answer section.
@@ -299,6 +325,12 @@ Query::process() {
{
addAuthAdditional(*result.zone_finder);
}
+
+ // If the answer is a result of wildcard substitution,
+ // add a proof that there's no closer name.
+ if (dnssec_ && db_result.code == ZoneFinder::WILDCARD) {
+ addWildcardProof(*result.zone_finder);
+ }
break;
case ZoneFinder::DELEGATION:
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
@@ -324,10 +356,9 @@ Query::process() {
}
break;
default:
- // These are new result codes (WILDCARD and WILDCARD_NXRRSET)
- // They should not happen from the in-memory and the database
- // backend isn't used yet.
- // TODO: Implement before letting the database backends in
+ // This is basically a bug of the data source implementation,
+ // but could also happen in the middle of development where
+ // we try to add a new result code.
isc_throw(isc::NotImplemented, "Unknown result code");
break;
}
diff --git a/src/bin/auth/query.h b/src/bin/auth/query.h
index f43dc77..3282c0d 100644
--- a/src/bin/auth/query.h
+++ b/src/bin/auth/query.h
@@ -77,6 +77,11 @@ private:
void addNXDOMAINProof(isc::datasrc::ZoneFinder& finder,
isc::dns::ConstRRsetPtr nsec);
+ /// Add NSEC RRs that prove a wildcard answer is the best one.
+ ///
+ /// This corresponds to Section 3.1.3.3 of RFC 4035.
+ void addWildcardProof(isc::datasrc::ZoneFinder& finder);
+
/// \brief Look up additional data (i.e., address records for the names
/// included in NS or MX records) and add them to the additional section.
///
diff --git a/src/bin/auth/tests/query_unittest.cc b/src/bin/auth/tests/query_unittest.cc
index 943c9ec..16a2409 100644
--- a/src/bin/auth/tests/query_unittest.cc
+++ b/src/bin/auth/tests/query_unittest.cc
@@ -92,6 +92,14 @@ const char* const other_zone_rrs =
"cnamemailer.example.com. 3600 IN CNAME www.example.com.\n"
"cnamemx.example.com. 3600 IN MX 10 cnamemailer.example.com.\n"
"mx.delegation.example.com. 3600 IN A 192.0.2.100\n";
+// Wildcards
+const char* const wild_txt = "*.wild.example.com. 3600 IN A 192.0.2.7\n";
+const char* const nsec_wild_txt =
+ "*.wild.example.com. 3600 IN NSEC www.example.com. A NSEC RRSIG\n";
+const char* const cnamewild_txt =
+ "*.cnamewild.example.com. 3600 IN CNAME www.example.org.\n";
+const char* const nsec_cnamewild_txt = "*.cnamewild.example.com. "
+ "3600 IN NSEC delegation.example.com. CNAME NSEC RRSIG\n";
// Used in NXDOMAIN proof test. We are going to test some unusual case where
// the best possible wildcard is below the "next domain" of the NSEC RR that
// proves the NXDOMAIN, i.e.,
@@ -170,7 +178,8 @@ public:
cname_nxdom_txt << cname_out_txt << dname_txt << dname_a_txt <<
other_zone_rrs << no_txt << nz_txt <<
nsec_apex_txt << nsec_mx_txt << nsec_no_txt << nsec_nz_txt <<
- nsec_nxdomain_txt << nsec_www_txt << nonsec_a_txt;
+ nsec_nxdomain_txt << nsec_www_txt << nonsec_a_txt <<
+ wild_txt << nsec_wild_txt << cnamewild_txt << nsec_cnamewild_txt;
masterLoad(zone_stream, origin_, rrclass_,
boost::bind(&MockZoneFinder::loadRRset, this, _1));
@@ -259,6 +268,24 @@ private:
boost::scoped_ptr<ZoneFinder::FindResult> nsec_result_;
};
+// A helper function that generates a new RRset based on "wild_rrset",
+// replacing its owner name with 'real_name'.
+ConstRRsetPtr
+substituteWild(const RRset& wild_rrset, const Name& real_name) {
+ RRsetPtr rrset(new RRset(real_name, wild_rrset.getClass(),
+ wild_rrset.getType(), wild_rrset.getTTL()));
+ // For simplicity we only consider the case with one RDATA (for now)
+ rrset->addRdata(wild_rrset.getRdataIterator()->getCurrent());
+ ConstRRsetPtr wild_sig = wild_rrset.getRRsig();
+ if (wild_sig) {
+ RRsetPtr sig(new RRset(real_name, wild_sig->getClass(),
+ wild_sig->getType(), wild_sig->getTTL()));
+ sig->addRdata(wild_sig->getRdataIterator()->getCurrent());
+ rrset->addRRsig(sig);
+ }
+ return (rrset);
+}
+
ZoneFinder::FindResult
MockZoneFinder::find(const Name& name, const RRType& type,
RRsetList* target, const FindOptions options)
@@ -365,6 +392,33 @@ MockZoneFinder::find(const Name& name, const RRType& type,
return (FindResult(NXRRSET, RRsetPtr()));
}
+ // Another possibility is wildcard. For simplicity we only check
+ // hardcoded specific cases, ignoring other details such as canceling
+ // due to the existence of closer name.
+ if ((options & NO_WILDCARD) == 0) {
+ const Name wild_suffix("wild.example.com");
+ if (name.compare(wild_suffix).getRelation() ==
+ NameComparisonResult::SUBDOMAIN) {
+ domain = domains_.find(Name("*").concatenate(wild_suffix));
+ assert(domain != domains_.end());
+ RRsetStore::const_iterator found_rrset = domain->second.find(type);
+ assert(found_rrset != domain->second.end());
+ return (FindResult(WILDCARD,
+ substituteWild(*found_rrset->second, name)));
+ }
+ const Name cnamewild_suffix("cnamewild.example.com");
+ if (name.compare(cnamewild_suffix).getRelation() ==
+ NameComparisonResult::SUBDOMAIN) {
+ domain = domains_.find(Name("*").concatenate(cnamewild_suffix));
+ assert(domain != domains_.end());
+ RRsetStore::const_iterator found_rrset =
+ domain->second.find(RRType::CNAME());
+ assert(found_rrset != domain->second.end());
+ return (FindResult(WILDCARD_CNAME,
+ substituteWild(*found_rrset->second, name)));
+ }
+ }
+
// This is an NXDOMAIN case.
// If we need DNSSEC proof, find the "previous name" that has an NSEC RR
// and return NXDOMAIN with the found NSEC. Otherwise, just return the
@@ -804,6 +858,72 @@ TEST_F(QueryTest, nxrrsetWithoutNSEC) {
NULL, mock_finder->getOrigin());
}
+TEST_F(QueryTest, wildcardNSEC) {
+ // The qname matches *.wild.example.com. The response should contain
+ // an NSEC that proves the non existence of a closer name.
+ Query(memory_client, Name("www.wild.example.com"), RRType::A(), response,
+ true).process();
+ responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 6, 6,
+ (string(wild_txt).replace(0, 1, "www") +
+ string("www.wild.example.com. 3600 IN RRSIG ") +
+ getCommonRRSIGText("A") + "\n").c_str(),
+ (zone_ns_txt + string("example.com. 3600 IN RRSIG NS 5 "
+ "3 3600 20000101000000 "
+ "20000201000000 12345 "
+ "example.com. FAKEFAKEFAKE\n") +
+ string(nsec_wild_txt) +
+ string("*.wild.example.com. 3600 IN RRSIG ") +
+ getCommonRRSIGText("NSEC") + "\n").c_str(),
+ NULL, // we are not interested in additionals in this test
+ mock_finder->getOrigin());
+}
+
+TEST_F(QueryTest, CNAMEwildNSEC) {
+ // Similar to the previous case, but the matching wildcard record is
+ // CNAME.
+ Query(memory_client, Name("www.cnamewild.example.com"), RRType::A(),
+ response, true).process();
+ responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 2, 0,
+ (string(cnamewild_txt).replace(0, 1, "www") +
+ string("www.cnamewild.example.com. 3600 IN RRSIG ") +
+ getCommonRRSIGText("CNAME") + "\n").c_str(),
+ (string(nsec_cnamewild_txt) +
+ string("*.cnamewild.example.com. 3600 IN RRSIG ") +
+ getCommonRRSIGText("NSEC") + "\n").c_str(),
+ NULL, // we are not interested in additionals in this test
+ mock_finder->getOrigin());
+}
+
+TEST_F(QueryTest, badWildcardProof1) {
+ // Unexpected case in wildcard proof: ZoneFinder::find() returns SUCCESS
+ // when NXDOMAIN is expected.
+ mock_finder->setNSECResult(Name("www.wild.example.com"),
+ ZoneFinder::SUCCESS,
+ mock_finder->delegation_rrset_);
+ EXPECT_THROW(Query(memory_client, Name("www.wild.example.com"),
+ RRType::A(), response, true).process(),
+ Query::BadNSEC);
+}
+
+TEST_F(QueryTest, badWildcardProof2) {
+ // "wildcard proof" doesn't return RRset.
+ mock_finder->setNSECResult(Name("www.wild.example.com"),
+ ZoneFinder::NXDOMAIN, ConstRRsetPtr());
+ EXPECT_THROW(Query(memory_client, Name("www.wild.example.com"),
+ RRType::A(), response, true).process(),
+ Query::BadNSEC);
+}
+
+TEST_F(QueryTest, badWildcardProof3) {
+ // "wildcard proof" returns empty NSEC.
+ mock_finder->setNSECResult(Name("www.wild.example.com"),
+ ZoneFinder::NXDOMAIN,
+ mock_finder->empty_nsec_rrset_);
+ EXPECT_THROW(Query(memory_client, Name("www.wild.example.com"),
+ RRType::A(), response, true).process(),
+ Query::BadNSEC);
+}
+
/*
* This tests that when there's no SOA and we need a negative answer. It should
* throw in that case.
More information about the bind10-changes
mailing list