From: JINMEI Tatuya Date: Tue, 7 Feb 2012 22:37:56 +0000 (-0800) Subject: [1576] introduced a framework to replace the default NSEC3Hash for further tests. X-Git-Tag: trac2351_base~97^2~35^2~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a5fa9a0f01113a92f6136f6dfc1716f877cbf07e;p=thirdparty%2Fkea.git [1576] introduced a framework to replace the default NSEC3Hash for further tests. --- diff --git a/src/lib/dns/nsec3hash.cc b/src/lib/dns/nsec3hash.cc index 87559598f2..cee504fd2e 100644 --- a/src/lib/dns/nsec3hash.cc +++ b/src/lib/dns/nsec3hash.cc @@ -142,6 +142,35 @@ NSEC3HashRFC5155::match(const generic::NSEC3PARAM& nsec3param) const { return (match(nsec3param.getHashalg(), nsec3param.getIterations(), nsec3param.getSalt())); } + +class DefaultNSEC3HashCreator : public NSEC3HashCreator { +public: + virtual NSEC3Hash* create(const generic::NSEC3PARAM& param) const { + return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(), + param.getSalt())); + } + virtual NSEC3Hash* create(const generic::NSEC3& nsec3) const { + return (new NSEC3HashRFC5155(nsec3.getHashalg(), nsec3.getIterations(), + nsec3.getSalt())); + } +}; + +// A static pointer that refers to the currently usable creator. +// Only get/setNSEC3HashCreator are expected to get access to this variable +// directly. +const NSEC3HashCreator* creator; + +// The accessor to the current creator. If it's not explicitly set or has +// been reset from a customized one, the default creator will be used. +const NSEC3HashCreator* +getNSEC3HashCreator() { + static DefaultNSEC3HashCreator default_creator; + if (creator == NULL) { + creator = &default_creator; + } + return (creator); +} + } // end of unnamed namespace namespace isc { @@ -149,14 +178,17 @@ namespace dns { NSEC3Hash* NSEC3Hash::create(const generic::NSEC3PARAM& param) { - return (new NSEC3HashRFC5155(param.getHashalg(), param.getIterations(), - param.getSalt())); + return (getNSEC3HashCreator()->create(param)); } NSEC3Hash* NSEC3Hash::create(const generic::NSEC3& nsec3) { - return (new NSEC3HashRFC5155(nsec3.getHashalg(), nsec3.getIterations(), - nsec3.getSalt())); + return (getNSEC3HashCreator()->create(nsec3)); +} + +void +setNSEC3HashCreator(const NSEC3HashCreator* new_creator) { + creator = new_creator; } } // namespace dns diff --git a/src/lib/dns/nsec3hash.h b/src/lib/dns/nsec3hash.h index 7937e9de1f..b743948b53 100644 --- a/src/lib/dns/nsec3hash.h +++ b/src/lib/dns/nsec3hash.h @@ -154,6 +154,78 @@ public: virtual bool match(const rdata::generic::NSEC3PARAM& nsec3param) const = 0; }; +/// \brief Factory class of NSEC3Hash. +/// +/// This class is an abstract base class that provides the creation interfaces +/// of \c NSEC3Hash objects. By defining a specific derived class of the +/// creator, normally with a different specific class of \c NSEC3Hash, +/// the application can use a customized implementation of \c NSEC3Hash +/// without changing the library itself. The intended primary application of +/// such customization is tests (it would be convenient for a test to produce +/// a faked hash value regardless of the input so it doesn't have to identify +/// a specific input value to produce a particular hash). Another possibility +/// would be an experimental extension for a newer hash algorithm or +/// implementation. +/// +/// The two main methods named \c create() correspond to the static factory +/// methods of \c NSEC3Hash of the same name. +/// +/// By default, the library uses a builtin creator implementation. The +/// \c setNSEC3HashCreator() function can be used to replace it with a user +/// defined version. +/// +/// The creator objects are generally expected to be stateless; they will +/// only encapsulate the factory logic. The \c create() methods are declared +/// as const member functions for this reason. But if we see the need for +/// having a customized creator that benefits from its own state in future, +/// this condition can be loosened. +class NSEC3HashCreator { +protected: + /// \brief The default constructor. + /// + /// Make very sure this isn't directly instantiated by making it protected + /// even if this class is modified to lose all pure virtual methods. + NSEC3HashCreator() {} + +public: + /// \brief The destructor. + /// + /// This does nothing; defined only for allowing derived classes to + /// specialize its behavior. + virtual ~NSEC3HashCreator() {} + + /// \brief Factory method of NSECHash from NSEC3PARAM RDATA. + /// + /// See + /// NSEC3Hash::create(const rdata::generic::NSEC3PARAM& param) + virtual NSEC3Hash* create(const rdata::generic::NSEC3PARAM& nsec3param) + const = 0; + + /// \brief Factory method of NSECHash from NSEC3 RDATA. + /// + /// See + /// NSEC3Hash::create(const rdata::generic::NSEC3& param) + virtual NSEC3Hash* create(const rdata::generic::NSEC3& nsec3) + const = 0; +}; + +/// \brief The registrar of \c NSEC3HashCreator. +/// +/// This function sets or resets the system-wide \c NSEC3HashCreator that +/// is used by \c NSEC3Hash::create(). +/// +/// If \c new_creator is non NULL, the given creator object will replace +/// any existing creator. If it's NULL, the default builtin creator will be +/// used again from that point. +/// +/// When \c new_creator is non NULL, the caller is responsible for keeping +/// the referenced object valid as long as it can be used via +/// \c NSEC3Hash::create(). +/// +/// \exception None +/// \param new_creator A pointer to the new creator object or NULL. +void setNSEC3HashCreator(const NSEC3HashCreator* new_creator); + } } #endif // __NSEC3HASH_H diff --git a/src/lib/dns/tests/nsec3hash_unittest.cc b/src/lib/dns/tests/nsec3hash_unittest.cc index 36a1d4d5ee..3f2dad2c8f 100644 --- a/src/lib/dns/tests/nsec3hash_unittest.cc +++ b/src/lib/dns/tests/nsec3hash_unittest.cc @@ -29,7 +29,7 @@ using namespace isc::dns::rdata; namespace { typedef scoped_ptr NSEC3HashPtr; -// Commonly used NSEC3 suffix, defined to reduce amount of type +// Commonly used NSEC3 suffix, defined to reduce the amount of typing const char* const nsec3_common = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG"; class NSEC3HashTest : public ::testing::Test { @@ -41,6 +41,11 @@ protected: string(nsec3_common)))) {} + ~NSEC3HashTest() { + // Make sure we reset the hash creator to the default + setNSEC3HashCreator(NULL); + } + // An NSEC3Hash object commonly used in tests. Parameters are borrowed // from the RFC5155 example. Construction of this object implicitly // checks a successful case of the creation. @@ -142,4 +147,53 @@ TEST_F(NSEC3HashTest, matchWithNSEC3PARAM) { } } +// A simple faked hash calculator and a dedicated creator for it. +class TestNSEC3Hash : public NSEC3Hash { + virtual string calculate(const Name&) const { + return ("00000000000000000000000000000000"); + } + virtual bool match(const generic::NSEC3PARAM&) const { + return (true); + } + virtual bool match(const generic::NSEC3&) const { + return (true); + } +}; + +class TestNSEC3HashCreator : public NSEC3HashCreator { +public: + virtual NSEC3Hash* create(const generic::NSEC3PARAM&) const { + return (new TestNSEC3Hash); + } + virtual NSEC3Hash* create(const generic::NSEC3&) const { + return (new TestNSEC3Hash); + } +}; + +TEST_F(NSEC3HashTest, setCreator) { + // Re-check an existing case using the default creator/hash implementation + EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", + test_hash->calculate(Name("example"))); + + // Replace the creator, and confirm the hash values are faked + TestNSEC3HashCreator test_creator; + setNSEC3HashCreator(&test_creator); + // Re-create the hash object with the new creator + test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd"))); + EXPECT_EQ("00000000000000000000000000000000", + test_hash->calculate(Name("example"))); + // Same for hash from NSEC3 RDATA + test_hash.reset(NSEC3Hash::create(generic::NSEC3 + ("1 0 12 aabbccdd " + + string(nsec3_common)))); + EXPECT_EQ("00000000000000000000000000000000", + test_hash->calculate(Name("example"))); + + // Reset the creator to default, and confirm that + setNSEC3HashCreator(NULL); + test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd"))); + EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM", + test_hash->calculate(Name("example"))); +} + } // end namespace