nsec3_50.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright (C) 2010 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 <iostream>
  15. #include <iomanip>
  16. #include <string>
  17. #include <sstream>
  18. #include <vector>
  19. #include <cassert>
  20. #include <boost/lexical_cast.hpp>
  21. #include <util/encode/base32hex.h>
  22. #include <util/encode/hex.h>
  23. #include <util/buffer.h>
  24. #include <dns/exceptions.h>
  25. #include <dns/messagerenderer.h>
  26. #include <dns/name.h>
  27. #include <dns/rrtype.h>
  28. #include <dns/rrttl.h>
  29. #include <dns/rdata.h>
  30. #include <dns/rdataclass.h>
  31. #include <dns/rdata/generic/detail/nsec_bitmap.h>
  32. #include <dns/rdata/generic/detail/nsec3param_common.h>
  33. #include <stdio.h>
  34. #include <time.h>
  35. using namespace std;
  36. using namespace isc::dns::rdata::generic::detail::nsec;
  37. using namespace isc::dns::rdata::generic::detail::nsec3;
  38. using namespace isc::util::encode;
  39. using namespace isc::util;
  40. // BEGIN_ISC_NAMESPACE
  41. // BEGIN_RDATA_NAMESPACE
  42. struct NSEC3Impl {
  43. // straightforward representation of NSEC3 RDATA fields
  44. NSEC3Impl(uint8_t hashalg, uint8_t flags, uint16_t iterations,
  45. vector<uint8_t>salt, vector<uint8_t>next,
  46. vector<uint8_t> typebits) :
  47. hashalg_(hashalg), flags_(flags), iterations_(iterations),
  48. salt_(salt), next_(next), typebits_(typebits)
  49. {}
  50. const uint8_t hashalg_;
  51. const uint8_t flags_;
  52. const uint16_t iterations_;
  53. const vector<uint8_t> salt_;
  54. const vector<uint8_t> next_;
  55. const vector<uint8_t> typebits_;
  56. };
  57. NSEC3::NSEC3(const string& nsec3_str) :
  58. impl_(NULL)
  59. {
  60. istringstream iss(nsec3_str);
  61. vector<uint8_t> salt;
  62. const ParseNSEC3ParamResult params =
  63. parseNSEC3ParamText("NSEC3", nsec3_str, iss, salt);
  64. // Extract Next hash. It must be an unpadded base32hex string.
  65. string nexthash;
  66. iss >> nexthash;
  67. if (iss.bad() || iss.fail()) {
  68. isc_throw(InvalidRdataText, "Invalid NSEC3 text: " << nsec3_str);
  69. }
  70. assert(!nexthash.empty());
  71. if (*nexthash.rbegin() == '=') {
  72. isc_throw(InvalidRdataText, "NSEC3 hash has padding: " << nsec3_str);
  73. }
  74. vector<uint8_t> next;
  75. decodeBase32Hex(nexthash, next);
  76. if (next.size() > 255) {
  77. isc_throw(InvalidRdataText, "NSEC3 hash is too long: "
  78. << next.size() << " bytes");
  79. }
  80. // For NSEC3 empty bitmap is possible and allowed.
  81. if (iss.eof()) {
  82. impl_ = new NSEC3Impl(params.algorithm, params.flags,
  83. params.iterations, salt, next,
  84. vector<uint8_t>());
  85. return;
  86. }
  87. vector<uint8_t> typebits;
  88. buildBitmapsFromText("NSEC3", iss, typebits);
  89. impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations,
  90. salt, next, typebits);
  91. }
  92. NSEC3::NSEC3(InputBuffer& buffer, size_t rdata_len) {
  93. vector<uint8_t> salt;
  94. const ParseNSEC3ParamResult params =
  95. parseNSEC3ParamWire("NSEC3", buffer, rdata_len, salt);
  96. if (rdata_len < 1) {
  97. isc_throw(DNSMessageFORMERR, "NSEC3 too short to contain hash length, "
  98. "length: " << rdata_len + salt.size() + 5);
  99. }
  100. const uint8_t nextlen = buffer.readUint8();
  101. --rdata_len;
  102. if (nextlen == 0 || rdata_len < nextlen) {
  103. isc_throw(DNSMessageFORMERR, "NSEC3 invalid hash length: " <<
  104. static_cast<unsigned int>(nextlen));
  105. }
  106. vector<uint8_t> next(nextlen);
  107. buffer.readData(&next[0], nextlen);
  108. rdata_len -= nextlen;
  109. vector<uint8_t> typebits(rdata_len);
  110. if (rdata_len > 0) {
  111. // Read and parse the bitmaps only when they exist; empty bitmap
  112. // is possible for NSEC3.
  113. buffer.readData(&typebits[0], rdata_len);
  114. checkRRTypeBitmaps("NSEC3", typebits);
  115. }
  116. impl_ = new NSEC3Impl(params.algorithm, params.flags, params.iterations,
  117. salt, next, typebits);
  118. }
  119. NSEC3::NSEC3(const NSEC3& source) :
  120. Rdata(), impl_(new NSEC3Impl(*source.impl_))
  121. {}
  122. NSEC3&
  123. NSEC3::operator=(const NSEC3& source) {
  124. if (impl_ == source.impl_) {
  125. return (*this);
  126. }
  127. NSEC3Impl* newimpl = new NSEC3Impl(*source.impl_);
  128. delete impl_;
  129. impl_ = newimpl;
  130. return (*this);
  131. }
  132. NSEC3::~NSEC3() {
  133. delete impl_;
  134. }
  135. string
  136. NSEC3::toText() const {
  137. ostringstream s;
  138. bitmapsToText(impl_->typebits_, s);
  139. using namespace boost;
  140. return (lexical_cast<string>(static_cast<int>(impl_->hashalg_)) +
  141. " " + lexical_cast<string>(static_cast<int>(impl_->flags_)) +
  142. " " + lexical_cast<string>(static_cast<int>(impl_->iterations_)) +
  143. " " + (impl_->salt_.empty() ? "-" : encodeHex(impl_->salt_)) +
  144. " " + encodeBase32Hex(impl_->next_) + s.str());
  145. }
  146. template <typename OUTPUT_TYPE>
  147. void
  148. toWireHelper(const NSEC3Impl& impl, OUTPUT_TYPE& output) {
  149. output.writeUint8(impl.hashalg_);
  150. output.writeUint8(impl.flags_);
  151. output.writeUint16(impl.iterations_);
  152. output.writeUint8(impl.salt_.size());
  153. if (!impl.salt_.empty()) {
  154. output.writeData(&impl.salt_[0], impl.salt_.size());
  155. }
  156. assert(!impl.next_.empty());
  157. output.writeUint8(impl.next_.size());
  158. output.writeData(&impl.next_[0], impl.next_.size());
  159. if (!impl.typebits_.empty()) {
  160. output.writeData(&impl.typebits_[0], impl.typebits_.size());
  161. }
  162. }
  163. void
  164. NSEC3::toWire(OutputBuffer& buffer) const {
  165. toWireHelper(*impl_, buffer);
  166. }
  167. void
  168. NSEC3::toWire(AbstractMessageRenderer& renderer) const {
  169. toWireHelper(*impl_, renderer);
  170. }
  171. namespace {
  172. // This is a helper subroutine for compare(). It compares two binary
  173. // data stored in vector<uint8_t> objects based on the "Canonical RR Ordering"
  174. // as defined in Section 6.3 of RFC4034, that is, the data are treated
  175. // "as a left-justified unsigned octet sequence in which the absence of an
  176. // octet sorts before a zero octet."
  177. //
  178. // If check_length_first is true, it treats the compared data as if they
  179. // began with a single-octet "length" field whose value is the size of the
  180. // corresponding vector. In this case, if the sizes of the two vectors are
  181. // different the shorter one is always considered the "smaller"; the contents
  182. // of the vector don't matter.
  183. //
  184. // This function returns:
  185. // -1 if v1 is considered smaller than v2
  186. // 1 if v1 is considered larger than v2
  187. // 0 otherwise
  188. int
  189. compareVectors(const vector<uint8_t>& v1, const vector<uint8_t>& v2,
  190. bool check_length_first = true)
  191. {
  192. const size_t len1 = v1.size();
  193. const size_t len2 = v2.size();
  194. if (check_length_first && len1 != len2) {
  195. return (len1 - len2);
  196. }
  197. const size_t cmplen = min(len1, len2);
  198. const int cmp = cmplen == 0 ? 0 : memcmp(&v1.at(0), &v2.at(0), cmplen);
  199. if (cmp != 0) {
  200. return (cmp);
  201. } else {
  202. return (len1 - len2);
  203. }
  204. }
  205. }
  206. int
  207. NSEC3::compare(const Rdata& other) const {
  208. const NSEC3& other_nsec3 = dynamic_cast<const NSEC3&>(other);
  209. if (impl_->hashalg_ != other_nsec3.impl_->hashalg_) {
  210. return (impl_->hashalg_ < other_nsec3.impl_->hashalg_ ? -1 : 1);
  211. }
  212. if (impl_->flags_ != other_nsec3.impl_->flags_) {
  213. return (impl_->flags_ < other_nsec3.impl_->flags_ ? -1 : 1);
  214. }
  215. if (impl_->iterations_ != other_nsec3.impl_->iterations_) {
  216. return (impl_->iterations_ < other_nsec3.impl_->iterations_ ? -1 : 1);
  217. }
  218. int cmp = compareVectors(impl_->salt_, other_nsec3.impl_->salt_);
  219. if (cmp != 0) {
  220. return (cmp);
  221. }
  222. cmp = compareVectors(impl_->next_, other_nsec3.impl_->next_);
  223. if (cmp != 0) {
  224. return (cmp);
  225. }
  226. // Note that bitmap doesn't have a dedicated length field, so we shouldn't
  227. // terminate the comparison just because the lengths are different.
  228. return (compareVectors(impl_->typebits_, other_nsec3.impl_->typebits_,
  229. false));
  230. }
  231. uint8_t
  232. NSEC3::getHashalg() const {
  233. return (impl_->hashalg_);
  234. }
  235. uint8_t
  236. NSEC3::getFlags() const {
  237. return (impl_->flags_);
  238. }
  239. uint16_t
  240. NSEC3::getIterations() const {
  241. return (impl_->iterations_);
  242. }
  243. const vector<uint8_t>&
  244. NSEC3::getSalt() const {
  245. return (impl_->salt_);
  246. }
  247. const vector<uint8_t>&
  248. NSEC3::getNext() const {
  249. return (impl_->next_);
  250. }
  251. // END_RDATA_NAMESPACE
  252. // END_ISC_NAMESPACE