Browse Source

[2480] use a separate faked NSEC3Hash for query tests

JINMEI Tatuya 12 years ago
parent
commit
33ba1827b5
1 changed files with 112 additions and 60 deletions
  1. 112 60
      src/bin/auth/tests/query_unittest.cc

+ 112 - 60
src/bin/auth/tests/query_unittest.cc

@@ -26,6 +26,7 @@
 #include <dns/message.h>
 #include <dns/master_loader.h>
 #include <dns/name.h>
+#include <dns/nsec3hash.h>
 #include <dns/opcode.h>
 #include <dns/rcode.h>
 #include <dns/rrcollator.h>
@@ -51,7 +52,7 @@ using namespace isc::testutils;
 
 namespace {
 
-// Simple wrapper for a sincle data source client.
+// Simple wrapper for a single data source client.
 // The list simply delegates all the answers to the single
 // client.
 class SingletonList : public ClientList {
@@ -158,44 +159,14 @@ textToRRset(const string& text_rrset, const Name& origin = Name::ROOT_NAME()) {
     return (rrset);
 }
 
-// This is a mock Zone Finder class for testing.
-// It is a derived class of ZoneFinder for the convenient of tests.
-// Its find() method emulates the common behavior of protocol compliant
-// ZoneFinder classes, but simplifies some minor cases and also supports broken
-// behavior.
-// For simplicity, most names are assumed to be "in zone"; delegations
-// to child zones are identified by the existence of non origin NS records.
-// Another special name is "dname.example.com".  Query names under this name
-// will result in DNAME.
-// This mock zone doesn't handle empty non terminal nodes (if we need to test
-// such cases find() should have specialized code for it).
-class MockZoneFinder : public ZoneFinder {
+// Setup for faked NSEC3 hash used throughout this test.
+class TestNSEC3Hash : public NSEC3Hash {
+private:
+    typedef map<Name, string> NSEC3HashMap;
+    typedef NSEC3HashMap::value_type NSEC3HashPair;
+    NSEC3HashMap hash_map_;
 public:
-    MockZoneFinder() :
-        origin_(Name("example.com")),
-        bad_signed_delegation_name_("bad-delegation.example.com"),
-        dname_name_("dname.example.com"),
-        has_SOA_(true),
-        has_apex_NS_(true),
-        rrclass_(RRClass::IN()),
-        include_rrsig_anyway_(false),
-        use_nsec3_(false),
-        nsec_name_(origin_),
-        nsec3_fake_(NULL),
-        nsec3_name_(NULL)
-    {
-        RRCollator collator(boost::bind(&MockZoneFinder::loadRRset, this, _1));
-        MasterLoader loader(TEST_OWN_DATA_DIR "/example-nsec3.zone",
-                            origin_, rrclass_,
-                            MasterLoaderCallbacks::getNullCallbacks(),
-                            collator.getCallback());
-        loader.load();
-
-        empty_nsec_rrset_ = ConstRRsetPtr(new RRset(Name::ROOT_NAME(),
-                                                    RRClass::IN(),
-                                                    RRType::NSEC(),
-                                                    RRTTL(3600)));
-
+    TestNSEC3Hash() {
         // (Faked) NSEC3 hash map.  For convenience we use hardcoded built-in
         // map instead of calculating and using actual hash.
         // The used hash values are borrowed from RFC5155 examples (they are
@@ -241,6 +212,79 @@ public:
         hash_map_[Name("www1.uwild.example.com")] =
             "q04jkcevqvmu85r014c7dkba38o0ji6r"; // a bit larger than H(www)
     }
+    virtual string calculate(const Name& name) const {
+        const NSEC3HashMap::const_iterator found = hash_map_.find(name);
+        if (found != hash_map_.end()) {
+            return (found->second);
+        }
+        isc_throw(isc::Unexpected, "unexpected name for NSEC3 test: "
+                  << name);
+    }
+    virtual bool match(const rdata::generic::NSEC3PARAM&) const {
+        return (true);
+    }
+    virtual bool match(const rdata::generic::NSEC3&) const {
+        return (true);
+    }
+};
+
+class TestNSEC3HashCreator : public isc::dns::NSEC3HashCreator {
+public:
+    TestNSEC3HashCreator() {}
+    virtual isc::dns::NSEC3Hash*
+    create(const isc::dns::rdata::generic::NSEC3PARAM&) const {
+        return (new TestNSEC3Hash);
+    }
+
+    virtual isc::dns::NSEC3Hash*
+    create(const isc::dns::rdata::generic::NSEC3&) const {
+        return (new TestNSEC3Hash);
+    }
+
+    virtual isc::dns::NSEC3Hash*
+    create(uint8_t, uint16_t, const uint8_t*, size_t) const {
+        return (new TestNSEC3Hash);
+    }
+};
+
+// This is a mock Zone Finder class for testing.
+// It is a derived class of ZoneFinder for the convenient of tests.
+// Its find() method emulates the common behavior of protocol compliant
+// ZoneFinder classes, but simplifies some minor cases and also supports broken
+// behavior.
+// For simplicity, most names are assumed to be "in zone"; delegations
+// to child zones are identified by the existence of non origin NS records.
+// Another special name is "dname.example.com".  Query names under this name
+// will result in DNAME.
+// This mock zone doesn't handle empty non terminal nodes (if we need to test
+// such cases find() should have specialized code for it).
+class MockZoneFinder : public ZoneFinder {
+public:
+    MockZoneFinder() :
+        origin_(Name("example.com")),
+        bad_signed_delegation_name_("bad-delegation.example.com"),
+        dname_name_("dname.example.com"),
+        has_SOA_(true),
+        has_apex_NS_(true),
+        rrclass_(RRClass::IN()),
+        include_rrsig_anyway_(false),
+        use_nsec3_(false),
+        nsec_name_(origin_),
+        nsec3_fake_(NULL),
+        nsec3_name_(NULL)
+    {
+        RRCollator collator(boost::bind(&MockZoneFinder::loadRRset, this, _1));
+        MasterLoader loader(TEST_OWN_DATA_DIR "/example-nsec3.zone",
+                            origin_, rrclass_,
+                            MasterLoaderCallbacks::getNullCallbacks(),
+                            collator.getCallback());
+        loader.load();
+
+        empty_nsec_rrset_ = ConstRRsetPtr(new RRset(Name::ROOT_NAME(),
+                                                    RRClass::IN(),
+                                                    RRType::NSEC(),
+                                                    RRTTL(3600)));
+    }
     virtual isc::dns::Name getOrigin() const { return (origin_); }
     virtual isc::dns::RRClass getClass() const { return (rrclass_); }
     virtual ZoneFinderContextPtr find(const isc::dns::Name& name,
@@ -402,9 +446,7 @@ private:
     // Enabled when not NULL
     const FindNSEC3Result* nsec3_fake_;
     const Name* nsec3_name_;
-public:
-    // Public, to allow tests looking up the right names for something
-    map<Name, string> hash_map_;
+    TestNSEC3Hash nsec3_hash_;
 };
 
 // A helper function that generates a new RRset based on "wild_rrset",
@@ -464,7 +506,7 @@ MockZoneFinder::findNSEC3(const Name& name, bool recursive) {
     // For brevity, we assume several things below: maps should have an
     // expected entry when operator[] is used; maps are not empty.
     for (int i = 0; i < labels; ++i) {
-        const string hlabel = hash_map_[name.split(i, labels - i)];
+        const string hlabel = nsec3_hash_.calculate(name.split(i, labels - i));
         if (hlabel.empty()) {
             isc_throw(isc::Unexpected, "findNSEC3() hash failure for " <<
                       name.split(i, labels - i));
@@ -781,12 +823,21 @@ protected:
                              "noglue.example.com. 3600 IN RRSIG " +
                              getCommonRRSIGText("A"))
     {
+        // Set up the faked hash calculator.
+        const TestNSEC3HashCreator creator;
+        setNSEC3HashCreator(&creator);
+
         response.setRcode(Rcode::NOERROR());
         response.setOpcode(Opcode::QUERY());
         // create and add a matching zone.
         mock_finder = new MockZoneFinder();
         memory_client.addZone(ZoneFinderPtr(mock_finder));
     }
+    ~QueryTest() {
+        // Make sure we reset the hash creator to the default
+        setNSEC3HashCreator(NULL);
+    }
+
     MockZoneFinder* mock_finder;
     // We use InMemoryClient here. We could have some kind of mock client
     // here, but historically, the Query supported only InMemoryClient
@@ -805,6 +856,7 @@ protected:
     const uint16_t query_code;
     const string ns_addrs_and_sig_txt; // convenient shortcut
     Query query;
+    TestNSEC3Hash nsec3_hash_;
 };
 
 // We test the in-memory and SQLite3 data source implementations.  SQLite3
@@ -1081,7 +1133,7 @@ TEST_P(QueryTest, secureUnsignedDelegationWithNSEC3) {
                   NULL,
                   (string(unsigned_delegation_txt) +
                    string(unsigned_delegation_nsec3_txt) +
-                   mock_finder->hash_map_[insecurechild_name] +
+                   nsec3_hash_.calculate(insecurechild_name) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3")).c_str(),
                   NULL);
@@ -1108,11 +1160,11 @@ TEST_P(QueryTest, secureUnsignedDelegationWithNSEC3OptOut) {
                   NULL,
                   (string(unsigned_delegation_txt) +
                    string(nsec3_apex_txt) +
-                   mock_finder->hash_map_[mock_finder->getOrigin()] +
+                   nsec3_hash_.calculate(mock_finder->getOrigin()) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n" +
                    string(nsec3_www_txt) +
-                   mock_finder->hash_map_[Name("www.example.com")] +
+                   nsec3_hash_.calculate(Name("www.example.com")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3")).c_str(),
                   NULL);
@@ -1433,7 +1485,7 @@ TEST_P(QueryTest, wildcardNSEC3) {
                    getCommonRRSIGText("NS") + "\n" +
                    // NSEC3 for the wildcard proof and its RRSIG
                    string(nsec3_apex_txt) +
-                   mock_finder->hash_map_[Name("example.com.")] +
+                   nsec3_hash_.calculate(Name("example.com.")) +
                    string(".example.com. 3600 IN RRSIG ") +
                    getCommonRRSIGText("NSEC3")).c_str(),
                   NULL, // we are not interested in additionals in this test
@@ -1459,7 +1511,7 @@ TEST_P(QueryTest, CNAMEwildNSEC3) {
                    string("www.cnamewild.example.com. 3600 IN RRSIG ") +
                    getCommonRRSIGText("CNAME") + "\n").c_str(),
                   (string(nsec3_www_txt) +
-                   mock_finder->hash_map_[Name("www.example.com.")] +
+                   nsec3_hash_.calculate(Name("www.example.com.")) +
                    string(".example.com. 3600 IN RRSIG ") +
                    getCommonRRSIGText("NSEC3")).c_str(),
                   NULL, // we are not interested in additionals in this test
@@ -1598,17 +1650,17 @@ TEST_P(QueryTest, wildcardNxrrsetWithNSEC3) {
                    getCommonRRSIGText("SOA") + "\n" +
                    // NSEC3 for the closest encloser + its RRSIG
                    string(nsec3_uwild_txt) +
-                   mock_finder->hash_map_[Name("uwild.example.com.")] +
+                   nsec3_hash_.calculate(Name("uwild.example.com.")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n" +
                    // NSEC3 for the next closer + its RRSIG
                    string(nsec3_www_txt) +
-                   mock_finder->hash_map_[Name("www.example.com.")] +
+                   nsec3_hash_.calculate(Name("www.example.com.")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n" +
                    // NSEC3 for the wildcard + its RRSIG
                    string(nsec3_wild_txt) +
-                   mock_finder->hash_map_[Name("*.uwild.example.com.")] +
+                   nsec3_hash_.calculate(Name("*.uwild.example.com.")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3")).c_str(),
                   NULL, mock_finder->getOrigin());
@@ -2318,7 +2370,7 @@ TEST_P(QueryTest, nxrrsetWithNSEC3) {
                   (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
                    getCommonRRSIGText("SOA") + "\n" +
                    string(nsec3_www_txt) + "\n" +
-                   mock_finder->hash_map_[Name("www.example.com.")] +
+                   nsec3_hash_.calculate(Name("www.example.com.")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n").c_str(),
                   NULL, mock_finder->getOrigin());
@@ -2361,8 +2413,8 @@ TEST_P(QueryTest, nxrrsetWithNSEC3_ds_exact) {
                   (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
                    getCommonRRSIGText("SOA") + "\n" +
                    string(unsigned_delegation_nsec3_txt) + "\n" +
-                   mock_finder->
-                        hash_map_[Name("unsigned-delegation.example.com.")] +
+                   nsec3_hash_.calculate(
+                       Name("unsigned-delegation.example.com.")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n").c_str(),
                   NULL, mock_finder->getOrigin());
@@ -2388,12 +2440,12 @@ TEST_P(QueryTest, nxrrsetWithNSEC3_ds_no_exact) {
                   (string(soa_txt) + string("example.com. 3600 IN RRSIG ") +
                    getCommonRRSIGText("SOA") + "\n" +
                    string(nsec3_apex_txt) + "\n" +
-                   mock_finder->hash_map_[Name("example.com.")] +
+                   nsec3_hash_.calculate(Name("example.com.")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n" +
                    string(unsigned_delegation_nsec3_txt) + "\n" +
-                   mock_finder->
-                        hash_map_[Name("unsigned-delegation.example.com.")] +
+                   nsec3_hash_.calculate(
+                       Name("unsigned-delegation.example.com.")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n").c_str(),
                   NULL, mock_finder->getOrigin());
@@ -2423,18 +2475,18 @@ TEST_P(QueryTest, nxdomainWithNSEC3Proof) {
                    getCommonRRSIGText("SOA") + "\n" +
                    // NSEC3 for the closest encloser + its RRSIG
                    string(nsec3_apex_txt) + "\n" +
-                   mock_finder->hash_map_[mock_finder->getOrigin()] +
+                   nsec3_hash_.calculate(mock_finder->getOrigin()) +
                    string(".example.com. 3600 IN RRSIG ") +
                    getCommonRRSIGText("NSEC3") + "\n" +
                    // NSEC3 for the next closer + its RRSIG
                    string(nsec3_uwild_txt) + "\n" +
-                   mock_finder->hash_map_[Name("uwild.example.com")] +
+                   nsec3_hash_.calculate(Name("uwild.example.com")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3") + "\n" +
                    // NSEC3 for the wildcard + its RRSIG
                    string(unsigned_delegation_nsec3_txt) +
-                   mock_finder->hash_map_[
-                       Name("unsigned-delegation.example.com")] +
+                   nsec3_hash_.calculate(
+                       Name("unsigned-delegation.example.com")) +
                    ".example.com. 3600 IN RRSIG " +
                    getCommonRRSIGText("NSEC3")).c_str(),
                   NULL, mock_finder->getOrigin());