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.14 2020/09/14 08:40:43 florian 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 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 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 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 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 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 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 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 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 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