1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
|
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __TSIGKEY_H
#define __TSIGKEY_H 1
namespace isc {
namespace dns {
class Name;
/// \brief TSIG key.
///
/// This class holds a TSIG key along with some related attributes as
/// defined in RFC2845.
///
/// A TSIG key consists of the following attributes:
/// - Key name
/// - Hash algorithm
/// - Shared secret
///
/// <b>Implementation Notes</b>
///
/// We may add more attributes in future versions. For example, if and when
/// we support the TKEY protocol (RFC2930), we may need to introduce the
/// notion of inception and expiration times.
/// At that point we may also have to introduce a class hierarchy to handle
/// different types of keys in a polymorphic way.
/// At the moment we use the straightforward value-type class with minimal
/// attributes.
///
/// In the TSIG protocol, hash algorithms are represented in the form of
/// domain name.
/// Our interfaces provide direct translation of this concept; for example,
/// the constructor from parameters take a \c Name object to specify the
/// algorithm.
/// On one hand, this may be counter intuitive.
/// An API user would rather specify "hmac-md5" instead of
/// <code>Name("hmac-md5.sig-alg.reg.int")</code>.
/// On the other hand, it may be more convenient for some kind of applications
/// if we maintain the algorithm as the expected representation for
/// protocol operations (such as sign and very a message).
/// Considering these points, we adopt the interface closer to the protocol
/// specification for now.
/// To minimize the burden for API users, we also define a set of constants
/// for commonly used algorithm names so that the users don't have to
/// remember the actual domain names defined in the protocol specification.
/// We may also have to add conversion routines between domain names
/// and more intuitive representations (e.g. strings) for algorithms.
class TSIGKey {
public:
///
/// \name Constructors, Assignment Operator and Destructor.
///
//@{
/// \brief Constructor from key parameters
///
/// In the current implementation, \c algorithm_name must be a known
/// algorithm to this implementation, which are defined via the
/// <code>static const</code> member functions. For other names
/// an exception of class \c InvalidParameter will be thrown.
/// Note: This restriction may be too strict, and we may revisit it
/// later.
///
/// \c secret and \c secret_len must be consistent in that the latter
/// is 0 if and only if the former is \c NULL;
/// otherwise an exception of type \c InvalidParameter will be thrown.
///
/// This constructor internally involves resource allocation, and if
/// it fails, a corresponding standard exception will be thrown.
///
/// \param key_name The name of the key as a domain name.
/// \param algorithm_name The hash algorithm used for this key in the
/// form of domain name. For example, it can be
/// \c TSIGKey::HMACSHA256_NAME() for HMAC-SHA256.
/// \param secret Point to a binary sequence of the shared secret to be
/// used for this key, or \c NULL if the secret is empty.
/// \param secret_len The size of the binary %data (\c secret) in bytes.
TSIGKey(const Name& key_name, const Name& algorithm_name,
const void* secret, size_t secret_len);
/// \brief The copy constructor.
///
/// It internally allocates a resource, and if it fails a corresponding
/// standard exception will be thrown.
/// This constructor never throws an exception otherwise.
TSIGKey(const TSIGKey& source);
/// \brief Assignment operator.
///
/// It internally allocates a resource, and if it fails a corresponding
/// standard exception will be thrown.
/// This operator never throws an exception otherwise.
///
/// This operator provides the strong exception guarantee: When an
/// exception is thrown the content of the assignment target will be
/// intact.
TSIGKey& operator=(const TSIGKey& source);
/// The destructor.
~TSIGKey();
//@}
///
/// \name Getter Methods
///
/// These methods never throw an exception.
//@{
/// Return the key name.
const Name& getKeyName() const;
/// Return the algorithm name.
const Name& getAlgorithmName() const;
/// Return the length of the TSIG secret in bytes.
size_t getSecretLength() const;
/// Return the value of the TSIG secret.
///
/// If it returns a non NULL pointer, the memory region beginning at the
/// address returned by this method is valid up to the bytes specified
/// by the return value of \c getSecretLength().
///
/// The memory region is only valid while the corresponding \c TSIGKey
/// object is valid. The caller must hold the \c TSIGKey object while
/// it needs to refer to the region or it must make a local copy of the
/// region.
const void* getSecret() const;
//@}
///
/// \name Well known algorithm names as defined in RFC2845 and RFC4635.
///
/// Note: we begin with the "mandatory" algorithms defined in RFC4635
/// as a minimal initial set.
/// We'll add others as we see the need for them.
//@{
static const Name& HMACMD5_NAME(); ///< HMAC-MD5 (RFC2845)
static const Name& HMACSHA1_NAME(); ///< HMAC-SHA1 (RFC4635)
static const Name& HMACSHA256_NAME(); ///< HMAC-SHA256 (RFC4635)
//@}
private:
struct TSIGKeyImpl;
const TSIGKeyImpl* impl_;
};
/// \brief A simple repository of a set of \c TSIGKey objects.
///
/// This is a "key ring" to maintain TSIG keys (\c TSIGKey objects) and
/// provides trivial operations such as add, remove, and find.
///
/// The keys are identified by their key names.
/// So, for example, two or more keys of the same key name but of different
/// algorithms are considered to be the same, and cannot be stored in the
/// key ring at the same time.
///
/// <b>Implementation Note:</b>
/// For simplicity the initial implementation requests the application make
/// a copy of keys stored in the key ring if it needs to use the keys for
/// a long period (during which some of the keys may be removed).
/// This is based on the observations that a single server will not hold
/// a huge number of keys nor use keys in many different contexts (such as
/// in different DNS transactions).
/// If this assumption does not hold and memory consumption becomes an issue
/// we may have to revisit the design.
class TSIGKeyRing {
public:
/// Result codes of various public methods of \c TSIGKeyRing
enum Result {
SUCCESS = 0, ///< The operation is successful.
EXIST = 1, ///< A key is already stored in \c TSIGKeyRing.
NOTFOUND = 2 ///< The specified key is not found in \c TSIGKeyRing.
};
/// \brief A helper structure to represent the search result of
/// <code>TSIGKeyRing::find()</code>.
///
/// This is a straightforward pair of the result code and a pointer
/// to the found key to represent the result of \c find().
/// We use this in order to avoid overloading the return value for both
/// the result code ("success" or "not found") and the found object,
/// i.e., avoid using \c NULL to mean "not found", etc.
///
/// This is a simple value class with no internal state, so for
/// convenience we allow the applications to refer to the members
/// directly.
///
/// See the description of \c find() for the semantics of the member
/// variables.
struct FindResult {
FindResult(Result param_code, const TSIGKey* param_key) :
code(param_code), key(param_key)
{}
const Result code;
const TSIGKey* const key;
};
///
/// \name Constructors and Destructor.
///
/// \b Note:
/// The copy constructor and the assignment operator are
/// intentionally defined as private, making this class non copyable.
/// There is no technical reason why this class cannot be copied,
/// but since the key ring can potentially have a large number of keys,
/// a naive copy operation may cause unexpected overhead.
/// It's generally expected for an application to share the same
/// instance of key ring and share it throughout the program via
/// references, so we prevent the copy operation explicitly to avoid
/// unexpected copy operations.
//@{
private:
TSIGKeyRing(const TSIGKeyRing& source);
TSIGKeyRing& operator=(const TSIGKeyRing& source);
public:
/// \brief The default constructor.
///
/// This constructor never throws an exception.
TSIGKeyRing();
/// The destructor.
~TSIGKeyRing();
//@}
/// Return the number of keys stored in the \c TSIGKeyRing.
///
/// This method never throws an exception.
unsigned int size() const;
/// Add a \c TSIGKey to the \c TSIGKeyRing.
///
/// This method will create a local copy of the given key, so the caller
/// does not have to keep owning it.
///
/// If internal resource allocation fails, a corresponding standard
/// exception will be thrown.
/// This method never throws an exception otherwise.
///
/// \param key A \c TSIGKey to be added.
/// \return \c SUCCESS If the key is successfully added to the key ring.
/// \return \c EXIST The key ring already stores a key whose name is
/// identical to that of \c key.
Result add(const TSIGKey& key);
/// Remove a \c TSIGKey for the given name from the \c TSIGKeyRing.
///
/// This method never throws an exception.
///
/// \param key_name The name of the key to be removed.
/// \return \c SUCCESS If the key is successfully removed from the key
/// ring.
/// \return \c NOTFOUND The key ring does not store the key that matches
/// \c key_name.
Result remove(const Name& key_name);
/// Find a \c TSIGKey for the given name in the \c TSIGKeyRing.
///
/// It searches the internal storage for a \c TSIGKey whose name is
/// \c key_name, and returns the result in the form of a \c FindResult
/// object as follows:
/// - \c code: \c SUCCESS if a key is found; otherwise \c NOTFOUND.
/// - \c key: A pointer to the found \c TSIGKey object if one is found;
/// otherwise \c NULL.
///
/// The pointer returned in the \c FindResult object is only valid until
/// the corresponding key is removed from the key ring.
/// The caller must ensure that the key is held in the key ring while
/// it needs to refer to it, or it must make a local copy of the key.
///
/// This method never throws an exception.
///
/// \param key_name The name of the key to be found.
/// \return A \c FindResult object enclosing the search result (see above).
FindResult find(const Name& key_name);
private:
struct TSIGKeyRingImpl;
TSIGKeyRingImpl* impl_;
};
}
}
#endif // __TSIGKEY_H
// Local Variables:
// mode: c++
// End:
|