Browse Source

[1574b] checked some NSEC3 parameter consistency

JINMEI Tatuya 13 years ago
parent
commit
95f2ccbb56
2 changed files with 64 additions and 6 deletions
  1. 34 3
      src/lib/datasrc/memory_datasrc.cc
  2. 30 3
      src/lib/datasrc/tests/memory_datasrc_unittest.cc

+ 34 - 3
src/lib/datasrc/memory_datasrc.cc

@@ -25,6 +25,7 @@
 #include <exceptions/exceptions.h>
 
 #include <dns/name.h>
+#include <dns/nsec3hash.h>
 #include <dns/rdataclass.h>
 #include <dns/rrclass.h>
 #include <dns/rrsetlist.h>
@@ -86,8 +87,14 @@ struct ZoneData {
 
     // The optional NSEC3 related data
     struct NSEC3Data {
-        NSEC3Map map_;          // Actual NSEC3 RRs
-        // We should also have hash parameters here (maybe hold NSEC3Hash?)
+        NSEC3Data(const generic::NSEC3PARAM& nsec3param) :
+            hash_(NSEC3Hash::create(nsec3param))
+        {}
+        NSEC3Data(const generic::NSEC3& nsec3) :
+            hash_(NSEC3Hash::create(nsec3))
+        {}
+        NSEC3Map map_;    // Actual NSEC3 RRs
+        const scoped_ptr<NSEC3Hash> hash_; // hash parameter/calculator
     };
     scoped_ptr<NSEC3Data> nsec3_data_; // non NULL only when it's NSEC3 signed
 };
@@ -370,9 +377,22 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
     }
 
     result::Result addNSEC3(const ConstRRsetPtr rrset, ZoneData& zone_data) {
+        // We know rrset has exactly one RDATA
+        const generic::NSEC3& nsec3_rdata =
+            dynamic_cast<const generic::NSEC3&>(
+                rrset->getRdataIterator()->getCurrent());
+
+        // If we've not done any NSEC3 setup for the zone, do it know;
+        // otherwise check parameter consistency.
         if (!zone_data.nsec3_data_) {
-            zone_data.nsec3_data_.reset(new ZoneData::NSEC3Data);
+            zone_data.nsec3_data_.reset(new ZoneData::NSEC3Data(nsec3_rdata));
+        } else {
+            if (!zone_data.nsec3_data_->hash_->match(nsec3_rdata)) {
+                isc_throw(AddError, "NSEC3 with inconsistent parameters: " <<
+                          rrset->toText());
+            }
         }
+
         string fst_label = rrset->getName().split(0, 1).toText(true);
         transform(fst_label.begin(), fst_label.end(), fst_label.begin(),
                   ToUpper());
@@ -457,6 +477,17 @@ struct InMemoryZoneFinder::InMemoryZoneFinderImpl {
                 node->setFlag(DomainNode::FLAG_CALLBACK);
             }
 
+            // If we've added NSEC3PARAM and the zone isn't yet NSEC3-ready
+            // set it up (note: this part doesn't ensure strong exception
+            // guarantee)
+            if (rrset->getType() == RRType::NSEC3PARAM() &&
+                !zone_data.nsec3_data_) {
+                zone_data.nsec3_data_.reset(
+                    new ZoneData::NSEC3Data(
+                        dynamic_cast<const generic::NSEC3PARAM&>(
+                            rrset->getRdataIterator()->getCurrent())));
+            }
+
             return (result::SUCCESS);
         } else {
             // The RRSet of given type was already there

+ 30 - 3
src/lib/datasrc/tests/memory_datasrc_unittest.cc

@@ -1478,6 +1478,34 @@ TEST_F(InMemoryZoneFinderTest, badRRsigForNSEC3) {
                  InMemoryZoneFinder::AddError);
 }
 
+TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3PARAM) {
+    // First, add an NSEC3PARAM RR
+    EXPECT_EQ(result::SUCCESS,
+              zone_finder_.add(textToRRset("example.org. 300 IN NSEC3PARAM "
+                                           "1 0 12 aabbccdd")));
+    // Adding an NSEC3 that has matching parameters is okay.
+    EXPECT_EQ(result::SUCCESS, zone_finder_.add(
+                  textToRRset(string(apex_hash) + ".example.org." +
+                              string(nsec3_common))));
+    // NSEC3 with inconsistent parameter will be rejected
+    EXPECT_THROW(zone_finder_.add(
+                     textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
+                                 "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
+                 InMemoryZoneFinder::AddError);
+}
+
+TEST_F(InMemoryZoneFinderTest, paramConsistencyWithNSEC3) {
+    // Add an NSEC3 without adding NSEC3PARAM
+    EXPECT_EQ(result::SUCCESS, zone_finder_.add(
+                  textToRRset(string(apex_hash) + ".example.org." +
+                              string(nsec3_common))));
+    // Adding an NSEC3 with inconsistent parameter will be rejected at this pt.
+    EXPECT_THROW(zone_finder_.add(
+                     textToRRset("a.example.org. 300 IN NSEC3 1 0 1 aabbccdd "
+                                 "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG")),
+                 InMemoryZoneFinder::AddError);
+}
+
 TEST_F(InMemoryZoneFinderTest, multiNSEC3PARAM) {
     // In this current implementation multiple NSEC3PARAM isn't supported.
     RRsetPtr nsec3param(new RRset(Name("example.org"), RRClass::IN(),
@@ -1488,8 +1516,7 @@ TEST_F(InMemoryZoneFinderTest, multiNSEC3PARAM) {
 }
 
 // TODO
-// - parameter consistency
 // - existence of NSEC3PARAM
-// - parameter consistency with NSEC3PARAM
-// - add NSEC3PARAM first/second
+// - add NSEC3PARAM second, check consistency
+// - add NSEC3PARAM at non origin (should be ignored)
 }