Kea  1.9.9-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 {
103  const HashAlgorithm algorithm = convertAlgorithmName(algorithm_name);
104  if ((secret != NULL && secret_len == 0) ||
105  (secret == NULL && secret_len != 0)) {
107  "TSIGKey secret and its length are inconsistent: " <<
108  key_name << ":" << algorithm_name);
109  }
110  if (algorithm == isc::cryptolink::UNKNOWN_HASH && secret_len != 0) {
112  "TSIGKey with unknown algorithm has non empty secret: " <<
113  key_name << ":" << algorithm_name);
114  }
115  if (secret == NULL) {
116  impl_ = new TSIGKeyImpl(key_name, algorithm_name, algorithm,
117  digestbits);
118  } else {
119  impl_ = new TSIGKeyImpl(key_name, algorithm_name, algorithm,
120  digestbits, secret, secret_len);
121  }
122 }
123 
124 TSIGKey::TSIGKey(const std::string& str) : impl_(NULL) {
125  try {
126  istringstream iss(str);
127 
128  string keyname_str;
129  getline(iss, keyname_str, ':');
130  if (iss.fail() || iss.bad() || iss.eof()) {
131  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
132  }
133 
134  string secret_str;
135  getline(iss, secret_str, ':');
136  if (iss.fail() || iss.bad()) {
137  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
138  }
139 
140  string algo_str;
141  if (!iss.eof()) {
142  getline(iss, algo_str, ':');
143  }
144  if (iss.fail() || iss.bad()) {
145  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
146  }
147 
148  string dgstbt_str;
149  if (!iss.eof()) {
150  getline(iss, dgstbt_str);
151  }
152  if (iss.fail() || iss.bad()) {
153  isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
154  }
155 
156  const Name algo_name(algo_str.empty() ? "hmac-md5.sig-alg.reg.int" :
157  algo_str);
158  const HashAlgorithm algorithm = convertAlgorithmName(algo_name);
159  size_t digestbits = 0;
160  try {
161  if (!dgstbt_str.empty()) {
162  digestbits = boost::lexical_cast<size_t>(dgstbt_str);
163  }
164  } catch (const boost::bad_lexical_cast&) {
166  "TSIG key with non-numeric digestbits: " << dgstbt_str);
167  }
168 
169  vector<uint8_t> secret;
170  isc::util::encode::decodeBase64(secret_str, secret);
171 
172  if (algorithm == isc::cryptolink::UNKNOWN_HASH && !secret.empty()) {
174  "TSIG key with unknown algorithm has non empty secret: "
175  << str);
176  }
177 
178  if (secret.empty()) {
179  impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
180  digestbits);
181  } else {
182  impl_ = new TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
183  digestbits, &secret[0], secret.size());
184  }
185  } catch (const isc::Exception& e) {
186  // 'reduce' the several types of exceptions name parsing and
187  // Base64 decoding can throw to just the InvalidParameter
189  }
190 }
191 
192 
193 TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_))
194 {}
195 
196 TSIGKey&
197 TSIGKey::operator=(const TSIGKey& source) {
198  if (this == &source) {
199  return (*this);
200  }
201 
202  TSIGKeyImpl* newimpl = new TSIGKeyImpl(*source.impl_);
203  delete impl_;
204  impl_ = newimpl;
205 
206  return (*this);
207 }
208 
210  delete impl_;
211 }
212 
213 const Name&
215  return (impl_->key_name_);
216 }
217 
218 const Name&
220  return (impl_->algorithm_name_);
221 }
222 
225  return (impl_->algorithm_);
226 }
227 
228 size_t
230  return (impl_->digestbits_);
231 }
232 
233 const void*
235  return ((impl_->secret_.size() > 0) ? &impl_->secret_[0] : NULL);
236 }
237 
238 size_t
240  return (impl_->secret_.size());
241 }
242 
243 std::string
245  size_t digestbits = getDigestbits();
246  const vector<uint8_t> secret_v(static_cast<const uint8_t*>(getSecret()),
247  static_cast<const uint8_t*>(getSecret()) +
248  getSecretLength());
249  std::string secret_str = isc::util::encode::encodeBase64(secret_v);
250 
251  if (digestbits) {
252  std::string dgstbt_str = boost::lexical_cast<std::string>(static_cast<int>(digestbits));
253  return (getKeyName().toText() + ":" + secret_str + ":" +
254  getAlgorithmName().toText() + ":" + dgstbt_str);
255  } else {
256  return (getKeyName().toText() + ":" + secret_str + ":" +
258  }
259 }
260 
261 const
263  static Name alg_name("hmac-md5.sig-alg.reg.int");
264  return (alg_name);
265 }
266 
267 const
269  static Name alg_name("hmac-md5");
270  return (alg_name);
271 }
272 
273 const
275  static Name alg_name("hmac-sha1");
276  return (alg_name);
277 }
278 
279 const
281  static Name alg_name("hmac-sha256");
282  return (alg_name);
283 }
284 
285 const
287  static Name alg_name("hmac-sha224");
288  return (alg_name);
289 }
290 
291 const
293  static Name alg_name("hmac-sha384");
294  return (alg_name);
295 }
296 
297 const
299  static Name alg_name("hmac-sha512");
300  return (alg_name);
301 }
302 
303 const
305  static Name alg_name("gss-tsig");
306  return (alg_name);
307 }
308 
310  typedef map<Name, TSIGKey> TSIGKeyMap;
311  typedef pair<Name, TSIGKey> NameAndKey;
312  TSIGKeyMap keys;
313 };
314 
316 }
317 
319  delete impl_;
320 }
321 
322 unsigned int
324  return (impl_->keys.size());
325 }
326 
329  if (impl_->keys.insert(
330  TSIGKeyRingImpl::NameAndKey(key.getKeyName(), key)).second
331  == true) {
332  return (SUCCESS);
333  } else {
334  return (EXIST);
335  }
336 }
337 
339 TSIGKeyRing::remove(const Name& key_name) {
340  return (impl_->keys.erase(key_name) == 1 ? SUCCESS : NOTFOUND);
341 }
342 
344 TSIGKeyRing::find(const Name& key_name) const {
345  TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
346  impl_->keys.find(key_name);
347  if (found == impl_->keys.end()) {
348  return (FindResult(NOTFOUND, NULL));
349  }
350  return (FindResult(SUCCESS, &((*found).second)));
351 }
352 
354 TSIGKeyRing::find(const Name& key_name, const Name& algorithm_name) const {
355  TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
356  impl_->keys.find(key_name);
357  if (found == impl_->keys.end() ||
358  (*found).second.getAlgorithmName() != algorithm_name) {
359  return (FindResult(NOTFOUND, NULL));
360  }
361  return (FindResult(SUCCESS, &((*found).second)));
362 }
363 
364 } // namespace dns
365 } // namespace isc
The Name class encapsulates DNS names.
Definition: name.h:223
isc::cryptolink::HashAlgorithm getAlgorithm() const
Return the hash algorithm name in the form of cryptolink::HashAlgorithm.
Definition: tsigkey.cc:224
The operation is successful.
Definition: tsigkey.h:250
const void * getSecret() const
Return the value of the TSIG secret.
Definition: tsigkey.cc:234
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:310
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:286
STL namespace.
static const Name & HMACSHA1_NAME()
HMAC-SHA1 (RFC4635)
Definition: tsigkey.cc:274
~TSIGKey()
The destructor.
Definition: tsigkey.cc:209
static const Name & HMACSHA256_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:280
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
const Name & getAlgorithmName() const
Return the algorithm name.
Definition: tsigkey.cc:219
static const Name & HMACSHA512_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:298
Result add(const TSIGKey &key)
Add a TSIGKey to the TSIGKeyRing.
Definition: tsigkey.cc:328
static const Name & HMACMD5_NAME()
HMAC-MD5 (RFC2845)
Definition: tsigkey.cc:262
size_t getDigestbits() const
Return the minimum truncated length.
Definition: tsigkey.cc:229
const Name & getKeyName() const
Return the key name.
Definition: tsigkey.cc:214
FindResult find(const Name &key_name) const
Find a TSIGKey for the given name in the TSIGKeyRing.
Definition: tsigkey.cc:344
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
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
pair< Name, TSIGKey > NameAndKey
Definition: tsigkey.cc:311
TSIGKey & operator=(const TSIGKey &source)
Assignment operator.
Definition: tsigkey.cc:197
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
TSIGKeyRing()
The default constructor.
Definition: tsigkey.cc:315
std::string encodeBase64(const std::vector< uint8_t > &binary)
Encode binary data in the base64 format.
Definition: base_n.cc:449
size_t getSecretLength() const
Return the length of the TSIG secret in bytes.
Definition: tsigkey.cc:239
static const Name & HMACMD5_SHORT_NAME()
Definition: tsigkey.cc:268
static const Name & GSSTSIG_NAME()
GSS-TSIG (RFC3645)
Definition: tsigkey.cc:304
~TSIGKeyRing()
The destructor.
Definition: tsigkey.cc:318
The specified key is not found in TSIGKeyRing.
Definition: tsigkey.h:252
unsigned int size() const
Return the number of keys stored in the TSIGKeyRing.
Definition: tsigkey.cc:323
const isc::cryptolink::HashAlgorithm algorithm_
Definition: tsigkey.cc:94
std::string toText() const
Converts the TSIGKey to a string value.
Definition: tsigkey.cc:244
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:339
static const Name & HMACSHA384_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:292
A key is already stored in TSIGKeyRing.
Definition: tsigkey.h:251