nsec3hash_unittest.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <string>
  15. #include <gtest/gtest.h>
  16. #include <boost/scoped_ptr.hpp>
  17. #include <dns/nsec3hash.h>
  18. #include <dns/rdataclass.h>
  19. #include <util/encode/hex.h>
  20. using boost::scoped_ptr;
  21. using namespace std;
  22. using namespace isc::dns;
  23. using namespace isc::dns::rdata;
  24. using namespace isc::util;
  25. using namespace isc::util::encode;
  26. namespace {
  27. typedef scoped_ptr<NSEC3Hash> NSEC3HashPtr;
  28. // Commonly used NSEC3 suffix, defined to reduce the amount of typing
  29. const char* const nsec3_common = "2T7B4G4VSA5SMI47K61MV5BV1A22BOJR A RRSIG";
  30. class NSEC3HashTest : public ::testing::Test {
  31. protected:
  32. NSEC3HashTest() :
  33. test_hash(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd"))),
  34. test_hash_nsec3(NSEC3Hash::create(generic::NSEC3
  35. ("1 0 12 aabbccdd " +
  36. string(nsec3_common))))
  37. {
  38. const uint8_t salt[] = {0xaa, 0xbb, 0xcc, 0xdd};
  39. test_hash_args.reset(NSEC3Hash::create(1, 12, salt, sizeof(salt)));
  40. }
  41. ~NSEC3HashTest() {
  42. // Make sure we reset the hash creator to the default
  43. setNSEC3HashCreator(NULL);
  44. }
  45. // An NSEC3Hash object commonly used in tests. Parameters are borrowed
  46. // from the RFC5155 example. Construction of this object implicitly
  47. // checks a successful case of the creation.
  48. NSEC3HashPtr test_hash;
  49. // Similar to test_hash, but created from NSEC3 RR.
  50. NSEC3HashPtr test_hash_nsec3;
  51. // Similar to test_hash, but created from passed args.
  52. NSEC3HashPtr test_hash_args;
  53. };
  54. TEST_F(NSEC3HashTest, unknownAlgorithm) {
  55. EXPECT_THROW(NSEC3HashPtr(
  56. NSEC3Hash::create(
  57. generic::NSEC3PARAM("2 0 12 aabbccdd"))),
  58. UnknownNSEC3HashAlgorithm);
  59. EXPECT_THROW(NSEC3HashPtr(
  60. NSEC3Hash::create(
  61. generic::NSEC3("2 0 12 aabbccdd " +
  62. string(nsec3_common)))),
  63. UnknownNSEC3HashAlgorithm);
  64. const uint8_t salt[] = {0xaa, 0xbb, 0xcc, 0xdd};
  65. EXPECT_THROW(NSEC3HashPtr(NSEC3Hash::create(2, 12, salt, sizeof(salt))),
  66. UnknownNSEC3HashAlgorithm);
  67. }
  68. // Common checks for NSEC3 hash calculation
  69. void
  70. calculateCheck(NSEC3Hash& hash) {
  71. // A couple of normal cases from the RFC5155 example.
  72. EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
  73. hash.calculate(Name("example")));
  74. EXPECT_EQ("35MTHGPGCU1QG68FAB165KLNSNK3DPVL",
  75. hash.calculate(Name("a.example")));
  76. // Check case-insensitiveness
  77. EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
  78. hash.calculate(Name("EXAMPLE")));
  79. }
  80. TEST_F(NSEC3HashTest, calculate) {
  81. {
  82. SCOPED_TRACE("calculate check with NSEC3PARAM based hash");
  83. calculateCheck(*test_hash);
  84. }
  85. {
  86. SCOPED_TRACE("calculate check with NSEC3 based hash");
  87. calculateCheck(*test_hash_nsec3);
  88. }
  89. {
  90. SCOPED_TRACE("calculate check with args based hash");
  91. calculateCheck(*test_hash_args);
  92. }
  93. // Some boundary cases: 0-iteration and empty salt. Borrowed from the
  94. // .com zone data.
  95. EXPECT_EQ("CK0POJMG874LJREF7EFN8430QVIT8BSM",
  96. NSEC3HashPtr(NSEC3Hash::create(generic::NSEC3PARAM("1 0 0 -")))
  97. ->calculate(Name("com")));
  98. // Using unusually large iterations, something larger than the 8-bit range.
  99. // (expected hash value generated by BIND 9's dnssec-signzone)
  100. EXPECT_EQ("COG6A52MJ96MNMV3QUCAGGCO0RHCC2Q3",
  101. NSEC3HashPtr(NSEC3Hash::create(
  102. generic::NSEC3PARAM("1 0 256 AABBCCDD")))
  103. ->calculate(Name("example.org")));
  104. }
  105. // Common checks for match cases
  106. template <typename RDATAType>
  107. void
  108. matchCheck(NSEC3Hash& hash, const string& postfix) {
  109. // If all parameters match, it's considered to be matched.
  110. EXPECT_TRUE(hash.match(RDATAType("1 0 12 aabbccdd" + postfix)));
  111. // Algorithm doesn't match
  112. EXPECT_FALSE(hash.match(RDATAType("2 0 12 aabbccdd" + postfix)));
  113. // Iterations doesn't match
  114. EXPECT_FALSE(hash.match(RDATAType("1 0 1 aabbccdd" + postfix)));
  115. // Salt doesn't match
  116. EXPECT_FALSE(hash.match(RDATAType("1 0 12 aabbccde" + postfix)));
  117. // Salt doesn't match: the other has an empty salt
  118. EXPECT_FALSE(hash.match(RDATAType("1 0 12 -" + postfix)));
  119. // Flags don't matter
  120. EXPECT_TRUE(hash.match(RDATAType("1 1 12 aabbccdd" + postfix)));
  121. }
  122. TEST_F(NSEC3HashTest, matchWithNSEC3) {
  123. {
  124. SCOPED_TRACE("match NSEC3PARAM based hash against NSEC3 parameters");
  125. matchCheck<generic::NSEC3>(*test_hash, " " + string(nsec3_common));
  126. }
  127. {
  128. SCOPED_TRACE("match NSEC3 based hash against NSEC3 parameters");
  129. matchCheck<generic::NSEC3>(*test_hash_nsec3,
  130. " " + string(nsec3_common));
  131. }
  132. }
  133. TEST_F(NSEC3HashTest, matchWithNSEC3PARAM) {
  134. {
  135. SCOPED_TRACE("match NSEC3PARAM based hash against NSEC3 parameters");
  136. matchCheck<generic::NSEC3PARAM>(*test_hash, "");
  137. }
  138. {
  139. SCOPED_TRACE("match NSEC3 based hash against NSEC3 parameters");
  140. matchCheck<generic::NSEC3PARAM>(*test_hash_nsec3, "");
  141. }
  142. }
  143. // A simple faked hash calculator and a dedicated creator for it.
  144. class TestNSEC3Hash : public NSEC3Hash {
  145. virtual string calculate(const Name&) const {
  146. return ("00000000000000000000000000000000");
  147. }
  148. virtual bool match(const generic::NSEC3PARAM&) const {
  149. return (true);
  150. }
  151. virtual bool match(const generic::NSEC3&) const {
  152. return (true);
  153. }
  154. };
  155. // This faked creator basically creates the faked calculator regardless of
  156. // the passed NSEC3PARAM or NSEC3. But if the most significant bit of flags
  157. // is set, it will behave like the default creator.
  158. class TestNSEC3HashCreator : public NSEC3HashCreator {
  159. public:
  160. virtual NSEC3Hash* create(const generic::NSEC3PARAM& param) const {
  161. if ((param.getFlags() & 0x80) != 0) {
  162. return (default_creator_.create(param));
  163. }
  164. return (new TestNSEC3Hash);
  165. }
  166. virtual NSEC3Hash* create(const generic::NSEC3& nsec3) const {
  167. if ((nsec3.getFlags() & 0x80) != 0) {
  168. return (default_creator_.create(nsec3));
  169. }
  170. return (new TestNSEC3Hash);
  171. }
  172. virtual NSEC3Hash* create(uint8_t, uint16_t,
  173. const uint8_t*, size_t) const {
  174. isc_throw(isc::Unexpected,
  175. "This method is not implemented here.");
  176. }
  177. private:
  178. DefaultNSEC3HashCreator default_creator_;
  179. };
  180. TEST_F(NSEC3HashTest, setCreator) {
  181. // Re-check an existing case using the default creator/hash implementation
  182. EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
  183. test_hash->calculate(Name("example")));
  184. // Replace the creator, and confirm the hash values are faked
  185. TestNSEC3HashCreator test_creator;
  186. setNSEC3HashCreator(&test_creator);
  187. // Re-create the hash object with the new creator
  188. test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd")));
  189. EXPECT_EQ("00000000000000000000000000000000",
  190. test_hash->calculate(Name("example")));
  191. // Same for hash from NSEC3 RDATA
  192. test_hash.reset(NSEC3Hash::create(generic::NSEC3
  193. ("1 0 12 aabbccdd " +
  194. string(nsec3_common))));
  195. EXPECT_EQ("00000000000000000000000000000000",
  196. test_hash->calculate(Name("example")));
  197. // If we set a special flag big (0x80) on creation, it will act like the
  198. // default creator.
  199. test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM(
  200. "1 128 12 aabbccdd")));
  201. EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
  202. test_hash->calculate(Name("example")));
  203. test_hash.reset(NSEC3Hash::create(generic::NSEC3
  204. ("1 128 12 aabbccdd " +
  205. string(nsec3_common))));
  206. EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
  207. test_hash->calculate(Name("example")));
  208. // Reset the creator to default, and confirm that
  209. setNSEC3HashCreator(NULL);
  210. test_hash.reset(NSEC3Hash::create(generic::NSEC3PARAM("1 0 12 aabbccdd")));
  211. EXPECT_EQ("0P9MHAVEQVM6T7VBL5LOP2U3T2RP3TOM",
  212. test_hash->calculate(Name("example")));
  213. }
  214. } // end namespace