Browse Source

[2659] updated the behavior for empty name derived from opt-out nsec3.

it now returns the closest provable encloser proof as described in
RFC 5155 errata 3441, instead of returning SERVFAIL.  test case was
adjusted and test was renamed to explain the intent more correctly.
JINMEI Tatuya 12 years ago
parent
commit
78b66fd894
2 changed files with 35 additions and 16 deletions
  1. 12 8
      src/bin/auth/query.cc
  2. 23 8
      src/bin/auth/tests/query_unittest.cc

+ 12 - 8
src/bin/auth/query.cc

@@ -298,14 +298,18 @@ Query::addNXRRsetProof(ZoneFinder& finder,
             addWildcardNXRRSETProof(finder, db_context.rrset);
         }
     } else if (db_context.isNSEC3Signed() && !db_context.isWildcard()) {
-        if (*qtype_ == RRType::DS()) {
-            // RFC 5155, Section 7.2.4.  Add either NSEC3 for the qname or
-            // closest (provable) encloser proof in case of optout.
-            addClosestEncloserProof(finder, *qname_, true);
-        } else {
-            // RFC 5155, Section 7.2.3.  Just add NSEC3 for the qname.
-            addNSEC3ForName(finder, *qname_, true);
-        }
+        // Section 7.2.3 and 7.2.4 of RFC 5155 with clarification by errata
+        // http://www.rfc-editor.org/errata_search.php?rfc=5155&eid=3441
+        // In the end, these two cases are basically the same: if the qname is
+        // equal to or derived from insecure delegation covered by an Opt-Out
+        // NSEC3 RR, include the closest provable encloser proof; otherwise we
+        // have a matching NSEC3, so we include it.
+        //
+        // Note: This implementation does not check in the former case whether
+        // the NSEC3 for the next closer has Opt-Out bit on; this must be the
+        // case as long as the zone is correctly signed, and if it's broken
+        // we'd just return what we are given and have the validator detect it.
+        addClosestEncloserProof(finder, *qname_, true);
     } else if (db_context.isNSEC3Signed() && db_context.isWildcard()) {
         // Case for RFC 5155 Section 7.2.5: add closest encloser proof for the
         // qname, construct the matched wildcard name and add NSEC3 for it.

+ 23 - 8
src/bin/auth/tests/query_unittest.cc

@@ -2473,17 +2473,32 @@ TEST_P(QueryTest, nxrrsetWithNSEC3) {
                   NULL, mock_finder->getOrigin());
 }
 
-// Check the exception is correctly raised when the NSEC3 thing isn't in the
-// zone
-TEST_P(QueryTest, nxrrsetMissingNSEC3) {
+TEST_P(QueryTest, nxrrsetDerivedFromOptOutNSEC3) {
     // In this test we emulate the situation where an empty non-terminal name
     // is derived from insecure delegation and covered by an opt-out NSEC3.
-    // In the actual test data the covering NSEC3 doesn't have the opt-out
-    // bit set, but the implementation doesn't check it.
+    // In the actual test data the covering NSEC3 really has the opt-out
+    // bit set, although the implementation doesn't check it anyway.
     enableNSEC3(rrsets_to_add_);
-    EXPECT_THROW(query.process(*list_, Name("empty.example.com"),
-                               RRType::TXT(), response, true),
-                 Query::BadNSEC3);
+    query.process(*list_, Name("empty.example.com"), RRType::TXT(), response,
+                  true);
+
+    // The closest provable encloser is the origin name (example.com.), and
+    // the next closer is the empty name itself, which is expected to be
+    // covered by an opt-out NSEC3 RR.  The response should contain these 2
+    // NSEC3s.
+    responseCheck(response, Rcode::NOERROR(), AA_FLAG, 0, 6, 0, NULL,
+                  (string(soa_minttl_txt) +
+                   string("example.com. 0 IN RRSIG ") +
+                   getCommonRRSIGText("SOA") + "\n" +
+                   string(nsec3_apex_txt) + "\n" +
+                   nsec3_hash_.calculate(Name("example.com.")) +
+                   ".example.com. 3600 IN RRSIG " +
+                   getCommonRRSIGText("NSEC3") + "\n" +
+                   string(nsec3_www_txt) + "\n" +
+                   nsec3_hash_.calculate(Name("www.example.com.")) +
+                   ".example.com. 3600 IN RRSIG " +
+                   getCommonRRSIGText("NSEC3") + "\n").c_str(),
+                  NULL, mock_finder->getOrigin());
 }
 
 TEST_P(QueryTest, nxrrsetWithNSEC3_ds_exact) {