Kea 2.5.8
tsigkey.cc
Go to the documentation of this file.
1// Copyright (C) 2010-2024 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/encode.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 {
29struct
31 TSIGKeyImpl(const Name& key_name, const Name& algorithm_name,
33 size_t digestbits) :
34 key_name_(key_name), algorithm_name_(algorithm_name),
35 algorithm_(algorithm), digestbits_(digestbits),
36 secret_() {
37 // Convert the key and algorithm names to the canonical form.
38 key_name_.downcase();
39 if (algorithm == isc::cryptolink::MD5) {
40 algorithm_name_ = TSIGKey::HMACMD5_NAME();
41 }
42 algorithm_name_.downcase();
43 }
44 TSIGKeyImpl(const Name& key_name, const Name& algorithm_name,
46 size_t digestbits,
47 const void* secret, size_t secret_len) :
48 key_name_(key_name), algorithm_name_(algorithm_name),
49 algorithm_(algorithm), digestbits_(digestbits),
50 secret_(static_cast<const uint8_t*>(secret),
51 static_cast<const uint8_t*>(secret) + secret_len) {
52 // Convert the key and algorithm names to the canonical form.
53 key_name_.downcase();
54 if (algorithm == isc::cryptolink::MD5) {
55 algorithm_name_ = TSIGKey::HMACMD5_NAME();
56 }
57 algorithm_name_.downcase();
58 }
63 const vector<uint8_t> secret_;
64};
65
66namespace {
68 convertAlgorithmName(const isc::dns::Name& name) {
69 if (name == TSIGKey::HMACMD5_NAME()) {
70 return (isc::cryptolink::MD5);
71 }
72 if (name == TSIGKey::HMACMD5_SHORT_NAME()) {
73 return (isc::cryptolink::MD5);
74 }
75 if (name == TSIGKey::HMACSHA1_NAME()) {
76 return (isc::cryptolink::SHA1);
77 }
78 if (name == TSIGKey::HMACSHA224_NAME()) {
80 }
81 if (name == TSIGKey::HMACSHA256_NAME()) {
83 }
84 if (name == TSIGKey::HMACSHA384_NAME()) {
86 }
87 if (name == TSIGKey::HMACSHA512_NAME()) {
89 }
90
92 }
93}
94
95TSIGKey::TSIGKey(const Name& key_name, const Name& algorithm_name,
96 const void* secret, size_t secret_len,
97 size_t digestbits /*= 0*/) : impl_(0) {
98 const HashAlgorithm algorithm = convertAlgorithmName(algorithm_name);
99 if ((secret && secret_len == 0) ||
100 (!secret && secret_len != 0)) {
102 "TSIGKey secret and its length are inconsistent: " <<
103 key_name << ":" << algorithm_name);
104 }
105 if (algorithm == isc::cryptolink::UNKNOWN_HASH && secret_len != 0) {
107 "TSIGKey with unknown algorithm has non empty secret: " <<
108 key_name << ":" << algorithm_name);
109 }
110 if (!secret) {
111 impl_.reset(new TSIGKey::TSIGKeyImpl(key_name, algorithm_name, algorithm,
112 digestbits));
113 } else {
114 impl_.reset(new TSIGKey::TSIGKeyImpl(key_name, algorithm_name, algorithm,
115 digestbits, secret, secret_len));
116 }
117}
118
119TSIGKey::TSIGKey(const std::string& str) : impl_(0) {
120 try {
121 istringstream iss(str);
122
123 string keyname_str;
124 getline(iss, keyname_str, ':');
125 if (iss.fail() || iss.bad() || iss.eof()) {
126 isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
127 }
128
129 string secret_str;
130 getline(iss, secret_str, ':');
131 if (iss.fail() || iss.bad()) {
132 isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
133 }
134
135 string algo_str;
136 if (!iss.eof()) {
137 getline(iss, algo_str, ':');
138 }
139 if (iss.fail() || iss.bad()) {
140 isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
141 }
142
143 string dgstbt_str;
144 if (!iss.eof()) {
145 getline(iss, dgstbt_str);
146 }
147 if (iss.fail() || iss.bad()) {
148 isc_throw(InvalidParameter, "Invalid TSIG key string: " << str);
149 }
150
151 const Name algo_name(algo_str.empty() ? "hmac-md5.sig-alg.reg.int" :
152 algo_str);
153 const HashAlgorithm algorithm = convertAlgorithmName(algo_name);
154 size_t digestbits = 0;
155 try {
156 if (!dgstbt_str.empty()) {
157 digestbits = boost::lexical_cast<size_t>(dgstbt_str);
158 }
159 } catch (const boost::bad_lexical_cast&) {
161 "TSIG key with non-numeric digestbits: " << dgstbt_str);
162 }
163
164 vector<uint8_t> secret;
165 isc::util::encode::decodeBase64(secret_str, secret);
166
167 if (algorithm == isc::cryptolink::UNKNOWN_HASH && !secret.empty()) {
169 "TSIG key with unknown algorithm has non empty secret: "
170 << str);
171 }
172
173 if (secret.empty()) {
174 impl_.reset(new TSIGKey::TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
175 digestbits));
176 } else {
177 impl_.reset(new TSIGKey::TSIGKeyImpl(Name(keyname_str), algo_name, algorithm,
178 digestbits, &secret[0], secret.size()));
179 }
180 } catch (const isc::Exception& e) {
181 // 'reduce' the several types of exceptions name parsing and
182 // Base64 decoding can throw to just the InvalidParameter
184 }
185}
186
187TSIGKey::TSIGKey(const TSIGKey& source) : impl_(new TSIGKeyImpl(*source.impl_)) {
188}
189
190TSIGKey&
192 if (this == &source) {
193 return (*this);
194 }
195
196 impl_.reset(new TSIGKey::TSIGKeyImpl(*source.impl_));
197 return (*this);
198}
199
201}
202
203const Name&
205 return (impl_->key_name_);
206}
207
208const Name&
210 return (impl_->algorithm_name_);
211}
212
215 return (impl_->algorithm_);
216}
217
218size_t
220 return (impl_->digestbits_);
221}
222
223const void*
225 return ((impl_->secret_.size() > 0) ? &impl_->secret_[0] : 0);
226}
227
228size_t
230 return (impl_->secret_.size());
231}
232
233std::string
235 size_t digestbits = getDigestbits();
236 const vector<uint8_t> secret_v(static_cast<const uint8_t*>(getSecret()),
237 static_cast<const uint8_t*>(getSecret()) +
239 std::string secret_str = isc::util::encode::encodeBase64(secret_v);
240
241 if (digestbits) {
242 std::string dgstbt_str = boost::lexical_cast<std::string>(static_cast<int>(digestbits));
243 return (getKeyName().toText() + ":" + secret_str + ":" +
244 getAlgorithmName().toText() + ":" + dgstbt_str);
245 } else {
246 return (getKeyName().toText() + ":" + secret_str + ":" +
248 }
249}
250
252 typedef map<Name, TSIGKey> TSIGKeyMap;
253 typedef pair<Name, TSIGKey> NameAndKey;
255};
256
258}
259
261}
262
263unsigned int
265 return (impl_->keys.size());
266}
267
270 if (impl_->keys.insert(TSIGKeyRingImpl::NameAndKey(key.getKeyName(), key)).second) {
271 return (SUCCESS);
272 } else {
273 return (EXIST);
274 }
275}
276
278TSIGKeyRing::remove(const Name& key_name) {
279 return (impl_->keys.erase(key_name) == 1 ? SUCCESS : NOTFOUND);
280}
281
283TSIGKeyRing::find(const Name& key_name) const {
284 TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
285 impl_->keys.find(key_name);
286 if (found == impl_->keys.end()) {
287 return (FindResult(NOTFOUND, 0));
288 }
289 return (FindResult(SUCCESS, &((*found).second)));
290}
291
293TSIGKeyRing::find(const Name& key_name, const Name& algorithm_name) const {
294 TSIGKeyRingImpl::TSIGKeyMap::const_iterator found =
295 impl_->keys.find(key_name);
296 if (found == impl_->keys.end() ||
297 (*found).second.getAlgorithmName() != algorithm_name) {
298 return (FindResult(NOTFOUND, 0));
299 }
300 return (FindResult(SUCCESS, &((*found).second)));
301}
302
303const
305 static Name alg_name("hmac-md5.sig-alg.reg.int");
306 return (alg_name);
307}
308
309const
311 static Name alg_name("hmac-md5");
312 return (alg_name);
313}
314
315const
317 static Name alg_name("hmac-sha1");
318 return (alg_name);
319}
320
321const
323 static Name alg_name("hmac-sha224");
324 return (alg_name);
325}
326
327const
329 static Name alg_name("hmac-sha256");
330 return (alg_name);
331}
332
333const
335 static Name alg_name("hmac-sha384");
336 return (alg_name);
337}
338
339const
341 static Name alg_name("hmac-sha512");
342 return (alg_name);
343}
344
345const
347 static Name alg_name("gss-tsig");
348 return (alg_name);
349}
350
351} // namespace dns
352} // 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:219
~TSIGKeyRing()
The destructor.
Definition: tsigkey.cc:260
unsigned int size() const
Return the number of keys stored in the TSIGKeyRing.
Definition: tsigkey.cc:264
Result remove(const Name &key_name)
Remove a TSIGKey for the given name from the TSIGKeyRing.
Definition: tsigkey.cc:278
TSIGKeyRing()
The default constructor.
Definition: tsigkey.cc:257
Result add(const TSIGKey &key)
Add a TSIGKey to the TSIGKeyRing.
Definition: tsigkey.cc:269
FindResult find(const Name &key_name) const
Find a TSIGKey for the given name in the TSIGKeyRing.
Definition: tsigkey.cc:283
Result
Result codes of various public methods of TSIGKeyRing.
Definition: tsigkey.h:248
static const Name & HMACMD5_NAME()
Well known algorithm names as defined in RFC2845 and RFC4635.
Definition: tsigkey.cc:304
static const Name & HMACSHA224_NAME()
Definition: tsigkey.cc:322
const Name & getAlgorithmName() const
Return the algorithm name.
Definition: tsigkey.cc:209
virtual ~TSIGKey()
The destructor.
Definition: tsigkey.cc:200
static const Name & GSSTSIG_NAME()
Definition: tsigkey.cc:346
size_t getDigestbits() const
Return the minimum truncated length.
Definition: tsigkey.cc:219
static const Name & HMACSHA256_NAME()
Definition: tsigkey.cc:328
TSIGKey & operator=(const TSIGKey &source)
Assignment operator.
Definition: tsigkey.cc:191
isc::cryptolink::HashAlgorithm getAlgorithm() const
Return the hash algorithm name in the form of cryptolink::HashAlgorithm.
Definition: tsigkey.cc:214
static const Name & HMACSHA1_NAME()
Definition: tsigkey.cc:316
const Name & getKeyName() const
Getter Methods.
Definition: tsigkey.cc:204
static const Name & HMACMD5_SHORT_NAME()
Definition: tsigkey.cc:310
static const Name & HMACSHA512_NAME()
Definition: tsigkey.cc:340
TSIGKey(const Name &key_name, const Name &algorithm_name, const void *secret, size_t secret_len, size_t digestbits=0)
Constructors, Assignment Operator and Destructor.
Definition: tsigkey.cc:95
static const Name & HMACSHA384_NAME()
Definition: tsigkey.cc:334
std::string toText() const
Converts the TSIGKey to a string value.
Definition: tsigkey.cc:234
size_t getSecretLength() const
Return the length of the TSIG secret in bytes.
Definition: tsigkey.cc:229
const void * getSecret() const
Return the value of the TSIG secret.
Definition: tsigkey.cc:224
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
string encodeBase64(const vector< uint8_t > &binary)
Encode binary data in the base64 format.
Definition: encode.cc:337
void decodeBase64(const std::string &encoded_str, std::vector< uint8_t > &output)
Decode a base64 encoded string into binary data.
Definition: encode.cc:343
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:269
map< Name, TSIGKey > TSIGKeyMap
Definition: tsigkey.cc:252
pair< Name, TSIGKey > NameAndKey
Definition: tsigkey.cc:253
const isc::cryptolink::HashAlgorithm algorithm_
Definition: tsigkey.cc:61
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:44
TSIGKeyImpl(const Name &key_name, const Name &algorithm_name, isc::cryptolink::HashAlgorithm algorithm, size_t digestbits)
Definition: tsigkey.cc:31
const vector< uint8_t > secret_
Definition: tsigkey.cc:63