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