tsigkey.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 <map>
  15. #include <utility>
  16. #include <vector>
  17. #include <exceptions/exceptions.h>
  18. #include <crypto/crypto.h>
  19. #include <dns/name.h>
  20. #include <dns/util/base64.h>
  21. #include <dns/tsigkey.h>
  22. using namespace std;
  23. namespace {
  24. bool isValidAlgorithmName(const isc::dns::Name& name) {
  25. return (name == isc::dns::TSIGKey::HMACMD5_NAME() ||
  26. name == isc::dns::TSIGKey::HMACSHA1_NAME() ||
  27. name == isc::dns::TSIGKey::HMACSHA256_NAME());
  28. }
  29. }
  30. namespace isc {
  31. namespace dns {
  32. struct
  33. TSIGKey::TSIGKeyImpl {
  34. TSIGKeyImpl(const Name& key_name, const Name& algorithm_name,
  35. const void* secret, size_t secret_len) :
  36. key_name_(key_name), algorithm_name_(algorithm_name),
  37. secret_(static_cast<const uint8_t*>(secret),
  38. static_cast<const uint8_t*>(secret) + secret_len)
  39. {
  40. // Convert the name to the canonical form.
  41. algorithm_name_.downcase();
  42. }
  43. const Name key_name_;
  44. Name algorithm_name_;
  45. const vector<uint8_t> secret_;
  46. };
  47. TSIGKey::TSIGKey(const Name& key_name, const Name& algorithm_name,
  48. const void* secret, size_t secret_len) : impl_(NULL)
  49. {
  50. if (!isValidAlgorithmName(algorithm_name)) {
  51. isc_throw(InvalidParameter, "Unknown TSIG algorithm is specified: " <<
  52. algorithm_name);
  53. }
  54. if ((secret != NULL && secret_len == 0) ||
  55. (secret == NULL && secret_len != 0)) {
  56. isc_throw(InvalidParameter,
  57. "TSIGKey secret and its length are inconsistent");
  58. }
  59. impl_ = new TSIGKeyImpl(key_name, algorithm_name, secret, secret_len);
  60. }
  61. TSIGKey::TSIGKey(const std::string& str) : impl_(NULL) {
  62. try {
  63. istringstream iss(str);
  64. string keyname_str;
  65. getline(iss, keyname_str, ':');
  66. if (iss.fail() || iss.bad() || iss.eof()) {
  67. isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
  68. }
  69. string secret_str;
  70. getline(iss, secret_str, ':');
  71. if (iss.fail() || iss.bad()) {
  72. isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
  73. }
  74. string algo_str;
  75. if (!iss.eof()) {
  76. getline(iss, algo_str);
  77. }
  78. if (iss.fail() || iss.bad()) {
  79. isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
  80. }
  81. const Name algo_name(algo_str.empty() ? "hmac-md5.sig-alg.reg.int" :
  82. algo_str);
  83. if (!isValidAlgorithmName(algo_name)) {
  84. isc_throw(InvalidParameter, "Unknown TSIG algorithm is specified: " <<
  85. algo_name);
  86. }
  87. vector<uint8_t> secret;
  88. decodeBase64(secret_str, secret);
  89. impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, &secret[0],
  90. secret.size());
  91. } catch (const Exception& e) {
  92. // 'reduce' the several types of exceptions name parsing and
  93. // Base64 decoding can throw to just the InvalidParameter
  94. isc_throw(InvalidParameter, e.what());
  95. }
  96. }
  97. TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_))
  98. {}
  99. TSIGKey&
  100. TSIGKey::operator=(const TSIGKey& source) {
  101. if (impl_ == source.impl_) {
  102. return (*this);
  103. }
  104. TSIGKeyImpl* newimpl = new TSIGKeyImpl(*source.impl_);
  105. delete impl_;
  106. impl_ = newimpl;
  107. return (*this);
  108. }
  109. TSIGKey::~TSIGKey() {
  110. delete impl_;
  111. }
  112. const Name&
  113. TSIGKey::getKeyName() const {
  114. return (impl_->key_name_);
  115. }
  116. const Name&
  117. TSIGKey::getAlgorithmName() const {
  118. return (impl_->algorithm_name_);
  119. }
  120. const void*
  121. TSIGKey::getSecret() const {
  122. return ((impl_->secret_.size() > 0) ? &impl_->secret_[0] : NULL);
  123. }
  124. size_t
  125. TSIGKey::getSecretLength() const {
  126. return (impl_->secret_.size());
  127. }
  128. std::string
  129. TSIGKey::toText() const {
  130. const vector<uint8_t> secret_v(static_cast<const uint8_t*>(getSecret()),
  131. static_cast<const uint8_t*>(getSecret()) +
  132. getSecretLength());
  133. std::string secret_str = encodeBase64(secret_v);
  134. return (getKeyName().toText() + ":" + secret_str + ":" +
  135. getAlgorithmName().toText());
  136. }
  137. const
  138. Name& TSIGKey::HMACMD5_NAME() {
  139. static Name alg_name("hmac-md5.sig-alg.reg.int");
  140. return (alg_name);
  141. }
  142. const
  143. Name& TSIGKey::HMACSHA1_NAME() {
  144. static Name alg_name("hmac-sha1");
  145. return (alg_name);
  146. }
  147. const
  148. Name& TSIGKey::HMACSHA256_NAME() {
  149. static Name alg_name("hmac-sha256");
  150. return (alg_name);
  151. }
  152. struct TSIGKeyRing::TSIGKeyRingImpl {
  153. typedef map<Name, TSIGKey> TSIGKeyMap;
  154. typedef pair<Name, TSIGKey> NameAndKey;
  155. TSIGKeyMap keys;
  156. };
  157. TSIGKeyRing::TSIGKeyRing() : impl_(new TSIGKeyRingImpl) {
  158. }
  159. TSIGKeyRing::~TSIGKeyRing() {
  160. delete impl_;
  161. }
  162. unsigned int
  163. TSIGKeyRing::size() const {
  164. return (impl_->keys.size());
  165. }
  166. TSIGKeyRing::Result
  167. TSIGKeyRing::add(const TSIGKey& key) {
  168. if (impl_->keys.insert(
  169. TSIGKeyRingImpl::NameAndKey(key.getKeyName(), key)).second
  170. == true) {
  171. return (SUCCESS);
  172. } else {
  173. return (EXIST);
  174. }
  175. }
  176. TSIGKeyRing::Result
  177. TSIGKeyRing::remove(const Name& key_name) {
  178. return (impl_->keys.erase(key_name) == 1 ? SUCCESS : NOTFOUND);
  179. }
  180. TSIGKeyRing::FindResult
  181. TSIGKeyRing::find(const Name& key_name) {
  182. TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
  183. impl_->keys.find(key_name);
  184. if (found == impl_->keys.end()) {
  185. return (FindResult(NOTFOUND, NULL));
  186. }
  187. return (FindResult(SUCCESS, &((*found).second)));
  188. }
  189. } // namespace dns
  190. } // namespace isc