Kea 2.2.0
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
15
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
24using namespace std;
25using namespace isc::cryptolink;
26
27namespace isc {
28namespace dns {
29namespace {
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()) {
43 }
44 if (name == TSIGKey::HMACSHA224_NAME()) {
46 }
47 if (name == TSIGKey::HMACSHA384_NAME()) {
49 }
50 if (name == TSIGKey::HMACSHA512_NAME()) {
52 }
53
55 }
56}
57
58struct
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 }
96 const vector<uint8_t> secret_;
97};
98
99TSIGKey::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
123TSIGKey::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
192TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_)) {
193}
194
195TSIGKey&
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
212const Name&
214 return (impl_->key_name_);
215}
216
217const Name&
219 return (impl_->algorithm_name_);
220}
221
224 return (impl_->algorithm_);
225}
226
227size_t
229 return (impl_->digestbits_);
230}
231
232const void*
234 return ((impl_->secret_.size() > 0) ? &impl_->secret_[0] : NULL);
235}
236
237size_t
239 return (impl_->secret_.size());
240}
241
242std::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()) +
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
260const
262 static Name alg_name("hmac-md5.sig-alg.reg.int");
263 return (alg_name);
264}
265
266const
268 static Name alg_name("hmac-md5");
269 return (alg_name);
270}
271
272const
274 static Name alg_name("hmac-sha1");
275 return (alg_name);
276}
277
278const
280 static Name alg_name("hmac-sha256");
281 return (alg_name);
282}
283
284const
286 static Name alg_name("hmac-sha224");
287 return (alg_name);
288}
289
290const
292 static Name alg_name("hmac-sha384");
293 return (alg_name);
294}
295
296const
298 static Name alg_name("hmac-sha512");
299 return (alg_name);
300}
301
302const
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;
312};
313
315}
316
318 delete impl_;
319}
320
321unsigned 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
338TSIGKeyRing::remove(const Name& key_name) {
339 return (impl_->keys.erase(key_name) == 1 ? SUCCESS : NOTFOUND);
340}
341
343TSIGKeyRing::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
353TSIGKeyRing::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
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
The Name class encapsulates DNS names.
Definition: name.h:223
~TSIGKeyRing()
The destructor.
Definition: tsigkey.cc:317
unsigned int size() const
Return the number of keys stored in the TSIGKeyRing.
Definition: tsigkey.cc:322
Result remove(const Name &key_name)
Remove a TSIGKey for the given name from the TSIGKeyRing.
Definition: tsigkey.cc:338
TSIGKeyRing()
The default constructor.
Definition: tsigkey.cc:314
Result add(const TSIGKey &key)
Add a TSIGKey to the TSIGKeyRing.
Definition: tsigkey.cc:327
FindResult find(const Name &key_name) const
Find a TSIGKey for the given name in the TSIGKeyRing.
Definition: tsigkey.cc:343
Result
Result codes of various public methods of TSIGKeyRing.
Definition: tsigkey.h:249
@ EXIST
A key is already stored in TSIGKeyRing.
Definition: tsigkey.h:251
@ NOTFOUND
The specified key is not found in TSIGKeyRing.
Definition: tsigkey.h:252
@ SUCCESS
The operation is successful.
Definition: tsigkey.h:250
TSIG key.
Definition: tsigkey.h:56
static const Name & HMACMD5_NAME()
HMAC-MD5 (RFC2845)
Definition: tsigkey.cc:261
static const Name & HMACSHA224_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:285
const Name & getAlgorithmName() const
Return the algorithm name.
Definition: tsigkey.cc:218
virtual ~TSIGKey()
The destructor.
Definition: tsigkey.cc:208
static const Name & GSSTSIG_NAME()
GSS-TSIG (RFC3645)
Definition: tsigkey.cc:303
size_t getDigestbits() const
Return the minimum truncated length.
Definition: tsigkey.cc:228
static const Name & HMACSHA256_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:279
TSIGKey & operator=(const TSIGKey &source)
Assignment operator.
Definition: tsigkey.cc:196
isc::cryptolink::HashAlgorithm getAlgorithm() const
Return the hash algorithm name in the form of cryptolink::HashAlgorithm.
Definition: tsigkey.cc:223
static const Name & HMACSHA1_NAME()
HMAC-SHA1 (RFC4635)
Definition: tsigkey.cc:273
const Name & getKeyName() const
Return the key name.
Definition: tsigkey.cc:213
static const Name & HMACMD5_SHORT_NAME()
Definition: tsigkey.cc:267
static const Name & HMACSHA512_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:297
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
static const Name & HMACSHA384_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:291
std::string toText() const
Converts the TSIGKey to a string value.
Definition: tsigkey.cc:243
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
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
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
std::string encodeBase64(const std::vector< uint8_t > &binary)
Encode binary data in the base64 format.
Definition: base_n.cc:449
Defines the logger used by the top-level component of kea-lfc.
A helper structure to represent the search result of TSIGKeyRing::find().
Definition: tsigkey.h:270
map< Name, TSIGKey > TSIGKeyMap
Definition: tsigkey.cc:309
pair< Name, TSIGKey > NameAndKey
Definition: tsigkey.cc:310
const isc::cryptolink::HashAlgorithm algorithm_
Definition: tsigkey.cc:94
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
TSIGKeyImpl(const Name &key_name, const Name &algorithm_name, isc::cryptolink::HashAlgorithm algorithm, size_t digestbits)
Definition: tsigkey.cc:60
const vector< uint8_t > secret_
Definition: tsigkey.cc:96