1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14 * PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /*
18 * $Id: tsig.c,v 1.15 2024/04/23 13:34:50 jsg Exp $
19 */
20 /*! \file */
21
22 #include <stdlib.h>
23 #include <string.h> /* Required for HP/UX (and others?) */
24 #include <time.h>
25
26 #include <isc/util.h>
27 #include <isc/buffer.h>
28 #include <isc/refcount.h>
29
30 #include <dns/keyvalues.h>
31 #include <dns/log.h>
32 #include <dns/message.h>
33 #include <dns/rdata.h>
34 #include <dns/rdatalist.h>
35 #include <dns/rdataset.h>
36 #include <dns/result.h>
37 #include <dns/tsig.h>
38
39 #include <dst/result.h>
40
41 #define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR)
42 #define algname_is_allocated(algname) \
43 ((algname) != dns_tsig_hmacsha1_name && \
44 (algname) != dns_tsig_hmacsha224_name && \
45 (algname) != dns_tsig_hmacsha256_name && \
46 (algname) != dns_tsig_hmacsha384_name && \
47 (algname) != dns_tsig_hmacsha512_name)
48
49 #define BADTIMELEN 6
50
51 static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
52 static unsigned char hmacsha1_offsets[] = { 0, 10 };
53 static dns_name_t hmacsha1 =
54 DNS_NAME_INITABSOLUTE(hmacsha1_ndata, hmacsha1_offsets);
55 dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
56
57 static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
58 static unsigned char hmacsha224_offsets[] = { 0, 12 };
59 static dns_name_t hmacsha224 =
60 DNS_NAME_INITABSOLUTE(hmacsha224_ndata, hmacsha224_offsets);
61 dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
62
63 static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
64 static unsigned char hmacsha256_offsets[] = { 0, 12 };
65 static dns_name_t hmacsha256 =
66 DNS_NAME_INITABSOLUTE(hmacsha256_ndata, hmacsha256_offsets);
67 dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
68
69 static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
70 static unsigned char hmacsha384_offsets[] = { 0, 12 };
71 static dns_name_t hmacsha384 =
72 DNS_NAME_INITABSOLUTE(hmacsha384_ndata, hmacsha384_offsets);
73 dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
74
75 static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
76 static unsigned char hmacsha512_offsets[] = { 0, 12 };
77 static dns_name_t hmacsha512 =
78 DNS_NAME_INITABSOLUTE(hmacsha512_ndata, hmacsha512_offsets);
79 dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
80
81 static isc_result_t
82 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg);
83
84 static void
85 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...)
86 __attribute__((__format__(__printf__, 3, 4)));
87
88 static void
89 tsigkey_free(dns_tsigkey_t *key);
90
91 static void
tsig_log(dns_tsigkey_t * key,int level,const char * fmt,...)92 tsig_log(dns_tsigkey_t *key, int level, const char *fmt, ...) {
93 va_list ap;
94 char message[4096];
95 char namestr[DNS_NAME_FORMATSIZE];
96 char creatorstr[DNS_NAME_FORMATSIZE];
97
98 if (!isc_log_wouldlog(dns_lctx, level))
99 return;
100 if (key != NULL) {
101 dns_name_format(&key->name, namestr, sizeof(namestr));
102 } else {
103 strlcpy(namestr, "<null>", sizeof(namestr));
104 }
105
106 if (key != NULL && key->generated && key->creator) {
107 dns_name_format(key->creator, creatorstr, sizeof(creatorstr));
108 } else {
109 strlcpy(creatorstr, "<null>", sizeof(creatorstr));
110 }
111
112 va_start(ap, fmt);
113 vsnprintf(message, sizeof(message), fmt, ap);
114 va_end(ap);
115 if (key != NULL && key->generated) {
116 isc_log_write(dns_lctx,
117 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
118 level, "tsig key '%s' (%s): %s",
119 namestr, creatorstr, message);
120 } else {
121 isc_log_write(dns_lctx,
122 DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG,
123 level, "tsig key '%s': %s", namestr, message);
124 }
125 }
126
127 isc_result_t
dns_tsigkey_createfromkey(dns_name_t * name,dns_name_t * algorithm,dst_key_t * dstkey,int generated,dns_name_t * creator,time_t inception,time_t expire,dns_tsigkey_t ** key)128 dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
129 dst_key_t *dstkey, int generated,
130 dns_name_t *creator, time_t inception,
131 time_t expire,
132 dns_tsigkey_t **key)
133 {
134 dns_tsigkey_t *tkey;
135 isc_result_t ret;
136 unsigned int refs = 0;
137
138 REQUIRE(key == NULL || *key == NULL);
139 REQUIRE(name != NULL);
140 REQUIRE(algorithm != NULL);
141 REQUIRE(key != NULL);
142
143 tkey = (dns_tsigkey_t *) malloc(sizeof(dns_tsigkey_t));
144 if (tkey == NULL)
145 return (ISC_R_NOMEMORY);
146
147 dns_name_init(&tkey->name, NULL);
148 ret = dns_name_dup(name, &tkey->name);
149 if (ret != ISC_R_SUCCESS)
150 goto cleanup_key;
151 (void)dns_name_downcase(&tkey->name, &tkey->name, NULL);
152
153 if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
154 tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
155 if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
156 ret = DNS_R_BADALG;
157 goto cleanup_name;
158 }
159 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
160 tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
161 if (dstkey != NULL &&
162 dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
163 ret = DNS_R_BADALG;
164 goto cleanup_name;
165 }
166 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
167 tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
168 if (dstkey != NULL &&
169 dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
170 ret = DNS_R_BADALG;
171 goto cleanup_name;
172 }
173 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
174 tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
175 if (dstkey != NULL &&
176 dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
177 ret = DNS_R_BADALG;
178 goto cleanup_name;
179 }
180 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
181 tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
182 if (dstkey != NULL &&
183 dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
184 ret = DNS_R_BADALG;
185 goto cleanup_name;
186 }
187 } else {
188 if (dstkey != NULL) {
189 ret = DNS_R_BADALG;
190 goto cleanup_name;
191 }
192 tkey->algorithm = malloc(sizeof(dns_name_t));
193 if (tkey->algorithm == NULL) {
194 ret = ISC_R_NOMEMORY;
195 goto cleanup_name;
196 }
197 dns_name_init(tkey->algorithm, NULL);
198 ret = dns_name_dup(algorithm, tkey->algorithm);
199 if (ret != ISC_R_SUCCESS)
200 goto cleanup_algorithm;
201 (void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
202 NULL);
203 }
204
205 if (creator != NULL) {
206 tkey->creator = malloc(sizeof(dns_name_t));
207 if (tkey->creator == NULL) {
208 ret = ISC_R_NOMEMORY;
209 goto cleanup_algorithm;
210 }
211 dns_name_init(tkey->creator, NULL);
212 ret = dns_name_dup(creator, tkey->creator);
213 if (ret != ISC_R_SUCCESS) {
214 free(tkey->creator);
215 goto cleanup_algorithm;
216 }
217 } else
218 tkey->creator = NULL;
219
220 tkey->key = NULL;
221 if (dstkey != NULL)
222 dst_key_attach(dstkey, &tkey->key);
223
224 if (key != NULL)
225 refs = 1;
226
227 ret = isc_refcount_init(&tkey->refs, refs);
228 if (ret != ISC_R_SUCCESS)
229 goto cleanup_creator;
230
231 tkey->generated = generated;
232 tkey->inception = inception;
233 tkey->expire = expire;
234 ISC_LINK_INIT(tkey, link);
235
236 /*
237 * Ignore this if it's a GSS key, since the key size is meaningless.
238 */
239 if (dstkey != NULL && dst_key_size(dstkey) < 64) {
240 char namestr[DNS_NAME_FORMATSIZE];
241 dns_name_format(name, namestr, sizeof(namestr));
242 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
243 DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
244 "the key '%s' is too short to be secure",
245 namestr);
246 }
247
248 if (key != NULL)
249 *key = tkey;
250
251 return (ISC_R_SUCCESS);
252
253 cleanup_creator:
254 if (tkey->key != NULL)
255 dst_key_free(&tkey->key);
256 if (tkey->creator != NULL) {
257 dns_name_free(tkey->creator);
258 free(tkey->creator);
259 }
260 cleanup_algorithm:
261 if (algname_is_allocated(tkey->algorithm)) {
262 if (dns_name_dynamic(tkey->algorithm))
263 dns_name_free(tkey->algorithm);
264 free(tkey->algorithm);
265 }
266 cleanup_name:
267 dns_name_free(&tkey->name);
268 cleanup_key:
269 free(tkey);
270
271 return (ret);
272 }
273
274 isc_result_t
dns_tsigkey_create(dns_name_t * name,dns_name_t * algorithm,unsigned char * secret,int length,int generated,dns_name_t * creator,time_t inception,time_t expire,dns_tsigkey_t ** key)275 dns_tsigkey_create(dns_name_t *name, dns_name_t *algorithm,
276 unsigned char *secret, int length, int generated,
277 dns_name_t *creator, time_t inception,
278 time_t expire,
279 dns_tsigkey_t **key)
280 {
281 dst_key_t *dstkey = NULL;
282 isc_result_t result;
283
284 REQUIRE(length >= 0);
285 if (length > 0)
286 REQUIRE(secret != NULL);
287
288 if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
289 if (secret != NULL) {
290 isc_buffer_t b;
291
292 isc_buffer_init(&b, secret, length);
293 isc_buffer_add(&b, length);
294 result = dst_key_frombuffer(DST_ALG_HMACSHA1,
295 DNS_KEYOWNER_ENTITY,
296 DNS_KEYPROTO_DNSSEC,
297 &b, &dstkey);
298 if (result != ISC_R_SUCCESS)
299 return (result);
300 }
301 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
302 if (secret != NULL) {
303 isc_buffer_t b;
304
305 isc_buffer_init(&b, secret, length);
306 isc_buffer_add(&b, length);
307 result = dst_key_frombuffer(DST_ALG_HMACSHA224,
308 DNS_KEYOWNER_ENTITY,
309 DNS_KEYPROTO_DNSSEC,
310 &b, &dstkey);
311 if (result != ISC_R_SUCCESS)
312 return (result);
313 }
314 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
315 if (secret != NULL) {
316 isc_buffer_t b;
317
318 isc_buffer_init(&b, secret, length);
319 isc_buffer_add(&b, length);
320 result = dst_key_frombuffer(DST_ALG_HMACSHA256,
321 DNS_KEYOWNER_ENTITY,
322 DNS_KEYPROTO_DNSSEC,
323 &b, &dstkey);
324 if (result != ISC_R_SUCCESS)
325 return (result);
326 }
327 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
328 if (secret != NULL) {
329 isc_buffer_t b;
330
331 isc_buffer_init(&b, secret, length);
332 isc_buffer_add(&b, length);
333 result = dst_key_frombuffer(DST_ALG_HMACSHA384,
334 DNS_KEYOWNER_ENTITY,
335 DNS_KEYPROTO_DNSSEC,
336 &b, &dstkey);
337 if (result != ISC_R_SUCCESS)
338 return (result);
339 }
340 } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
341 if (secret != NULL) {
342 isc_buffer_t b;
343
344 isc_buffer_init(&b, secret, length);
345 isc_buffer_add(&b, length);
346 result = dst_key_frombuffer(DST_ALG_HMACSHA512,
347 DNS_KEYOWNER_ENTITY,
348 DNS_KEYPROTO_DNSSEC,
349 &b, &dstkey);
350 if (result != ISC_R_SUCCESS)
351 return (result);
352 }
353 } else if (length > 0)
354 return (DNS_R_BADALG);
355
356 result = dns_tsigkey_createfromkey(name, algorithm, dstkey,
357 generated, creator,
358 inception, expire, key);
359 if (dstkey != NULL)
360 dst_key_free(&dstkey);
361 return (result);
362 }
363
364 void
dns_tsigkey_attach(dns_tsigkey_t * source,dns_tsigkey_t ** targetp)365 dns_tsigkey_attach(dns_tsigkey_t *source, dns_tsigkey_t **targetp) {
366 REQUIRE(targetp != NULL && *targetp == NULL);
367
368 isc_refcount_increment(&source->refs, NULL);
369 *targetp = source;
370 }
371
372 static void
tsigkey_free(dns_tsigkey_t * key)373 tsigkey_free(dns_tsigkey_t *key) {
374 dns_name_free(&key->name);
375 if (algname_is_allocated(key->algorithm)) {
376 dns_name_free(key->algorithm);
377 free(key->algorithm);
378 }
379 if (key->key != NULL)
380 dst_key_free(&key->key);
381 if (key->creator != NULL) {
382 dns_name_free(key->creator);
383 free(key->creator);
384 }
385 isc_refcount_destroy(&key->refs);
386 free(key);
387 }
388
389 void
dns_tsigkey_detach(dns_tsigkey_t ** keyp)390 dns_tsigkey_detach(dns_tsigkey_t **keyp) {
391 dns_tsigkey_t *key;
392 unsigned int refs;
393
394 REQUIRE(keyp != NULL);
395
396 key = *keyp;
397 isc_refcount_decrement(&key->refs, &refs);
398
399 if (refs == 0)
400 tsigkey_free(key);
401
402 *keyp = NULL;
403 }
404
405 isc_result_t
dns_tsig_sign(dns_message_t * msg)406 dns_tsig_sign(dns_message_t *msg) {
407 dns_tsigkey_t *key;
408 dns_rdata_any_tsig_t tsig, querytsig;
409 unsigned char data[128];
410 isc_buffer_t databuf, sigbuf;
411 isc_buffer_t *dynbuf;
412 dns_name_t *owner;
413 dns_rdata_t *rdata = NULL;
414 dns_rdatalist_t *datalist;
415 dns_rdataset_t *dataset;
416 isc_region_t r;
417 time_t now;
418 dst_context_t *ctx = NULL;
419 isc_result_t ret;
420 unsigned char badtimedata[BADTIMELEN];
421 unsigned int sigsize = 0;
422 int response;
423
424 REQUIRE(msg != NULL);
425 key = dns_message_gettsigkey(msg);
426
427 /*
428 * If this is a response, there should be a query tsig.
429 */
430 response = is_response(msg);
431 if (response && msg->querytsig == NULL)
432 return (DNS_R_EXPECTEDTSIG);
433
434 dynbuf = NULL;
435
436 tsig.common.rdclass = dns_rdataclass_any;
437 tsig.common.rdtype = dns_rdatatype_tsig;
438 ISC_LINK_INIT(&tsig.common, link);
439 dns_name_init(&tsig.algorithm, NULL);
440 dns_name_clone(key->algorithm, &tsig.algorithm);
441
442 time(&now);
443 tsig.timesigned = now + msg->timeadjust;
444 tsig.fudge = DNS_TSIG_FUDGE;
445
446 tsig.originalid = msg->id;
447
448 isc_buffer_init(&databuf, data, sizeof(data));
449
450 if (response)
451 tsig.error = msg->querytsigstatus;
452 else
453 tsig.error = dns_rcode_noerror;
454
455 if (tsig.error != dns_tsigerror_badtime) {
456 tsig.otherlen = 0;
457 tsig.other = NULL;
458 } else {
459 isc_buffer_t otherbuf;
460
461 tsig.otherlen = BADTIMELEN;
462 tsig.other = badtimedata;
463 isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen);
464 isc_buffer_putuint48(&otherbuf, tsig.timesigned);
465 }
466
467 if ((key->key != NULL) &&
468 (tsig.error != dns_tsigerror_badsig) &&
469 (tsig.error != dns_tsigerror_badkey))
470 {
471 unsigned char header[DNS_MESSAGE_HEADERLEN];
472 isc_buffer_t headerbuf;
473 uint16_t digestbits;
474
475 /*
476 * If it is a response, we assume that the request MAC
477 * has validated at this point. This is why we include a
478 * MAC length > 0 in the reply.
479 */
480 ret = dst_context_create3(key->key,
481 DNS_LOGCATEGORY_DNSSEC,
482 1, &ctx);
483 if (ret != ISC_R_SUCCESS)
484 return (ret);
485
486 /*
487 * If this is a response, digest the request's MAC.
488 */
489 if (response) {
490 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
491
492 INSIST(msg->verified_sig);
493
494 ret = dns_rdataset_first(msg->querytsig);
495 if (ret != ISC_R_SUCCESS)
496 goto cleanup_context;
497 dns_rdataset_current(msg->querytsig, &querytsigrdata);
498 ret = dns_rdata_tostruct_tsig(&querytsigrdata,
499 &querytsig);
500 if (ret != ISC_R_SUCCESS)
501 goto cleanup_context;
502 isc_buffer_putuint16(&databuf, querytsig.siglen);
503 if (isc_buffer_availablelength(&databuf) <
504 querytsig.siglen) {
505 ret = ISC_R_NOSPACE;
506 goto cleanup_context;
507 }
508 isc_buffer_putmem(&databuf, querytsig.signature,
509 querytsig.siglen);
510 isc_buffer_usedregion(&databuf, &r);
511 ret = dst_context_adddata(ctx, &r);
512 if (ret != ISC_R_SUCCESS)
513 goto cleanup_context;
514 }
515
516 /*
517 * Digest the header.
518 */
519 isc_buffer_init(&headerbuf, header, sizeof(header));
520 dns_message_renderheader(msg, &headerbuf);
521 isc_buffer_usedregion(&headerbuf, &r);
522 ret = dst_context_adddata(ctx, &r);
523 if (ret != ISC_R_SUCCESS)
524 goto cleanup_context;
525
526 /*
527 * Digest the remainder of the message.
528 */
529 isc_buffer_usedregion(msg->buffer, &r);
530 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
531 ret = dst_context_adddata(ctx, &r);
532 if (ret != ISC_R_SUCCESS)
533 goto cleanup_context;
534
535 if (msg->tcp_continuation == 0) {
536 /*
537 * Digest the name, class, ttl, alg.
538 */
539 dns_name_toregion(&key->name, &r);
540 ret = dst_context_adddata(ctx, &r);
541 if (ret != ISC_R_SUCCESS)
542 goto cleanup_context;
543
544 isc_buffer_clear(&databuf);
545 isc_buffer_putuint16(&databuf, dns_rdataclass_any);
546 isc_buffer_putuint32(&databuf, 0); /* ttl */
547 isc_buffer_usedregion(&databuf, &r);
548 ret = dst_context_adddata(ctx, &r);
549 if (ret != ISC_R_SUCCESS)
550 goto cleanup_context;
551
552 dns_name_toregion(&tsig.algorithm, &r);
553 ret = dst_context_adddata(ctx, &r);
554 if (ret != ISC_R_SUCCESS)
555 goto cleanup_context;
556
557 }
558 /* Digest the timesigned and fudge */
559 isc_buffer_clear(&databuf);
560 if (tsig.error == dns_tsigerror_badtime) {
561 INSIST(response);
562 tsig.timesigned = querytsig.timesigned;
563 }
564 isc_buffer_putuint48(&databuf, tsig.timesigned);
565 isc_buffer_putuint16(&databuf, tsig.fudge);
566 isc_buffer_usedregion(&databuf, &r);
567 ret = dst_context_adddata(ctx, &r);
568 if (ret != ISC_R_SUCCESS)
569 goto cleanup_context;
570
571 if (msg->tcp_continuation == 0) {
572 /*
573 * Digest the error and other data length.
574 */
575 isc_buffer_clear(&databuf);
576 isc_buffer_putuint16(&databuf, tsig.error);
577 isc_buffer_putuint16(&databuf, tsig.otherlen);
578
579 isc_buffer_usedregion(&databuf, &r);
580 ret = dst_context_adddata(ctx, &r);
581 if (ret != ISC_R_SUCCESS)
582 goto cleanup_context;
583
584 /*
585 * Digest other data.
586 */
587 if (tsig.otherlen > 0) {
588 r.length = tsig.otherlen;
589 r.base = tsig.other;
590 ret = dst_context_adddata(ctx, &r);
591 if (ret != ISC_R_SUCCESS)
592 goto cleanup_context;
593 }
594 }
595
596 ret = dst_key_sigsize(key->key, &sigsize);
597 if (ret != ISC_R_SUCCESS)
598 goto cleanup_context;
599 tsig.signature = (unsigned char *) malloc(sigsize);
600 if (tsig.signature == NULL) {
601 ret = ISC_R_NOMEMORY;
602 goto cleanup_context;
603 }
604
605 isc_buffer_init(&sigbuf, tsig.signature, sigsize);
606 ret = dst_context_sign(ctx, &sigbuf);
607 if (ret != ISC_R_SUCCESS)
608 goto cleanup_signature;
609 dst_context_destroy(&ctx);
610 digestbits = dst_key_getbits(key->key);
611 if (digestbits != 0) {
612 /*
613 * XXXRAY: Is this correct? What is the
614 * expected behavior when digestbits is not an
615 * integral multiple of 8? It looks like bytes
616 * should either be (digestbits/8) or
617 * (digestbits+7)/8.
618 *
619 * In any case, for current algorithms,
620 * digestbits are an integral multiple of 8, so
621 * it has the same effect as (digestbits/8).
622 */
623 unsigned int bytes = (digestbits + 1) / 8;
624 if (response && bytes < querytsig.siglen)
625 bytes = querytsig.siglen;
626 if (bytes > isc_buffer_usedlength(&sigbuf))
627 bytes = isc_buffer_usedlength(&sigbuf);
628 tsig.siglen = bytes;
629 } else
630 tsig.siglen = isc_buffer_usedlength(&sigbuf);
631 } else {
632 tsig.siglen = 0;
633 tsig.signature = NULL;
634 }
635
636 ret = dns_message_gettemprdata(msg, &rdata);
637 if (ret != ISC_R_SUCCESS)
638 goto cleanup_signature;
639 ret = isc_buffer_allocate(&dynbuf, 512);
640 if (ret != ISC_R_SUCCESS)
641 goto cleanup_rdata;
642 ret = dns_rdata_fromstruct_tsig(rdata, dns_rdataclass_any,
643 dns_rdatatype_tsig, &tsig, dynbuf);
644 if (ret != ISC_R_SUCCESS)
645 goto cleanup_dynbuf;
646
647 dns_message_takebuffer(msg, &dynbuf);
648
649 if (tsig.signature != NULL) {
650 free(tsig.signature);
651 tsig.signature = NULL;
652 }
653
654 owner = NULL;
655 ret = dns_message_gettempname(msg, &owner);
656 if (ret != ISC_R_SUCCESS)
657 goto cleanup_rdata;
658 dns_name_init(owner, NULL);
659 ret = dns_name_dup(&key->name, owner);
660 if (ret != ISC_R_SUCCESS)
661 goto cleanup_owner;
662
663 datalist = NULL;
664 ret = dns_message_gettemprdatalist(msg, &datalist);
665 if (ret != ISC_R_SUCCESS)
666 goto cleanup_owner;
667 dataset = NULL;
668 ret = dns_message_gettemprdataset(msg, &dataset);
669 if (ret != ISC_R_SUCCESS)
670 goto cleanup_rdatalist;
671 datalist->rdclass = dns_rdataclass_any;
672 datalist->type = dns_rdatatype_tsig;
673 ISC_LIST_APPEND(datalist->rdata, rdata, link);
674 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset)
675 == ISC_R_SUCCESS);
676 msg->tsig = dataset;
677 msg->tsigname = owner;
678
679 /* Windows does not like the tsig name being compressed. */
680 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
681
682 return (ISC_R_SUCCESS);
683
684 cleanup_rdatalist:
685 dns_message_puttemprdatalist(msg, &datalist);
686 cleanup_owner:
687 dns_message_puttempname(msg, &owner);
688 goto cleanup_rdata;
689 cleanup_dynbuf:
690 isc_buffer_free(&dynbuf);
691 cleanup_rdata:
692 dns_message_puttemprdata(msg, &rdata);
693 cleanup_signature:
694 if (tsig.signature != NULL)
695 free(tsig.signature);
696 cleanup_context:
697 if (ctx != NULL)
698 dst_context_destroy(&ctx);
699 return (ret);
700 }
701
702 isc_result_t
dns_tsig_verify(isc_buffer_t * source,dns_message_t * msg)703 dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg)
704 {
705 dns_rdata_any_tsig_t tsig, querytsig;
706 isc_region_t r, source_r, header_r, sig_r;
707 isc_buffer_t databuf;
708 unsigned char data[32];
709 dns_name_t *keyname;
710 dns_rdata_t rdata = DNS_RDATA_INIT;
711 time_t now;
712 isc_result_t ret;
713 dns_tsigkey_t *tsigkey;
714 dst_key_t *key = NULL;
715 unsigned char header[DNS_MESSAGE_HEADERLEN];
716 dst_context_t *ctx = NULL;
717 uint16_t addcount, id;
718 unsigned int siglen;
719 unsigned int alg;
720 int response;
721
722 REQUIRE(source != NULL);
723 tsigkey = dns_message_gettsigkey(msg);
724 response = is_response(msg);
725
726 msg->verify_attempted = 1;
727 msg->verified_sig = 0;
728 msg->tsigstatus = dns_tsigerror_badsig;
729
730 if (msg->tcp_continuation) {
731 if (tsigkey == NULL || msg->querytsig == NULL)
732 return (DNS_R_UNEXPECTEDTSIG);
733 return (tsig_verify_tcp(source, msg));
734 }
735
736 /*
737 * There should be a TSIG record...
738 */
739 if (msg->tsig == NULL)
740 return (DNS_R_EXPECTEDTSIG);
741
742 /*
743 * If this is a response and there's no key or query TSIG, there
744 * shouldn't be one on the response.
745 */
746 if (response && (tsigkey == NULL || msg->querytsig == NULL))
747 return (DNS_R_UNEXPECTEDTSIG);
748
749 /*
750 * If we're here, we know the message is well formed and contains a
751 * TSIG record.
752 */
753
754 keyname = msg->tsigname;
755 ret = dns_rdataset_first(msg->tsig);
756 if (ret != ISC_R_SUCCESS)
757 return (ret);
758 dns_rdataset_current(msg->tsig, &rdata);
759 ret = dns_rdata_tostruct_tsig(&rdata, &tsig);
760 if (ret != ISC_R_SUCCESS)
761 return (ret);
762 dns_rdata_reset(&rdata);
763 if (response) {
764 ret = dns_rdataset_first(msg->querytsig);
765 if (ret != ISC_R_SUCCESS)
766 return (ret);
767 dns_rdataset_current(msg->querytsig, &rdata);
768 ret = dns_rdata_tostruct_tsig(&rdata, &querytsig);
769 if (ret != ISC_R_SUCCESS)
770 return (ret);
771 }
772 /*
773 * Do the key name and algorithm match that of the query?
774 */
775 if (response &&
776 (!dns_name_equal(keyname, &tsigkey->name) ||
777 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))) {
778 msg->tsigstatus = dns_tsigerror_badkey;
779 tsig_log(msg->tsigkey, 2,
780 "key name and algorithm do not match");
781 return (DNS_R_TSIGVERIFYFAILURE);
782 }
783
784 /*
785 * Get the current time.
786 */
787 time(&now);
788
789 /*
790 * Find dns_tsigkey_t based on keyname.
791 */
792 if (tsigkey == NULL) {
793 ret = ISC_R_NOTFOUND;
794 if (ret != ISC_R_SUCCESS) {
795 msg->tsigstatus = dns_tsigerror_badkey;
796 ret = dns_tsigkey_create(keyname, &tsig.algorithm,
797 NULL, 0, 0, NULL,
798 now, now,
799 &msg->tsigkey);
800 if (ret != ISC_R_SUCCESS)
801 return (ret);
802 tsig_log(msg->tsigkey, 2, "unknown key");
803 return (DNS_R_TSIGVERIFYFAILURE);
804 }
805 msg->tsigkey = tsigkey;
806 }
807
808 key = tsigkey->key;
809
810 /*
811 * Check digest length.
812 */
813 alg = dst_key_alg(key);
814 ret = dst_key_sigsize(key, &siglen);
815 if (ret != ISC_R_SUCCESS)
816 return (ret);
817 if (
818 alg == DST_ALG_HMACSHA1 ||
819 alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
820 alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
821 {
822 if (tsig.siglen > siglen) {
823 tsig_log(msg->tsigkey, 2, "signature length too big");
824 return (DNS_R_FORMERR);
825 }
826 if (tsig.siglen > 0 &&
827 (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2)))
828 {
829 tsig_log(msg->tsigkey, 2,
830 "signature length below minimum");
831 return (DNS_R_FORMERR);
832 }
833 }
834
835 if (tsig.siglen > 0) {
836 uint16_t addcount_n;
837
838 sig_r.base = tsig.signature;
839 sig_r.length = tsig.siglen;
840
841 ret = dst_context_create3(key,
842 DNS_LOGCATEGORY_DNSSEC,
843 0, &ctx);
844 if (ret != ISC_R_SUCCESS)
845 return (ret);
846
847 if (response) {
848 isc_buffer_init(&databuf, data, sizeof(data));
849 isc_buffer_putuint16(&databuf, querytsig.siglen);
850 isc_buffer_usedregion(&databuf, &r);
851 ret = dst_context_adddata(ctx, &r);
852 if (ret != ISC_R_SUCCESS)
853 goto cleanup_context;
854 if (querytsig.siglen > 0) {
855 r.length = querytsig.siglen;
856 r.base = querytsig.signature;
857 ret = dst_context_adddata(ctx, &r);
858 if (ret != ISC_R_SUCCESS)
859 goto cleanup_context;
860 }
861 }
862
863 /*
864 * Extract the header.
865 */
866 isc_buffer_usedregion(source, &r);
867 memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
868 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
869
870 /*
871 * Decrement the additional field counter.
872 */
873 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
874 addcount_n = ntohs(addcount);
875 addcount = htons((uint16_t)(addcount_n - 1));
876 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
877
878 /*
879 * Put in the original id.
880 */
881 id = htons(tsig.originalid);
882 memmove(&header[0], &id, 2);
883
884 /*
885 * Digest the modified header.
886 */
887 header_r.base = (unsigned char *) header;
888 header_r.length = DNS_MESSAGE_HEADERLEN;
889 ret = dst_context_adddata(ctx, &header_r);
890 if (ret != ISC_R_SUCCESS)
891 goto cleanup_context;
892
893 /*
894 * Digest all non-TSIG records.
895 */
896 isc_buffer_usedregion(source, &source_r);
897 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
898 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
899 ret = dst_context_adddata(ctx, &r);
900 if (ret != ISC_R_SUCCESS)
901 goto cleanup_context;
902
903 /*
904 * Digest the key name.
905 */
906 dns_name_toregion(&tsigkey->name, &r);
907 ret = dst_context_adddata(ctx, &r);
908 if (ret != ISC_R_SUCCESS)
909 goto cleanup_context;
910
911 isc_buffer_init(&databuf, data, sizeof(data));
912 isc_buffer_putuint16(&databuf, tsig.common.rdclass);
913 isc_buffer_putuint32(&databuf, msg->tsig->ttl);
914 isc_buffer_usedregion(&databuf, &r);
915 ret = dst_context_adddata(ctx, &r);
916 if (ret != ISC_R_SUCCESS)
917 goto cleanup_context;
918
919 /*
920 * Digest the key algorithm.
921 */
922 dns_name_toregion(tsigkey->algorithm, &r);
923 ret = dst_context_adddata(ctx, &r);
924 if (ret != ISC_R_SUCCESS)
925 goto cleanup_context;
926
927 isc_buffer_clear(&databuf);
928 isc_buffer_putuint48(&databuf, tsig.timesigned);
929 isc_buffer_putuint16(&databuf, tsig.fudge);
930 isc_buffer_putuint16(&databuf, tsig.error);
931 isc_buffer_putuint16(&databuf, tsig.otherlen);
932 isc_buffer_usedregion(&databuf, &r);
933 ret = dst_context_adddata(ctx, &r);
934 if (ret != ISC_R_SUCCESS)
935 goto cleanup_context;
936
937 if (tsig.otherlen > 0) {
938 r.base = tsig.other;
939 r.length = tsig.otherlen;
940 ret = dst_context_adddata(ctx, &r);
941 if (ret != ISC_R_SUCCESS)
942 goto cleanup_context;
943 }
944
945 ret = dst_context_verify(ctx, &sig_r);
946 if (ret == DST_R_VERIFYFAILURE) {
947 ret = DNS_R_TSIGVERIFYFAILURE;
948 tsig_log(msg->tsigkey, 2,
949 "signature failed to verify(1)");
950 goto cleanup_context;
951 } else if (ret != ISC_R_SUCCESS) {
952 goto cleanup_context;
953 }
954 msg->verified_sig = 1;
955 } else if (tsig.error != dns_tsigerror_badsig &&
956 tsig.error != dns_tsigerror_badkey) {
957 tsig_log(msg->tsigkey, 2, "signature was empty");
958 return (DNS_R_TSIGVERIFYFAILURE);
959 }
960
961 /*
962 * Here at this point, the MAC has been verified. Even if any of
963 * the following code returns a TSIG error, the reply will be
964 * signed and WILL always include the request MAC in the digest
965 * computation.
966 */
967
968 /*
969 * Is the time ok?
970 */
971 if (now + msg->timeadjust > (time_t)(tsig.timesigned + tsig.fudge)) {
972 msg->tsigstatus = dns_tsigerror_badtime;
973 tsig_log(msg->tsigkey, 2, "signature has expired");
974 ret = DNS_R_CLOCKSKEW;
975 goto cleanup_context;
976 } else if (now + msg->timeadjust < (time_t)(tsig.timesigned -
977 tsig.fudge)) {
978 msg->tsigstatus = dns_tsigerror_badtime;
979 tsig_log(msg->tsigkey, 2, "signature is in the future");
980 ret = DNS_R_CLOCKSKEW;
981 goto cleanup_context;
982 }
983
984 if (
985 alg == DST_ALG_HMACSHA1 ||
986 alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
987 alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
988 {
989 uint16_t digestbits = dst_key_getbits(key);
990
991 /*
992 * XXXRAY: Is this correct? What is the expected
993 * behavior when digestbits is not an integral multiple
994 * of 8? It looks like bytes should either be
995 * (digestbits/8) or (digestbits+7)/8.
996 *
997 * In any case, for current algorithms, digestbits are
998 * an integral multiple of 8, so it has the same effect
999 * as (digestbits/8).
1000 */
1001 if (tsig.siglen > 0 && digestbits != 0 &&
1002 tsig.siglen < ((digestbits + 1) / 8))
1003 {
1004 msg->tsigstatus = dns_tsigerror_badtrunc;
1005 tsig_log(msg->tsigkey, 2,
1006 "truncated signature length too small");
1007 ret = DNS_R_TSIGVERIFYFAILURE;
1008 goto cleanup_context;
1009 }
1010 if (tsig.siglen > 0 && digestbits == 0 &&
1011 tsig.siglen < siglen)
1012 {
1013 msg->tsigstatus = dns_tsigerror_badtrunc;
1014 tsig_log(msg->tsigkey, 2, "signature length too small");
1015 ret = DNS_R_TSIGVERIFYFAILURE;
1016 goto cleanup_context;
1017 }
1018 }
1019
1020 if (tsig.error != dns_rcode_noerror) {
1021 msg->tsigstatus = tsig.error;
1022 if (tsig.error == dns_tsigerror_badtime)
1023 ret = DNS_R_CLOCKSKEW;
1024 else
1025 ret = DNS_R_TSIGERRORSET;
1026 goto cleanup_context;
1027 }
1028
1029 msg->tsigstatus = dns_rcode_noerror;
1030 ret = ISC_R_SUCCESS;
1031
1032 cleanup_context:
1033 if (ctx != NULL)
1034 dst_context_destroy(&ctx);
1035
1036 return (ret);
1037 }
1038
1039 static isc_result_t
tsig_verify_tcp(isc_buffer_t * source,dns_message_t * msg)1040 tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
1041 dns_rdata_any_tsig_t tsig, querytsig;
1042 isc_region_t r, source_r, header_r, sig_r;
1043 isc_buffer_t databuf;
1044 unsigned char data[32];
1045 dns_name_t *keyname;
1046 dns_rdata_t rdata = DNS_RDATA_INIT;
1047 time_t now;
1048 isc_result_t ret;
1049 dns_tsigkey_t *tsigkey;
1050 dst_key_t *key = NULL;
1051 unsigned char header[DNS_MESSAGE_HEADERLEN];
1052 uint16_t addcount, id;
1053 int has_tsig = 0;
1054 unsigned int siglen;
1055 unsigned int alg;
1056
1057 REQUIRE(source != NULL);
1058 REQUIRE(msg != NULL);
1059 REQUIRE(dns_message_gettsigkey(msg) != NULL);
1060 REQUIRE(msg->tcp_continuation == 1);
1061 REQUIRE(msg->querytsig != NULL);
1062
1063 msg->verified_sig = 0;
1064 msg->tsigstatus = dns_tsigerror_badsig;
1065
1066 if (!is_response(msg))
1067 return (DNS_R_EXPECTEDRESPONSE);
1068
1069 tsigkey = dns_message_gettsigkey(msg);
1070 key = tsigkey->key;
1071
1072 /*
1073 * Extract and parse the previous TSIG
1074 */
1075 ret = dns_rdataset_first(msg->querytsig);
1076 if (ret != ISC_R_SUCCESS)
1077 return (ret);
1078 dns_rdataset_current(msg->querytsig, &rdata);
1079 ret = dns_rdata_tostruct_tsig(&rdata, &querytsig);
1080 if (ret != ISC_R_SUCCESS)
1081 return (ret);
1082 dns_rdata_reset(&rdata);
1083
1084 /*
1085 * If there is a TSIG in this message, do some checks.
1086 */
1087 if (msg->tsig != NULL) {
1088 has_tsig = 1;
1089
1090 keyname = msg->tsigname;
1091 ret = dns_rdataset_first(msg->tsig);
1092 if (ret != ISC_R_SUCCESS)
1093 goto cleanup_querystruct;
1094 dns_rdataset_current(msg->tsig, &rdata);
1095 ret = dns_rdata_tostruct_tsig(&rdata, &tsig);
1096 if (ret != ISC_R_SUCCESS)
1097 goto cleanup_querystruct;
1098
1099 /*
1100 * Do the key name and algorithm match that of the query?
1101 */
1102 if (!dns_name_equal(keyname, &tsigkey->name) ||
1103 !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
1104 {
1105 msg->tsigstatus = dns_tsigerror_badkey;
1106 ret = DNS_R_TSIGVERIFYFAILURE;
1107 tsig_log(msg->tsigkey, 2,
1108 "key name and algorithm do not match");
1109 goto cleanup_querystruct;
1110 }
1111
1112 /*
1113 * Check digest length.
1114 */
1115 alg = dst_key_alg(key);
1116 ret = dst_key_sigsize(key, &siglen);
1117 if (ret != ISC_R_SUCCESS)
1118 goto cleanup_querystruct;
1119 if (
1120 alg == DST_ALG_HMACSHA1 ||
1121 alg == DST_ALG_HMACSHA224 ||
1122 alg == DST_ALG_HMACSHA256 ||
1123 alg == DST_ALG_HMACSHA384 ||
1124 alg == DST_ALG_HMACSHA512)
1125 {
1126 if (tsig.siglen > siglen) {
1127 tsig_log(tsigkey, 2,
1128 "signature length too big");
1129 ret = DNS_R_FORMERR;
1130 goto cleanup_querystruct;
1131 }
1132 if (tsig.siglen > 0 &&
1133 (tsig.siglen < 10 ||
1134 tsig.siglen < ((siglen + 1) / 2)))
1135 {
1136 tsig_log(tsigkey, 2,
1137 "signature length below minimum");
1138 ret = DNS_R_FORMERR;
1139 goto cleanup_querystruct;
1140 }
1141 }
1142 }
1143
1144 if (msg->tsigctx == NULL) {
1145 ret = dst_context_create3(key,
1146 DNS_LOGCATEGORY_DNSSEC,
1147 0, &msg->tsigctx);
1148 if (ret != ISC_R_SUCCESS)
1149 goto cleanup_querystruct;
1150
1151 /*
1152 * Digest the length of the query signature
1153 */
1154 isc_buffer_init(&databuf, data, sizeof(data));
1155 isc_buffer_putuint16(&databuf, querytsig.siglen);
1156 isc_buffer_usedregion(&databuf, &r);
1157 ret = dst_context_adddata(msg->tsigctx, &r);
1158 if (ret != ISC_R_SUCCESS)
1159 goto cleanup_context;
1160
1161 /*
1162 * Digest the data of the query signature
1163 */
1164 if (querytsig.siglen > 0) {
1165 r.length = querytsig.siglen;
1166 r.base = querytsig.signature;
1167 ret = dst_context_adddata(msg->tsigctx, &r);
1168 if (ret != ISC_R_SUCCESS)
1169 goto cleanup_context;
1170 }
1171 }
1172
1173 /*
1174 * Extract the header.
1175 */
1176 isc_buffer_usedregion(source, &r);
1177 memmove(header, r.base, DNS_MESSAGE_HEADERLEN);
1178 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN);
1179
1180 /*
1181 * Decrement the additional field counter if necessary.
1182 */
1183 if (has_tsig) {
1184 uint16_t addcount_n;
1185
1186 memmove(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2);
1187 addcount_n = ntohs(addcount);
1188 addcount = htons((uint16_t)(addcount_n - 1));
1189 memmove(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2);
1190
1191 /*
1192 * Put in the original id.
1193 *
1194 * XXX Can TCP transfers be forwarded? How would that
1195 * work?
1196 */
1197 id = htons(tsig.originalid);
1198 memmove(&header[0], &id, 2);
1199 }
1200
1201 /*
1202 * Digest the modified header.
1203 */
1204 header_r.base = (unsigned char *) header;
1205 header_r.length = DNS_MESSAGE_HEADERLEN;
1206 ret = dst_context_adddata(msg->tsigctx, &header_r);
1207 if (ret != ISC_R_SUCCESS)
1208 goto cleanup_context;
1209
1210 /*
1211 * Digest all non-TSIG records.
1212 */
1213 isc_buffer_usedregion(source, &source_r);
1214 r.base = source_r.base + DNS_MESSAGE_HEADERLEN;
1215 if (has_tsig)
1216 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN;
1217 else
1218 r.length = source_r.length - DNS_MESSAGE_HEADERLEN;
1219 ret = dst_context_adddata(msg->tsigctx, &r);
1220 if (ret != ISC_R_SUCCESS)
1221 goto cleanup_context;
1222
1223 /*
1224 * Digest the time signed and fudge.
1225 */
1226 if (has_tsig) {
1227 isc_buffer_init(&databuf, data, sizeof(data));
1228 isc_buffer_putuint48(&databuf, tsig.timesigned);
1229 isc_buffer_putuint16(&databuf, tsig.fudge);
1230 isc_buffer_usedregion(&databuf, &r);
1231 ret = dst_context_adddata(msg->tsigctx, &r);
1232 if (ret != ISC_R_SUCCESS)
1233 goto cleanup_context;
1234
1235 sig_r.base = tsig.signature;
1236 sig_r.length = tsig.siglen;
1237 if (tsig.siglen == 0) {
1238 if (tsig.error != dns_rcode_noerror) {
1239 msg->tsigstatus = tsig.error;
1240 if (tsig.error == dns_tsigerror_badtime) {
1241 ret = DNS_R_CLOCKSKEW;
1242 } else {
1243 ret = DNS_R_TSIGERRORSET;
1244 }
1245 } else {
1246 tsig_log(msg->tsigkey, 2,
1247 "signature is empty");
1248 ret = DNS_R_TSIGVERIFYFAILURE;
1249 }
1250 goto cleanup_context;
1251 }
1252
1253 ret = dst_context_verify(msg->tsigctx, &sig_r);
1254 if (ret == DST_R_VERIFYFAILURE) {
1255 tsig_log(msg->tsigkey, 2,
1256 "signature failed to verify(2)");
1257 ret = DNS_R_TSIGVERIFYFAILURE;
1258 goto cleanup_context;
1259 } else if (ret != ISC_R_SUCCESS) {
1260 goto cleanup_context;
1261 }
1262 msg->verified_sig = 1;
1263
1264 /*
1265 * Here at this point, the MAC has been verified. Even
1266 * if any of the following code returns a TSIG error,
1267 * the reply will be signed and WILL always include the
1268 * request MAC in the digest computation.
1269 */
1270
1271 /*
1272 * Is the time ok?
1273 */
1274 time(&now);
1275
1276 if (now + msg->timeadjust > (time_t)(tsig.timesigned +
1277 tsig.fudge)) {
1278 msg->tsigstatus = dns_tsigerror_badtime;
1279 tsig_log(msg->tsigkey, 2, "signature has expired");
1280 ret = DNS_R_CLOCKSKEW;
1281 goto cleanup_context;
1282 } else if (now + msg->timeadjust < (time_t)(tsig.timesigned -
1283 tsig.fudge)) {
1284 msg->tsigstatus = dns_tsigerror_badtime;
1285 tsig_log(msg->tsigkey, 2,
1286 "signature is in the future");
1287 ret = DNS_R_CLOCKSKEW;
1288 goto cleanup_context;
1289 }
1290
1291 alg = dst_key_alg(key);
1292 ret = dst_key_sigsize(key, &siglen);
1293 if (ret != ISC_R_SUCCESS)
1294 goto cleanup_context;
1295 if (
1296 alg == DST_ALG_HMACSHA1 ||
1297 alg == DST_ALG_HMACSHA224 ||
1298 alg == DST_ALG_HMACSHA256 ||
1299 alg == DST_ALG_HMACSHA384 ||
1300 alg == DST_ALG_HMACSHA512)
1301 {
1302 uint16_t digestbits = dst_key_getbits(key);
1303
1304 /*
1305 * XXXRAY: Is this correct? What is the
1306 * expected behavior when digestbits is not an
1307 * integral multiple of 8? It looks like bytes
1308 * should either be (digestbits/8) or
1309 * (digestbits+7)/8.
1310 *
1311 * In any case, for current algorithms,
1312 * digestbits are an integral multiple of 8, so
1313 * it has the same effect as (digestbits/8).
1314 */
1315 if (tsig.siglen > 0 && digestbits != 0 &&
1316 tsig.siglen < ((digestbits + 1) / 8))
1317 {
1318 msg->tsigstatus = dns_tsigerror_badtrunc;
1319 tsig_log(msg->tsigkey, 2,
1320 "truncated signature length "
1321 "too small");
1322 ret = DNS_R_TSIGVERIFYFAILURE;
1323 goto cleanup_context;
1324 }
1325 if (tsig.siglen > 0 && digestbits == 0 &&
1326 tsig.siglen < siglen)
1327 {
1328 msg->tsigstatus = dns_tsigerror_badtrunc;
1329 tsig_log(msg->tsigkey, 2,
1330 "signature length too small");
1331 ret = DNS_R_TSIGVERIFYFAILURE;
1332 goto cleanup_context;
1333 }
1334 }
1335
1336 if (tsig.error != dns_rcode_noerror) {
1337 msg->tsigstatus = tsig.error;
1338 if (tsig.error == dns_tsigerror_badtime)
1339 ret = DNS_R_CLOCKSKEW;
1340 else
1341 ret = DNS_R_TSIGERRORSET;
1342 goto cleanup_context;
1343 }
1344 }
1345
1346 msg->tsigstatus = dns_rcode_noerror;
1347 ret = ISC_R_SUCCESS;
1348
1349 cleanup_context:
1350 /*
1351 * Except in error conditions, don't destroy the DST context
1352 * for unsigned messages; it is a running sum till the next
1353 * TSIG signed message.
1354 */
1355 if ((ret != ISC_R_SUCCESS || has_tsig) && msg->tsigctx != NULL) {
1356 dst_context_destroy(&msg->tsigctx);
1357 }
1358
1359 cleanup_querystruct:
1360 dns_rdata_freestruct_tsig(&querytsig);
1361
1362 return (ret);
1363 }
1364
1365