Commit 08127115 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1309] supported a simple case of wildcard + NSEC.

parent 2182b30e
......@@ -167,6 +167,16 @@ Query::addNXDOMAINProof(ZoneFinder& finder, ConstRRsetPtr nsec) {
}
}
void
Query::addWildcardProof(ZoneFinder& finder) {
const ZoneFinder::FindResult fresult =
finder.find(qname_, RRType::NSEC(), NULL,
dnssec_opt_ | ZoneFinder::NO_WILDCARD);
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(fresult.rrset),
dnssec_);
}
void
Query::addAuthAdditional(ZoneFinder& finder) {
// Fill in authority and addtional sections.
......@@ -273,6 +283,7 @@ Query::process() {
dnssec_);
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 +310,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);
......
......@@ -77,6 +77,9 @@ private:
void addNXDOMAINProof(isc::datasrc::ZoneFinder& finder,
isc::dns::ConstRRsetPtr nsec);
/// TBD
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.
///
......
......@@ -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. A 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,22 @@ 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)));
}
}
// 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 +847,26 @@ 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());
}
/*
* This tests that when there's no SOA and we need a negative answer. It should
* throw in that case.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment