Kea 1.9.11
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{
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
124TSIGKey::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
193TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_))
194{}
195
196TSIGKey&
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
213const Name&
215 return (impl_->key_name_);
216}
217
218const Name&
220 return (impl_->algorithm_name_);
221}
222
225 return (impl_->algorithm_);
226}
227
228size_t
230 return (impl_->digestbits_);
231}
232
233const void*
235 return ((impl_->secret_.size() > 0) ? &impl_->secret_[0] : NULL);
236}
237
238size_t
240 return (impl_->secret_.size());
241}
242
243std::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()) +
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
261const
263 static Name alg_name("hmac-md5.sig-alg.reg.int");
264 return (alg_name);
265}
266
267const
269 static Name alg_name("hmac-md5");
270 return (alg_name);
271}
272
273const
275 static Name alg_name("hmac-sha1");
276 return (alg_name);
277}
278
279const
281 static Name alg_name("hmac-sha256");
282 return (alg_name);
283}
284
285const
287 static Name alg_name("hmac-sha224");
288 return (alg_name);
289}
290
291const
293 static Name alg_name("hmac-sha384");
294 return (alg_name);
295}
296
297const
299 static Name alg_name("hmac-sha512");
300 return (alg_name);
301}
302
303const
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;
313};
314
316}
317
319 delete impl_;
320}
321
322unsigned 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
339TSIGKeyRing::remove(const Name& key_name) {
340 return (impl_->keys.erase(key_name) == 1 ? SUCCESS : NOTFOUND);
341}
342
344TSIGKeyRing::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
354TSIGKeyRing::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
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:318
unsigned int size() const
Return the number of keys stored in the TSIGKeyRing.
Definition: tsigkey.cc:323
Result remove(const Name &key_name)
Remove a TSIGKey for the given name from the TSIGKeyRing.
Definition: tsigkey.cc:339
TSIGKeyRing()
The default constructor.
Definition: tsigkey.cc:315
Result add(const TSIGKey &key)
Add a TSIGKey to the TSIGKeyRing.
Definition: tsigkey.cc:328
FindResult find(const Name &key_name) const
Find a TSIGKey for the given name in the TSIGKeyRing.
Definition: tsigkey.cc:344
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:262
static const Name & HMACSHA224_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:286
const Name & getAlgorithmName() const
Return the algorithm name.
Definition: tsigkey.cc:219
virtual ~TSIGKey()
The destructor.
Definition: tsigkey.cc:209
static const Name & GSSTSIG_NAME()
GSS-TSIG (RFC3645)
Definition: tsigkey.cc:304
size_t getDigestbits() const
Return the minimum truncated length.
Definition: tsigkey.cc:229
static const Name & HMACSHA256_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:280
TSIGKey & operator=(const TSIGKey &source)
Assignment operator.
Definition: tsigkey.cc:197
isc::cryptolink::HashAlgorithm getAlgorithm() const
Return the hash algorithm name in the form of cryptolink::HashAlgorithm.
Definition: tsigkey.cc:224
static const Name & HMACSHA1_NAME()
HMAC-SHA1 (RFC4635)
Definition: tsigkey.cc:274
const Name & getKeyName() const
Return the key name.
Definition: tsigkey.cc:214
static const Name & HMACMD5_SHORT_NAME()
Definition: tsigkey.cc:268
static const Name & HMACSHA512_NAME()
HMAC-SHA256 (RFC4635)
Definition: tsigkey.cc:298
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:292
std::string toText() const
Converts the TSIGKey to a string value.
Definition: tsigkey.cc:244
size_t getSecretLength() const
Return the length of the TSIG secret in bytes.
Definition: tsigkey.cc:239
const void * getSecret() const
Return the value of the TSIG secret.
Definition: tsigkey.cc:234
#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:310
pair< Name, TSIGKey > NameAndKey
Definition: tsigkey.cc:311
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