Kea  2.1.7-git
tsigkey.cc
Go to the documentation of this file.
1 // Copyright (C) 2010-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <map>
10 #include <utility>
11 #include <vector>
12 #include <sstream>
13 
14 #include <exceptions/exceptions.h>
15 
16 #include <cryptolink/cryptolink.h>
17 
18 #include <dns/name.h>
19 #include <util/encode/base64.h>
20 #include <dns/tsigkey.h>
21 
22 #include <boost/lexical_cast.hpp>
23 
24 using namespace std;
25 using namespace isc::cryptolink;
26 
27 namespace isc {
28 namespace dns {
29 namespace {
31  convertAlgorithmName(const isc::dns::Name& name) {
32  if (name == TSIGKey::HMACMD5_NAME()) {
33  return (isc::cryptolink::MD5);
34  }
35  if (name == TSIGKey::HMACMD5_SHORT_NAME()) {
36  return (isc::cryptolink::MD5);
37  }
38  if (name == TSIGKey::HMACSHA1_NAME()) {
39  return (isc::cryptolink::SHA1);
40  }
41  if (name == TSIGKey::HMACSHA256_NAME()) {
42  return (isc::cryptolink::SHA256);
43  }
44  if (name == TSIGKey::HMACSHA224_NAME()) {
45  return (isc::cryptolink::SHA224);
46  }
47  if (name == TSIGKey::HMACSHA384_NAME()) {
48  return (isc::cryptolink::SHA384);
49  }
50  if (name == TSIGKey::HMACSHA512_NAME()) {
51  return (isc::cryptolink::SHA512);
52  }
53 
55  }
56 }
57 
58 struct
60  TSIGKeyImpl(const Name& key_name, const Name& algorithm_name,
62  size_t digestbits) :
63 
64  key_name_(key_name), algorithm_name_(algorithm_name),
65  algorithm_(algorithm), digestbits_(digestbits),
66  secret_()
67  {
68  // Convert the key and algorithm names to the canonical form.
69  key_name_.downcase();
70  if (algorithm == isc::cryptolink::MD5) {
71  algorithm_name_ = TSIGKey::HMACMD5_NAME();
72  }
73  algorithm_name_.downcase();
74  }
75  TSIGKeyImpl(const Name& key_name, const Name& algorithm_name,
77  size_t digestbits,
78  const void* secret, size_t secret_len) :
79 
80  key_name_(key_name), algorithm_name_(algorithm_name),
81  algorithm_(algorithm), digestbits_(digestbits),
82  secret_(static_cast<const uint8_t*>(secret),
83  static_cast<const uint8_t*>(secret) + secret_len)
84  {
85  // Convert the key and algorithm names to the canonical form.
86  key_name_.downcase();
87  if (algorithm == isc::cryptolink::MD5) {
88  algorithm_name_ = TSIGKey::HMACMD5_NAME();
89  }
90  algorithm_name_.downcase();
91  }
95  size_t digestbits_;
96  const vector<uint8_t> secret_;
97 };
98 
99 TSIGKey::TSIGKey(const Name& key_name, const Name& algorithm_name,
100  const void* secret, size_t secret_len,
101  size_t digestbits /*= 0*/) : impl_(NULL) {
102  const HashAlgorithm algorithm = convertAlgorithmName(algorithm_name);
103  if ((secret != NULL && secret_len == 0) ||
104  (secret == NULL && secret_len != 0)) {
106  "TSIGKey secret and its length are inconsistent: " <<
107  key_name << ":" << algorithm_name);
108  }
109  if (algorithm == isc::cryptolink::UNKNOWN_HASH && secret_len != 0) {
111  "TSIGKey with unknown algorithm has non empty secret: " <<
112  key_name << ":" << algorithm_name);
113  }
114  if (secret == NULL) {
115  impl_ = new TSIGKeyImpl(key_name, algorithm_name, algorithm,
116  digestbits);
117  } else {
118  impl_ = new TSIGKeyImpl(key_name, algorithm_name, algorithm,
119  digestbits, secret, secret_len);
120  }
121 }
122 
123 TSIGKey::TSIGKey(const std::string& str) : impl_(NULL) {
124  try {
125  istringstream iss(str);
126 
127  string keyname_str;
128  getline(iss, keyname_str, ':');
129  if (iss.fail() || iss.bad() || iss.eof()) {
130  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
131  }
132 
133  string secret_str;
134  getline(iss, secret_str, ':');
135  if (iss.fail() || iss.bad()) {
136  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
137  }
138 
139  string algo_str;
140  if (!iss.eof()) {
141  getline(iss, algo_str, ':');
142  }
143  if (iss.fail() || iss.bad()) {
144  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
145  }
146 
147  string dgstbt_str;
148  if (!iss.eof()) {
149  getline(iss, dgstbt_str);
150  }
151  if (iss.fail() || iss.bad()) {
152  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
153  }
154 
155  const Name algo_name(algo_str.empty() ? "hmac-md5.sig-alg.reg.int" :
156  algo_str);
157  const HashAlgorithm algorithm = convertAlgorithmName(algo_name);
158  size_t digestbits = 0;
159  try {
160  if (!dgstbt_str.empty()) {
161  digestbits = boost::lexical_cast<size_t>(dgstbt_str);
162  }
163  } catch (const boost::bad_lexical_cast&) {
165  "TSIG key with non-numeric digestbits: " << dgstbt_str);
166  }
167 
168  vector<uint8_t> secret;
169  isc::util::encode::decodeBase64(secret_str, secret);
170 
171  if (algorithm == isc::cryptolink::UNKNOWN_HASH && !secret.empty()) {
173  "TSIG key with unknown algorithm has non empty secret: "
174  << str);
175  }
176 
177  if (secret.empty()) {
178  impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
179  digestbits);
180  } else {
181  impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
182  digestbits, &secret[0], secret.size());
183  }
184  } catch (const isc::Exception& e) {
185  // 'reduce' the several types of exceptions name parsing and
186  // Base64 decoding can throw to just the InvalidParameter
188  }
189 }
190 
191 
192 TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_)) {
193 }
194 
195 TSIGKey&
196 TSIGKey::operator=(const TSIGKey& source) {
197  if (this == &source) {
198  return (*this);
199  }
200 
201  TSIGKeyImpl* newimpl = new TSIGKeyImpl(*source.impl_);
202  delete impl_;
203  impl_ = newimpl;
204 
205  return (*this);
206 }
207 
209  delete impl_;
210 }
211 
212 const Name&
214  return (impl_->key_name_);
215 }
216 
217 const Name&
219  return (impl_->algorithm_name_);
220 }
221 
224  return (impl_->algorithm_);
225 }
226 
227 size_t
229  return (impl_->digestbits_);
230 }
231 
232 const void*
234  return ((impl_->secret_.size() > 0) ? &impl_->secret_[0] : NULL);
235 }
236 
237 size_t
239  return (impl_->secret_.size());
240 }
241 
242 std::string
244  size_t digestbits = getDigestbits();
245  const vector<uint8_t> secret_v(static_cast<const uint8_t*>(getSecret()),
246  static_cast<const uint8_t*>(getSecret()) +
247  getSecretLength());
248  std::string secret_str = isc::util::encode::encodeBase64(secret_v);
249 
250  if (digestbits) {
251  std::string dgstbt_str = boost::lexical_cast<std::string>(static_cast<int>(digestbits));
252  return (getKeyName().toText() + ":" + secret_str + ":" +
253  getAlgorithmName().toText() + ":" + dgstbt_str);
254  } else {
255  return (getKeyName().toText() + ":" + secret_str + ":" +
257  }
258 }
259 
260 const
262  static Name alg_name("hmac-md5.sig-alg.reg.int");
263  return (alg_name);
264 }
265 
266 const
268  static Name alg_name("hmac-md5");
269  return (alg_name);
270 }
271 
272 const
274  static Name alg_name("hmac-sha1");
275  return (alg_name);
276 }
277 
278 const
280  static Name alg_name("hmac-sha256");
281  return (alg_name);
282 }
283 
284 const
286  static Name alg_name("hmac-sha224");
287  return (alg_name);
288 }
289 
290 const
292  static Name alg_name("hmac-sha384");
293  return (alg_name);
294 }
295 
296 const
298  static Name alg_name("hmac-sha512");
299  return (alg_name);
300 }
301 
302 const
304  static Name alg_name("gss-tsig");
305  return (alg_name);
306 }
307 
309  typedef map<Name, TSIGKey> TSIGKeyMap;
310  typedef pair<Name, TSIGKey> NameAndKey;
311  TSIGKeyMap keys;
312 };
313 
315 }
316 
318  delete impl_;
319 }
320 
321 unsigned int
323  return (impl_->keys.size());
324 }
325 
328  if (impl_->keys.insert(
329  TSIGKeyRingImpl::NameAndKey(key.getKeyName(), key)).second
330  == true) {
331  return (SUCCESS);
332  } else {
333  return (EXIST);
334  }
335 }
336 
338 TSIGKeyRing::remove(const Name& key_name) {
339  return (impl_->keys.erase(key_name) == 1 ? SUCCESS : NOTFOUND);
340 }
341 
343 TSIGKeyRing::find(const Name& key_name) const {
344  TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
345  impl_->keys.find(key_name);
346  if (found == impl_->keys.end()) {
347  return (FindResult(NOTFOUND, NULL));
348  }
349  return (FindResult(SUCCESS, &((*found).second)));
350 }
351 
353 TSIGKeyRing::find(const Name& key_name, const Name& algorithm_name) const {
354  TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
355  impl_->keys.find(key_name);
356  if (found == impl_->keys.end() ||
357  (*found).second.getAlgorithmName() != algorithm_name) {
358  return (FindResult(NOTFOUND, NULL));
359  }
360  return (FindResult(SUCCESS, &((*found).second)));
361 }
362 
363 } // namespace dns
364 } // namespace isc
The Name class encapsulates DNS names.
Definition: name.h:223
The operation is successful.
Definition: tsigkey.h:250
TSIGKeyImpl(const Name &key_name, const Name &algorithm_name, isc::cryptolink::HashAlgorithm algorithm, size_t digestbits)
Definition: tsigkey.cc:60
map< Name, TSIGKey > TSIGKeyMap
Definition: tsigkey.cc:309
Result
Result codes of various public methods of TSIGKeyRing.
Definition: tsigkey.h:249
TSIG key.
Definition: tsigkey.h:56
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
TSIGKey(const Name &key_name, const Name &algorithm_name, const void *secret, size_t secret_len, size_t digestbits=0)
Constructor from key parameters.
Definition: tsigkey.cc:99
TSIGKeyImpl(const Name &key_name, const Name &algorithm_name, isc::cryptolink::HashAlgorithm algorithm, size_t digestbits, const void *secret, size_t secret_len)
Definition: tsigkey.cc:75
A helper structure to represent the search result of TSIGKeyRing::find().
Definition: tsigkey.h:270
static const Name & HMACSHA224_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:285
const Name & getKeyName() const
Return the key name.
Definition: tsigkey.cc:213
STL namespace.
static const Name & HMACSHA1_NAME()
HMAC-SHA1 (RFC4635)
Definition: tsigkey.cc:273
virtual ~TSIGKey()
The destructor.
Definition: tsigkey.cc:208
size_t getDigestbits() const
Return the minimum truncated length.
Definition: tsigkey.cc:228
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
unsigned int size() const
Return the number of keys stored in the TSIGKeyRing.
Definition: tsigkey.cc:322
static const Name & HMACSHA256_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:279
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
std::string toText() const
Converts the TSIGKey to a string value.
Definition: tsigkey.cc:243
static const Name & HMACSHA512_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:297
Result add(const TSIGKey &key)
Add a TSIGKey to the TSIGKeyRing.
Definition: tsigkey.cc:327
static const Name & HMACMD5_NAME()
HMAC-MD5 (RFC2845)
Definition: tsigkey.cc:261
void decodeBase64(const std::string &input, std::vector< uint8_t > &result)
Decode a text encoded in the base64 format into the original data.
Definition: base_n.cc:454
pair< Name, TSIGKey > NameAndKey
Definition: tsigkey.cc:310
TSIGKey & operator=(const TSIGKey &source)
Assignment operator.
Definition: tsigkey.cc:196
FindResult find(const Name &key_name) const
Find a TSIGKey for the given name in the TSIGKeyRing.
Definition: tsigkey.cc:343
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-lfc.
TSIGKeyRing()
The default constructor.
Definition: tsigkey.cc:314
std::string encodeBase64(const std::vector< uint8_t > &binary)
Encode binary data in the base64 format.
Definition: base_n.cc:449
const Name & getAlgorithmName() const
Return the algorithm name.
Definition: tsigkey.cc:218
static const Name & HMACMD5_SHORT_NAME()
Definition: tsigkey.cc:267
static const Name & GSSTSIG_NAME()
GSS-TSIG (RFC3645)
Definition: tsigkey.cc:303
~TSIGKeyRing()
The destructor.
Definition: tsigkey.cc:317
The specified key is not found in TSIGKeyRing.
Definition: tsigkey.h:252
isc::cryptolink::HashAlgorithm getAlgorithm() const
Return the hash algorithm name in the form of cryptolink::HashAlgorithm.
Definition: tsigkey.cc:223
const isc::cryptolink::HashAlgorithm algorithm_
Definition: tsigkey.cc:94
const vector< uint8_t > secret_
Definition: tsigkey.cc:96
Result remove(const Name &key_name)
Remove a TSIGKey for the given name from the TSIGKeyRing.
Definition: tsigkey.cc:338
size_t getSecretLength() const
Return the length of the TSIG secret in bytes.
Definition: tsigkey.cc:238
const void * getSecret() const
Return the value of the TSIG secret.
Definition: tsigkey.cc:233
static const Name & HMACSHA384_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:291
A key is already stored in TSIGKeyRing.
Definition: tsigkey.h:251