Kea  2.3.8
tsig.cc
Go to the documentation of this file.
1 // Copyright (C) 2011-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 <sys/time.h>
10 
11 #include <stdint.h>
12 
13 #include <cassert>
14 #include <vector>
15 
16 #include <boost/shared_ptr.hpp>
17 
18 #include <exceptions/exceptions.h>
19 
20 #include <util/buffer.h>
21 #include <util/time_utilities.h>
22 
23 #include <dns/rdataclass.h>
24 #include <dns/rrclass.h>
25 #include <dns/tsig.h>
26 #include <dns/tsigerror.h>
27 #include <dns/tsigkey.h>
28 
29 #include <cryptolink/cryptolink.h>
30 #include <cryptolink/crypto_hmac.h>
31 
32 using namespace std;
33 using namespace isc::util;
34 using namespace isc::cryptolink;
35 using namespace isc::dns::rdata;
36 
37 namespace isc {
38 namespace dns {
39 namespace {
40 typedef boost::shared_ptr<HMAC> HMACPtr;
41 
42 // TSIG uses 48-bit unsigned integer to represent time signed.
43 // Since gettimeWrapper() returns a 64-bit *signed* integer, we
44 // make sure it's stored in an unsigned 64-bit integer variable and
45 // represents a value in the expected range. (In reality, however,
46 // gettimeWrapper() will return a positive integer that will fit
47 // in 48 bits)
48 uint64_t
49 getTSIGTime() {
50  return (detail::gettimeWrapper() & 0x0000ffffffffffffULL);
51 }
52 }
53 
56  TSIGError error = TSIGError::NOERROR()) :
57  state_(INIT), key_(key), error_(error),
58  previous_timesigned_(0), digest_len_(0),
59  last_sig_dist_(-1) {
60  if (error == TSIGError::NOERROR()) {
61  // In normal (NOERROR) case, the key should be valid, and we
62  // should be able to pre-create a corresponding HMAC object,
63  // which will be likely to be used for sign or verify later.
64  // We do this in the constructor so that we can know the expected
65  // digest length in advance. The creation should normally succeed,
66  // but the key information could be still broken, which could
67  // trigger an exception inside the cryptolink module. We ignore
68  // it at this moment; a subsequent sign/verify operation will try
69  // to create the HMAC, which would also fail.
70  try {
71  hmac_.reset(CryptoLink::getCryptoLink().createHMAC(
72  key_.getSecret(), key_.getSecretLength(),
73  key_.getAlgorithm()),
74  deleteHMAC);
75  } catch (const isc::Exception&) {
76  return;
77  }
78  size_t digestbits = key_.getDigestbits();
79  size_t default_digest_len = hmac_->getOutputLength();
80  if (digestbits > 0) {
81  digest_len_ = (digestbits + 7) / 8;
82  // sanity (cf. RFC 4635)
83  if ((digest_len_ < 10) ||
84  (digest_len_ < (default_digest_len / 2)) ||
85  (digest_len_ > default_digest_len)) {
86  // should emit a warning?
87  digest_len_ = default_digest_len;
88  }
89  } else {
90  digest_len_ = default_digest_len;
91  }
92  }
93  }
94 
95  // This helper method is used from verify(). It's expected to be called
96  // just before verify() returns. It updates internal state based on
97  // the verification result and return the TSIGError to be returned to
98  // the caller of verify(), so that verify() can call this method within
99  // its 'return' statement.
101  uint16_t digest_len)
102  {
103  if (state_ == INIT) {
104  state_ = RECEIVED_REQUEST;
105  } else if (state_ == SENT_REQUEST && error == TSIGError::NOERROR()) {
106  state_ = VERIFIED_RESPONSE;
107  }
108  if (digest != NULL) {
109  previous_digest_.assign(static_cast<const uint8_t*>(digest),
110  static_cast<const uint8_t*>(digest) +
111  digest_len);
112  }
113  error_ = error;
114  return (error);
115  }
116 
117  // A shortcut method to create an HMAC object for sign/verify. If one
118  // has been successfully created in the constructor, return it; otherwise
119  // create a new one and return it. In the former case, the ownership is
120  // transferred to the caller; the stored HMAC will be reset after the
121  // call.
122  HMACPtr createHMAC() {
123  if (hmac_) {
124  HMACPtr ret = HMACPtr();
125  ret.swap(hmac_);
126  return (ret);
127  }
128  return (HMACPtr(CryptoLink::getCryptoLink().createHMAC(
129  key_.getSecret(), key_.getSecretLength(),
130  key_.getAlgorithm()),
131  deleteHMAC));
132  }
133 
134  // The following three are helper methods to compute the digest for
135  // TSIG sign/verify in order to unify the common code logic for sign()
136  // and verify() and to keep these callers concise.
137  // These methods take an HMAC object, which will be updated with the
138  // calculated digest.
139  // Note: All methods construct a local OutputBuffer as a work space with a
140  // fixed initial buffer size to avoid intermediate buffer extension.
141  // This should be efficient enough, especially for fundamentally expensive
142  // operation like cryptographic sign/verify, but if the creation of the
143  // buffer in each helper method is still identified to be a severe
144  // performance bottleneck, we could have this class a buffer as a member
145  // variable and reuse it throughout the object's lifetime. Right now,
146  // we prefer keeping the scope for local things as small as possible.
147  void digestPreviousMAC(HMACPtr hmac);
148  void digestTSIGVariables(HMACPtr hmac, uint16_t rrclass, uint32_t rrttl,
149  uint64_t time_signed, uint16_t fudge,
150  uint16_t error, uint16_t otherlen,
151  const void* otherdata,
152  bool time_variables_only) const;
153  void digestDNSMessage(HMACPtr hmac, uint16_t qid, const void* data,
154  size_t data_len) const;
156  const TSIGKey key_;
157  vector<uint8_t> previous_digest_;
159  uint64_t previous_timesigned_; // only meaningful for response with BADTIME
160  size_t digest_len_;
161  HMACPtr hmac_;
162  // This is the distance from the last verified signed message. Value of 0
163  // means the last message was signed. Special value -1 means there was no
164  // signed message yet.
166 };
167 
168 void
169 TSIGContext::TSIGContextImpl::digestPreviousMAC(HMACPtr hmac) {
170  // We should have ensured the digest size fits 16 bits within this class
171  // implementation.
172  assert(previous_digest_.size() <= 0xffff);
173 
174  if (previous_digest_.empty()) {
175  // The previous digest was already used. We're in the middle of
176  // TCP stream somewhere and we already pushed some unsigned message
177  // into the HMAC state.
178  return;
179  }
180 
181  OutputBuffer buffer(sizeof(uint16_t) + previous_digest_.size());
182  const uint16_t previous_digest_len(previous_digest_.size());
183  buffer.writeUint16(previous_digest_len);
184  if (previous_digest_len != 0) {
185  buffer.writeData(&previous_digest_[0], previous_digest_len);
186  }
187  hmac->update(buffer.getData(), buffer.getLength());
188 }
189 
190 void
191 TSIGContext::TSIGContextImpl::digestTSIGVariables(
192  HMACPtr hmac, uint16_t rrclass, uint32_t rrttl, uint64_t time_signed,
193  uint16_t fudge, uint16_t error, uint16_t otherlen, const void* otherdata,
194  bool time_variables_only) const {
195  // It's bit complicated, but we can still predict the necessary size of
196  // the data to be digested. So we precompute it to avoid possible
197  // reallocation inside OutputBuffer (not absolutely necessary, but this
198  // is a bit more efficient)
199  size_t data_size = 8;
200  if (!time_variables_only) {
201  data_size += 10 + key_.getKeyName().getLength() +
202  key_.getAlgorithmName().getLength();
203  }
204  OutputBuffer buffer(data_size);
205 
206  if (!time_variables_only) {
207  key_.getKeyName().toWire(buffer);
208  buffer.writeUint16(rrclass);
209  buffer.writeUint32(rrttl);
210  key_.getAlgorithmName().toWire(buffer);
211  }
212  buffer.writeUint16(time_signed >> 32);
213  buffer.writeUint32(time_signed & 0xffffffff);
214  buffer.writeUint16(fudge);
215 
216  if (!time_variables_only) {
217  buffer.writeUint16(error);
218  buffer.writeUint16(otherlen);
219  }
220 
221  hmac->update(buffer.getData(), buffer.getLength());
222  if (!time_variables_only && otherlen > 0) {
223  hmac->update(otherdata, otherlen);
224  }
225 }
226 
227 // In digestDNSMessage, we exploit some minimum knowledge of DNS message
228 // format:
229 // - the header section has a fixed length of 12 octets (MESSAGE_HEADER_LEN)
230 // - the offset in the header section to the ID field is 0
231 // - the offset in the header section to the ARCOUNT field is 10 (and the field
232 // length is 2 octets)
233 // We could construct a separate Message object from the given data, adjust
234 // fields via the Message interfaces and then render it back to a separate
235 // buffer, but that would be overkilling. The DNS message header has a
236 // fixed length and necessary modifications are quite straightforward, so
237 // we do the job using lower level interfaces.
238 namespace {
239 const size_t MESSAGE_HEADER_LEN = 12;
240 }
241 
242 void
243 TSIGContext::TSIGContextImpl::digestDNSMessage(HMACPtr hmac,
244  uint16_t qid, const void* data,
245  size_t data_len) const {
246  OutputBuffer buffer(MESSAGE_HEADER_LEN);
247  const uint8_t* msgptr = static_cast<const uint8_t*>(data);
248 
249  // Install the original ID
250  buffer.writeUint16(qid);
251  msgptr += sizeof(uint16_t);
252 
253  // Copy the rest of the header except the ARCOUNT field.
254  buffer.writeData(msgptr, 8);
255  msgptr += 8;
256 
257  // Install the adjusted ARCOUNT (we don't care even if the value is bogus
258  // and it underflows; it would simply result in verification failure)
259  buffer.writeUint16(InputBuffer(msgptr, sizeof(uint16_t)).readUint16() - 1);
260  msgptr += 2;
261 
262  // Digest the header and the rest of the DNS message
263  hmac->update(buffer.getData(), buffer.getLength());
264  hmac->update(msgptr, data_len - MESSAGE_HEADER_LEN);
265 }
266 
267 TSIGContext::TSIGContext(const TSIGKey& key) : impl_(new TSIGContextImpl(key)) {
268 }
269 
270 TSIGContext::TSIGContext(const Name& key_name, const Name& algorithm_name,
271  const TSIGKeyRing& keyring) : impl_(NULL) {
272  const TSIGKeyRing::FindResult result(keyring.find(key_name,
273  algorithm_name));
274  if (result.code == TSIGKeyRing::NOTFOUND) {
275  // If not key is found, create a dummy key with the specified key
276  // parameters and empty secret. In the common scenario this will
277  // be used in subsequent response with a TSIG indicating a BADKEY
278  // error.
279  impl_ = new TSIGContextImpl(TSIGKey(key_name, algorithm_name,
280  NULL, 0), TSIGError::BAD_KEY());
281  } else {
282  impl_ = new TSIGContextImpl(*result.key);
283  }
284 }
285 
287  delete impl_;
288 }
289 
290 size_t
292  //
293  // The space required for an TSIG record is:
294  //
295  // n1 bytes for the (key) name
296  // 2 bytes for the type
297  // 2 bytes for the class
298  // 4 bytes for the ttl
299  // 2 bytes for the rdlength
300  // n2 bytes for the algorithm name
301  // 6 bytes for the time signed
302  // 2 bytes for the fudge
303  // 2 bytes for the MAC size
304  // x bytes for the MAC
305  // 2 bytes for the original id
306  // 2 bytes for the error
307  // 2 bytes for the other data length
308  // y bytes for the other data (at most)
309  // ---------------------------------
310  // 26 + n1 + n2 + x + y bytes
311  //
312 
313  // Normally the digest length ("x") is the length of the underlying
314  // hash output. If a key related error occurred, however, the
315  // corresponding TSIG will be "unsigned", and the digest length will be 0.
316  const size_t digest_len =
317  (impl_->error_ == TSIGError::BAD_KEY() ||
318  impl_->error_ == TSIGError::BAD_SIG()) ? 0 : impl_->digest_len_;
319 
320  // Other Len ("y") is normally 0; if BAD_TIME error occurred, the
321  // subsequent TSIG will contain 48 bits of the server current time.
322  const size_t other_len = (impl_->error_ == TSIGError::BAD_TIME()) ? 6 : 0;
323 
324  return (26 + impl_->key_.getKeyName().getLength() +
325  impl_->key_.getAlgorithmName().getLength() +
326  digest_len + other_len);
327 }
328 
331  return (impl_->state_);
332 }
333 
334 TSIGError
336  return (impl_->error_);
337 }
338 
340 TSIGContext::sign(const uint16_t qid, const void* const data,
341  const size_t data_len) {
342  if (impl_->state_ == VERIFIED_RESPONSE) {
344  "TSIG sign attempt after verifying a response");
345  }
346 
347  if (data == NULL || data_len == 0) {
348  isc_throw(InvalidParameter, "TSIG sign error: empty data is given");
349  }
350 
352  const uint64_t now = getTSIGTime();
353 
354  // For responses adjust the error code.
355  if (impl_->state_ == RECEIVED_REQUEST) {
356  error = impl_->error_;
357  }
358 
359  // For errors related to key or MAC, return an unsigned response as
360  // specified in Section 4.3 of RFC2845.
363  impl_->key_.getKeyName(),
365  now, DEFAULT_FUDGE, 0, NULL,
366  qid, error.getCode(), 0, NULL)));
367  impl_->previous_digest_.clear();
368  impl_->state_ = SENT_RESPONSE;
369  return (tsig);
370  }
371 
372  HMACPtr hmac(impl_->createHMAC());
373 
374  // If the context has previous MAC (either the Request MAC or its own
375  // previous MAC), digest it.
376  if (impl_->state_ != INIT) {
377  impl_->digestPreviousMAC(hmac);
378  }
379 
380  // Digest the message (without TSIG)
381  hmac->update(data, data_len);
382 
383  // Digest TSIG variables.
384  // First, prepare some non constant variables.
385  const uint64_t time_signed = (error == TSIGError::BAD_TIME()) ?
386  impl_->previous_timesigned_ : now;
387  // For BADTIME error, we include 6 bytes of other data.
388  // (6 bytes = size of time signed value)
389  const uint16_t otherlen = (error == TSIGError::BAD_TIME()) ? 6 : 0;
390  OutputBuffer otherdatabuf(otherlen);
391  if (error == TSIGError::BAD_TIME()) {
392  otherdatabuf.writeUint16(now >> 32);
393  otherdatabuf.writeUint32(now & 0xffffffff);
394  }
395  const void* const otherdata =
396  (otherlen == 0) ? NULL : otherdatabuf.getData();
397  // Then calculate the digest. If state_ is SENT_RESPONSE we are sending
398  // a continued message in the same TCP stream so skip digesting
399  // variables except for time related variables (RFC2845 4.4).
401  TSIGRecord::TSIG_TTL, time_signed,
402  DEFAULT_FUDGE, error.getCode(),
403  otherlen, otherdata,
404  impl_->state_ == SENT_RESPONSE);
405 
406  // Get the final digest, update internal state, then finish.
407  vector<uint8_t> digest = hmac->sign(impl_->digest_len_);
408  assert(digest.size() <= 0xffff); // cryptolink API should have ensured it.
410  impl_->key_.getKeyName(),
412  time_signed, DEFAULT_FUDGE,
413  digest.size(), &digest[0],
414  qid, error.getCode(), otherlen,
415  otherdata)));
416  // Exception free from now on.
417  impl_->previous_digest_.swap(digest);
418  impl_->state_ = (impl_->state_ == INIT) ? SENT_REQUEST : SENT_RESPONSE;
419  return (tsig);
420 }
421 
422 TSIGError
423 TSIGContext::verify(const TSIGRecord* const record, const void* const data,
424  const size_t data_len) {
425  if (impl_->state_ == SENT_RESPONSE) {
427  "TSIG verify attempt after sending a response");
428  }
429 
430  if (record == NULL) {
431  if (impl_->last_sig_dist_ >= 0 && impl_->last_sig_dist_ < 99) {
432  // It is not signed, but in the middle of TCP stream. We just
433  // update the HMAC state and consider this message OK.
434  update(data, data_len);
435  // This one is not signed, the last signed is one message further
436  // now.
437  impl_->last_sig_dist_++;
438  // No digest to return now. Just say it's OK.
439  return (impl_->postVerifyUpdate(TSIGError::NOERROR(), NULL, 0));
440  }
441  // This case happens when we sent a signed request and have received an
442  // unsigned response. According to RFC2845 Section 4.6 this case should be
443  // considered a "format error" (although the specific error code
444  // wouldn't matter much for the caller).
445  return (impl_->postVerifyUpdate(TSIGError::FORMERR(), NULL, 0));
446  }
447 
448  const any::TSIG& tsig_rdata = record->getRdata();
449 
450  // Reject some obviously invalid data
451  if (data_len < MESSAGE_HEADER_LEN + record->getLength()) {
453  "TSIG verify: data length is invalid: " << data_len);
454  }
455  if (data == NULL) {
456  isc_throw(InvalidParameter, "TSIG verify: empty data is invalid");
457  }
458 
459  // This message is signed and we won't throw any more.
460  impl_->last_sig_dist_ = 0;
461 
462  // Check key: whether we first verify it with a known key or we verify
463  // it using the consistent key in the context. If the check fails we are
464  // done with BADKEY.
465  if (impl_->state_ == INIT && impl_->error_ == TSIGError::BAD_KEY()) {
466  return (impl_->postVerifyUpdate(TSIGError::BAD_KEY(), NULL, 0));
467  }
468  if (impl_->key_.getKeyName() != record->getName() ||
469  impl_->key_.getAlgorithmName() != tsig_rdata.getAlgorithm()) {
470  return (impl_->postVerifyUpdate(TSIGError::BAD_KEY(), NULL, 0));
471  }
472 
473  // Check time: the current time must be in the range of
474  // [time signed - fudge, time signed + fudge]. Otherwise verification
475  // fails with BADTIME. (RFC2845 Section 4.6.2)
476  // Note: for simplicity we don't explicitly catch the case of too small
477  // current time causing underflow. With the fact that fudge is quite
478  // small and (for now) non configurable, it shouldn't be a real concern
479  // in practice.
480  const uint64_t now = getTSIGTime();
481  if (tsig_rdata.getTimeSigned() + DEFAULT_FUDGE < now ||
482  tsig_rdata.getTimeSigned() - DEFAULT_FUDGE > now) {
483  const void* digest = NULL;
484  size_t digest_len = 0;
485  if (impl_->state_ == INIT) {
486  digest = tsig_rdata.getMAC();
487  digest_len = tsig_rdata.getMACSize();
488  impl_->previous_timesigned_ = tsig_rdata.getTimeSigned();
489  }
490  return (impl_->postVerifyUpdate(TSIGError::BAD_TIME(), digest,
491  digest_len));
492  }
493 
494  // Handling empty MAC. While RFC2845 doesn't explicitly prohibit other
495  // cases, it can only reasonably happen in a response with BADSIG or
496  // BADKEY. We reject other cases as if it were BADSIG to avoid unexpected
497  // acceptance of a bogus signature. This behavior follows the BIND 9
498  // implementation.
499  if (tsig_rdata.getMACSize() == 0) {
500  TSIGError error = TSIGError(tsig_rdata.getError());
503  }
504  return (impl_->postVerifyUpdate(error, NULL, 0));
505  }
506 
507  HMACPtr hmac(impl_->createHMAC());
508 
509  // If the context has previous MAC (either the Request MAC or its own
510  // previous MAC), digest it.
511  if (impl_->state_ != INIT) {
512  impl_->digestPreviousMAC(hmac);
513  }
514 
515  // Signature length check based on RFC 4635 3.1
516  if (tsig_rdata.getMACSize() > hmac->getOutputLength()) {
517  // signature length too big
518  return (impl_->postVerifyUpdate(TSIGError::FORMERR(), NULL, 0));
519  }
520  if ((tsig_rdata.getMACSize() < 10) ||
521  (tsig_rdata.getMACSize() < (hmac->getOutputLength() / 2))) {
522  // signature length below minimum
523  return (impl_->postVerifyUpdate(TSIGError::FORMERR(), NULL, 0));
524  }
525  if (tsig_rdata.getMACSize() < impl_->digest_len_) {
526  // (truncated) signature length too small
527  return (impl_->postVerifyUpdate(TSIGError::BAD_TRUNC(), NULL, 0));
528  }
529 
530  //
531  // Digest DNS message (excluding the trailing TSIG RR and adjusting the
532  // QID and ARCOUNT header fields)
533  //
534  impl_->digestDNSMessage(hmac, tsig_rdata.getOriginalID(),
535  data, data_len - record->getLength());
536 
537  // Digest TSIG variables. If state_ is VERIFIED_RESPONSE, it's a
538  // continuation of the same TCP stream and skip digesting them except
539  // for time related variables (RFC2845 4.4).
540  // Note: we use the constant values for RR class and TTL specified
541  // in RFC2845, not received values (we reject other values in constructing
542  // the TSIGRecord).
543  impl_->digestTSIGVariables(hmac, TSIGRecord::getClass().getCode(),
545  tsig_rdata.getTimeSigned(),
546  tsig_rdata.getFudge(), tsig_rdata.getError(),
547  tsig_rdata.getOtherLen(),
548  tsig_rdata.getOtherData(),
549  impl_->state_ == VERIFIED_RESPONSE);
550 
551  // Verify the digest with the received signature.
552  if (hmac->verify(tsig_rdata.getMAC(), tsig_rdata.getMACSize())) {
553  return (impl_->postVerifyUpdate(TSIGError::NOERROR(),
554  tsig_rdata.getMAC(),
555  tsig_rdata.getMACSize()));
556  }
557 
558  return (impl_->postVerifyUpdate(TSIGError::BAD_SIG(), NULL, 0));
559 }
560 
561 bool
563  if (impl_->last_sig_dist_ == -1) {
564  isc_throw(TSIGContextError, "No message was verified yet");
565  }
566  return (impl_->last_sig_dist_ == 0);
567 }
568 
569 void
570 TSIGContext::update(const void* const data, size_t len) {
571  HMACPtr hmac(impl_->createHMAC());
572  // Use the previous digest and never use it again
573  impl_->digestPreviousMAC(hmac);
574  impl_->previous_digest_.clear();
575  // Push the message there
576  hmac->update(data, len);
577  impl_->hmac_ = hmac;
578 }
579 
580 } // namespace dns
581 } // namespace isc
This is a base class for exceptions thrown from the DNS library module.
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
size_t getLength() const
Gets the length of the Name in its wire format.
Definition: name.h:360
uint16_t getCode() const
Returns the RR class code as a 16-bit unsigned integer.
Definition: rrclass.h:238
An exception that is thrown for logic errors identified in TSIG sign/verify operations.
Definition: tsig.h:31
State
Internal state of context.
Definition: tsig.h:181
@ RECEIVED_REQUEST
Server received a signed request.
Definition: tsig.h:184
@ SENT_REQUEST
Client sent a signed request, waiting response.
Definition: tsig.h:183
@ SENT_RESPONSE
Server sent a signed response.
Definition: tsig.h:185
@ VERIFIED_RESPONSE
Client successfully verified a response.
Definition: tsig.h:186
@ INIT
Initial state.
Definition: tsig.h:182
virtual ConstTSIGRecordPtr sign(const uint16_t qid, const void *const data, const size_t data_len)
Sign a DNS message.
Definition: tsig.cc:340
static const uint16_t DEFAULT_FUDGE
The recommended fudge value (in seconds) by RFC2845.
Definition: tsig.h:414
virtual TSIGError getError() const
Return the TSIG error as a result of the latest verification.
Definition: tsig.cc:335
virtual size_t getTSIGLength() const
Return the expected length of TSIG RR after sign()
Definition: tsig.cc:291
virtual ~TSIGContext()
The destructor.
Definition: tsig.cc:286
void update(const void *const data, size_t len)
Update internal HMAC state by more data.
Definition: tsig.cc:570
TSIGContext(const TSIGKey &key)
Constructor from a TSIG key.
Definition: tsig.cc:267
virtual TSIGError verify(const TSIGRecord *const record, const void *const data, const size_t data_len)
Verify a DNS message.
Definition: tsig.cc:423
virtual State getState() const
Return the current state of the context.
Definition: tsig.cc:330
virtual bool lastHadSignature() const
Check whether the last verified message was signed.
Definition: tsig.cc:562
TSIG errors.
Definition: tsigerror.h:22
static const TSIGError & BAD_SIG()
A constant TSIG error object for the BADSIG code (see TSIGError::BAD_SIG_CODE).
Definition: tsigerror.h:315
static const TSIGError & BAD_KEY()
A constant TSIG error object for the BADKEY code (see TSIGError::BAD_KEY_CODE).
Definition: tsigerror.h:321
static const TSIGError & BAD_TIME()
A constant TSIG error object for the BADTIME code (see TSIGError::BAD_TIME_CODE).
Definition: tsigerror.h:327
static const TSIGError & NOERROR()
A constant TSIG error object derived from Rcode::NOERROR()
Definition: tsigerror.h:219
static const TSIGError & BAD_TRUNC()
A constant TSIG error object for the BADTRUNC code (see TSIGError::BAD_TRUNC_CODE).
Definition: tsigerror.h:351
static const TSIGError & FORMERR()
A constant TSIG error object derived from Rcode::FORMERR()
Definition: tsigerror.h:225
A simple repository of a set of TSIGKey objects.
Definition: tsigkey.h:246
FindResult find(const Name &key_name) const
Find a TSIGKey for the given name in the TSIGKeyRing.
Definition: tsigkey.cc:343
@ NOTFOUND
The specified key is not found in TSIGKeyRing.
Definition: tsigkey.h:252
TSIG key.
Definition: tsigkey.h:56
const Name & getAlgorithmName() const
Return the algorithm name.
Definition: tsigkey.cc:218
const Name & getKeyName() const
Return the key name.
Definition: tsigkey.cc:213
TSIG resource record.
Definition: tsigrecord.h:54
static const RRClass & getClass()
Return the RR class of TSIG.
Definition: tsigrecord.cc:81
static const uint32_t TSIG_TTL
The TTL value to be used in TSIG RRs.
Definition: tsigrecord.h:267
const rdata::any::TSIG & getRdata() const
Return the RDATA of the TSIG RR.
Definition: tsigrecord.h:176
size_t getLength() const
Return the length of the TSIG record.
Definition: tsigrecord.h:210
const Name & getName() const
Return the owner name of the TSIG RR, which is the TSIG key name.
Definition: tsigrecord.h:171
rdata::TSIG class represents the TSIG RDATA as defined in RFC2845.
Definition: rdataclass.h:63
uint16_t getOriginalID() const
Return the value of the Original ID field.
uint16_t getError() const
Return the value of the Error field.
const Name & getAlgorithm() const
Return the algorithm name.
uint16_t getOtherLen() const
Return the value of the Other Len field.
const void * getOtherData() const
Return the value of the Other Data field.
uint16_t getFudge() const
Return the value of the Fudge field.
const void * getMAC() const
Return the value of the MAC field.
uint16_t getMACSize() const
Return the value of the MAC Size field.
uint64_t getTimeSigned() const
Return the value of the Time Signed field.
The InputBuffer class is a buffer abstraction for manipulating read-only data.
Definition: buffer.h:81
The OutputBuffer class is a buffer abstraction for manipulating mutable data.
Definition: buffer.h:294
const void * getData() const
Return a pointer to the head of the data stored in the buffer.
Definition: buffer.h:401
void writeUint16(uint16_t data)
Write an unsigned 16-bit integer in host byte order into the buffer in network byte order.
Definition: buffer.h:490
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:550
void writeUint32(uint32_t data)
Write an unsigned 32-bit integer in host byte order into the buffer in network byte order.
Definition: buffer.h:520
size_t getLength() const
Return the length of data written in the buffer.
Definition: buffer.h:403
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
@ error
Definition: db_log.h:116
boost::shared_ptr< const TSIGRecord > ConstTSIGRecordPtr
A pointer-like type pointing to an immutable TSIGRecord object.
Definition: tsigrecord.h:280
int64_t gettimeWrapper()
Return the current time in seconds.
Definition: edns.h:19
uint16_t readUint16(const void *buffer, size_t length)
Read Unsigned 16-Bit Integer from Buffer.
Definition: io_utilities.h:28
Defines the logger used by the top-level component of kea-lfc.
void digestDNSMessage(HMACPtr hmac, uint16_t qid, const void *data, size_t data_len) const
Definition: tsig.cc:243
void digestPreviousMAC(HMACPtr hmac)
Definition: tsig.cc:169
TSIGContextImpl(const TSIGKey &key, TSIGError error=TSIGError::NOERROR())
Definition: tsig.cc:55
TSIGError postVerifyUpdate(TSIGError error, const void *digest, uint16_t digest_len)
Definition: tsig.cc:100
void digestTSIGVariables(HMACPtr hmac, uint16_t rrclass, uint32_t rrttl, uint64_t time_signed, uint16_t fudge, uint16_t error, uint16_t otherlen, const void *otherdata, bool time_variables_only) const
Definition: tsig.cc:191
vector< uint8_t > previous_digest_
Definition: tsig.cc:157
A helper structure to represent the search result of TSIGKeyRing::find().
Definition: tsigkey.h:270
const TSIGKey *const key
Definition: tsigkey.h:275