[svn] commit: r1474 - /trunk/src/lib/auth/data_source.cc

BIND 10 source code commits bind10-changes at lists.isc.org
Wed Mar 17 07:01:43 UTC 2010


Author: each
Date: Wed Mar 17 07:01:42 2010
New Revision: 1474

Log:
Correctly handle NSEC and NSEC3 responses when answering with a
wildcard record.  (Unit tests to follow in the morning.)

Modified:
    trunk/src/lib/auth/data_source.cc

Modified: trunk/src/lib/auth/data_source.cc
==============================================================================
--- trunk/src/lib/auth/data_source.cc (original)
+++ trunk/src/lib/auth/data_source.cc Wed Mar 17 07:01:42 2010
@@ -344,7 +344,8 @@
 }
 
 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 @@
             }
         }
 
-        // 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 @@
         }
     } 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 @@
             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 @@
 
     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 @@
                           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 @@
     // 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 @@
             }
 
             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;




More information about the bind10-changes mailing list