Commit 1e1f5433 authored by Evan Hunt's avatar Evan Hunt
Browse files

Correctly handle NSEC and NSEC3 responses when answering with a

wildcard record.  (Unit tests to follow in the morning.)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1474 e5f2f494-b856-4b98-b285-d166d9295462
parent 3831ebf5
......@@ -344,7 +344,8 @@ getNsec3Param(Query& q, const DataSrc* ds, const Name& zonename) {
}
static inline DataSrc::Result
proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, const Name& zonename)
proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds,
const Name& zonename, const bool wildcard)
{
Message& m = q.message();
ConstNsec3ParamPtr nsec3 = getNsec3Param(q, ds, zonename);
......@@ -382,8 +383,13 @@ proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, const Name& zonename)
}
}
// Now add a covering NSEC3 for a wildcard under the
// closest provable enclosing name
// If we are processing a wildcard answer, we're done.
if (wildcard) {
return (DataSrc::SUCCESS);
}
// Otherwise, there is no wildcard record, so we must add a
// covering NSEC3 to prove that it doesn't exist.
string hash3(nsec3->getHash(Name("*").concatenate(enclosure)));
RETERR(getNsec3(ds, zonename, q.qclass(), hash3, rrset));
if (hash3 != hash1 && hash3 != hash2) {
......@@ -391,7 +397,7 @@ proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, const Name& zonename)
}
} else {
Name nsecname(task->qname);
if ((task->flags & DataSrc::NAME_NOT_FOUND) != 0) {
if ((task->flags & DataSrc::NAME_NOT_FOUND) != 0 || wildcard) {
ds->findPreviousName(task->qname, nsecname, &zonename);
}
......@@ -402,6 +408,13 @@ proveNX(Query& q, QueryTaskPtr task, const DataSrc* ds, const Name& zonename)
return (DataSrc::SUCCESS);
}
// If we are processing a wildcard answer, we're done.
if (wildcard) {
return (DataSrc::SUCCESS);
}
// Otherwise, there is no wildcard record, so we must add an
// NSEC for the zone to prove the wildcard doesn't exist.
RETERR(addNSEC(q, task, zonename, zonename, ds));
}
......@@ -431,7 +444,7 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds,
RRsetList wild;
const Name star("*");
uint32_t rflags = 0;
bool cname = false;
for (int i = 1; i <= diff; ++i) {
const Name& wname(star.concatenate(task->qname.split(i, nlen - i)));
......@@ -439,12 +452,17 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds,
QueryTask::AUTH_QUERY);
result = doQueryTask(ds, zonename, newtask, wild);
if (result == DataSrc::SUCCESS) {
if (newtask.flags == 0 || (newtask.flags & DataSrc::CNAME_FOUND)) {
rflags = newtask.flags;
task->flags &= ~DataSrc::NAME_NOT_FOUND;
task->flags &= ~DataSrc::TYPE_NOT_FOUND;
if (newtask.flags == 0) {
found = true;
break;
} else if ((newtask.flags & DataSrc::CNAME_FOUND) != 0) {
task->flags |= DataSrc::CNAME_FOUND;
found = true;
cname = true;
break;
} else if ((newtask.flags & DataSrc::TYPE_NOT_FOUND) != 0) {
task->flags &= ~DataSrc::NAME_NOT_FOUND;
task->flags |= DataSrc::TYPE_NOT_FOUND;
break;
}
......@@ -457,7 +475,13 @@ tryWildcard(Query& q, QueryTaskPtr task, const DataSrc* ds,
// answer: if a CNAME, chase the target, otherwise
// add authority.
if (found) {
if ((rflags & DataSrc::CNAME_FOUND) != 0) {
result = proveNX(q, task, ds, *zonename, true);
if (result != DataSrc::SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return (DataSrc::ERROR);
}
if (cname) {
RRsetPtr rrset = wild.findRRset(RRType::CNAME(), q.qclass());
if (rrset != NULL) {
rrset->setName(task->qname);
......@@ -688,7 +712,7 @@ DataSrc::doQuery(Query& q)
}
if (q.wantDnssec()) {
result = proveNX(q, task, datasource, *zonename);
result = proveNX(q, task, datasource, *zonename, false);
if (result != DataSrc::SUCCESS) {
m.setRcode(Rcode::SERVFAIL());
return;
......
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