Browse Source

[1577] First shot at the findNSEC3 implementation

This one is wrong in many ways. It assumes (without checking) it gets an
exact match, it does not check any wrong data, it expects given order of
results. But it passes the minimal test now, and can be used as a base
for improving the implementation.
Michal 'vorner' Vaner 13 years ago
parent
commit
76f364b152
2 changed files with 65 additions and 5 deletions
  1. 35 2
      src/lib/datasrc/database.cc
  2. 30 3
      src/lib/datasrc/tests/database_unittest.cc

+ 35 - 2
src/lib/datasrc/database.cc

@@ -27,15 +27,18 @@
 #include <dns/rrset.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
+#include <dns/nsec3hash.h>
 
 #include <datasrc/data_source.h>
 #include <datasrc/logger.h>
 
 #include <boost/foreach.hpp>
+#include <boost/scoped_ptr.hpp>
 
 using namespace isc::dns;
 using namespace std;
 using namespace isc::dns::rdata;
+using namespace boost;
 
 namespace isc {
 namespace datasrc {
@@ -922,8 +925,38 @@ DatabaseClient::Finder::findNSEC3(const Name& name, bool) {
                   name << ", zone: " << getOrigin() << "/" << getClass());
     }
 
-    isc_throw(NotImplemented, "findNSEC3 is not yet implemented for database "
-              "data source");
+    // Now, we need to get the NSEC3 params from the apex and create the hash
+    // creator for it.
+
+    ZoneFinderContextPtr nsec3param(find(getOrigin(), RRType::NSEC3PARAM()));
+    if (nsec3param->code != SUCCESS) { // No NSEC3 params? :-(
+        isc_throw(DataSourceError, "findNSEC3 attempt for non NSEC3 signed " <<
+                  "zone: " << getOrigin() << "/" << getClass());
+    }
+    // This takes the RRset received from the find method, takes the first RR
+    // in it, casts it to NSEC3PARAM (as it should be that one) and then creates
+    // the hash calculator class from it.
+    const scoped_ptr<NSEC3Hash> calculator(NSEC3Hash::create(
+        dynamic_cast<const generic::NSEC3PARAM&>(
+            nsec3param->rrset->getRdataIterator()->getCurrent())));
+
+    // Compute the hash and find the corresponding NSEC3
+    const string hash(calculator->calculate(name));
+    DatabaseAccessor::IteratorContextPtr
+        context(accessor_->getNSEC3Records(hash, zone_id_));
+
+    // We store the data here
+    string columns[DatabaseAccessor::COLUMN_COUNT];
+    // TODO: Stop assuming the data is there. This is temporary, just for this
+    // commit.
+    context->getNext(columns);
+    RRsetPtr result(new RRset(Name(hash).concatenate(getOrigin()), getClass(),
+                              RRType::NSEC3(),
+                              RRTTL(columns[DatabaseAccessor::TTL_COLUMN])));
+    result->addRdata(generic::NSEC3(columns[DatabaseAccessor::RDATA_COLUMN]));
+    // Return an expected exact match for now
+    return (FindNSEC3Result(true, name.getLabelCount(), result,
+                            ConstRRsetPtr()));
 }
 
 Name

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

@@ -211,8 +211,8 @@ const char* const TEST_RECORDS[][5] = {
 
 // FIXME: Taken from a different test. Fill with proper data when creating a test.
 const char* TEST_NSEC3_RECORDS[][5] = {
-    {"1BB7SO0452U1QHL98UISNDD9218GELR5", "NSEC3", "3600", "", "1 0 10 FEEDABEE 4KLSVDE8KH8G95VU68R7AHBE1CPQN38J"},
-    {"1BB7SO0452U1QHL98UISNDD9218GELR5", "RRSIG", "3600", "", "NSEC3 5 4 7200 20100410172647 20100311172647 63192 example.org. gNIVj4T8t51fEU6kOPpvK7HOGBFZGbalN5ZK mInyrww6UWZsUNdw07ge6/U6HfG+/s61RZ/L is2M6yUWHyXbNbj/QqwqgadG5dhxTArfuR02 xP600x0fWX8LXzW4yLMdKVxGbzYT+vvGz71o 8gHSY5vYTtothcZQa4BMKhmGQEk="},
+    {"0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", "NSEC3", "300", "", "1 1 12 AABBCCDD 2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"},
+    {"0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", "RRSIG", "300", "", "NSEC3 5 4 7200 20100410172647 20100311172647 63192 example.org. gNIVj4T8t51fEU6kOPpvK7HOGBFZGbalN5ZK mInyrww6UWZsUNdw07ge6/U6HfG+/s61RZ/L is2M6yUWHyXbNbj/QqwqgadG5dhxTArfuR02 xP600x0fWX8LXzW4yLMdKVxGbzYT+vvGz71o 8gHSY5vYTtothcZQa4BMKhmGQEk="},
     {NULL, NULL, NULL, NULL, NULL}
 };
 
@@ -972,7 +972,7 @@ private:
              i = cur_name_.begin(); i != cur_name_.end(); ++ i) {
             i->push_back(hash);
         }
-        (*readonly_records_)[hash] = cur_name_;
+        nsec3_namespace_[hash] = cur_name_;
         cur_name_.clear();
     }
 
@@ -1010,6 +1010,31 @@ private:
         }
         addCurHash(prev_name);
     }
+
+public:
+    // This adds the NSEC3PARAM into the apex, so we can perform some NSEC3
+    // tests. Note that the NSEC3 namespace is available in other tests, but
+    // it should not be accessed at that time.
+    void enableNSEC3() {
+        // We place the signature first, so it's in the block with the other
+        // signatures
+        vector<string> signature;
+        signature.push_back("RRSIG");
+        signature.push_back("3600");
+        signature.push_back("");
+        signature.push_back("NSEC3PARAM 5 3 3600 20000101000000 20000201000000 "
+                            "12345 example.org. FAKEFAKEFAKE");
+        signature.push_back("exmaple.org.");
+        (*readonly_records_)["example.org."].push_back(signature);
+        // Now the NSEC3 param itself
+        vector<string> param;
+        param.push_back("NSEC3PARAM");
+        param.push_back("3600");
+        param.push_back("");
+        param.push_back("1 0 12 aabbccdd");
+        param.push_back("example.org.");
+        (*readonly_records_)["example.org."].push_back(param);
+    }
 };
 
 // This tests the default getRecords behaviour, throwing NotImplemented
@@ -3550,6 +3575,8 @@ TEST_F(MockDatabaseClientTest, journalWithBadData) {
 TEST_F(MockDatabaseClientTest, findNSEC3) {
     // Set up the faked hash calculator.
     setNSEC3HashCreator(&test_nsec3_hash_creator_);
+    // And enable NSEC3 in the zone.
+    this->current_accessor_->enableNSEC3();
 
     DataSourceClient::FindResult
         zone(this->client_->findZone(Name("example.org")));