dnssec.c revision 194995
1/* 2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* 19 * $Id: dnssec.c,v 1.93.12.4 2009/06/08 23:47:00 tbox Exp $ 20 */ 21 22/*! \file */ 23 24#include <config.h> 25 26#include <stdlib.h> 27 28#include <isc/buffer.h> 29#include <isc/mem.h> 30#include <isc/serial.h> 31#include <isc/string.h> 32#include <isc/util.h> 33 34#include <dns/db.h> 35#include <dns/dnssec.h> 36#include <dns/fixedname.h> 37#include <dns/keyvalues.h> 38#include <dns/message.h> 39#include <dns/rdata.h> 40#include <dns/rdatalist.h> 41#include <dns/rdataset.h> 42#include <dns/rdatastruct.h> 43#include <dns/result.h> 44#include <dns/tsig.h> /* for DNS_TSIG_FUDGE */ 45 46#include <dst/result.h> 47 48#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR) 49 50#define RETERR(x) do { \ 51 result = (x); \ 52 if (result != ISC_R_SUCCESS) \ 53 goto failure; \ 54 } while (0) 55 56 57#define TYPE_SIGN 0 58#define TYPE_VERIFY 1 59 60static isc_result_t 61digest_callback(void *arg, isc_region_t *data); 62 63static int 64rdata_compare_wrapper(const void *rdata1, const void *rdata2); 65 66static isc_result_t 67rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 68 dns_rdata_t **rdata, int *nrdata); 69 70static isc_result_t 71digest_callback(void *arg, isc_region_t *data) { 72 dst_context_t *ctx = arg; 73 74 return (dst_context_adddata(ctx, data)); 75} 76 77/* 78 * Make qsort happy. 79 */ 80static int 81rdata_compare_wrapper(const void *rdata1, const void *rdata2) { 82 return (dns_rdata_compare((const dns_rdata_t *)rdata1, 83 (const dns_rdata_t *)rdata2)); 84} 85 86/* 87 * Sort the rdataset into an array. 88 */ 89static isc_result_t 90rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 91 dns_rdata_t **rdata, int *nrdata) 92{ 93 isc_result_t ret; 94 int i = 0, n; 95 dns_rdata_t *data; 96 97 n = dns_rdataset_count(set); 98 99 data = isc_mem_get(mctx, n * sizeof(dns_rdata_t)); 100 if (data == NULL) 101 return (ISC_R_NOMEMORY); 102 103 ret = dns_rdataset_first(set); 104 if (ret != ISC_R_SUCCESS) { 105 isc_mem_put(mctx, data, n * sizeof(dns_rdata_t)); 106 return (ret); 107 } 108 109 /* 110 * Put them in the array. 111 */ 112 do { 113 dns_rdata_init(&data[i]); 114 dns_rdataset_current(set, &data[i++]); 115 } while (dns_rdataset_next(set) == ISC_R_SUCCESS); 116 117 /* 118 * Sort the array. 119 */ 120 qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); 121 *rdata = data; 122 *nrdata = n; 123 return (ISC_R_SUCCESS); 124} 125 126isc_result_t 127dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx, 128 dst_key_t **key) 129{ 130 isc_buffer_t b; 131 isc_region_t r; 132 133 INSIST(name != NULL); 134 INSIST(rdata != NULL); 135 INSIST(mctx != NULL); 136 INSIST(key != NULL); 137 INSIST(*key == NULL); 138 REQUIRE(rdata->type == dns_rdatatype_key || 139 rdata->type == dns_rdatatype_dnskey); 140 141 dns_rdata_toregion(rdata, &r); 142 isc_buffer_init(&b, r.base, r.length); 143 isc_buffer_add(&b, r.length); 144 return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key)); 145} 146 147static isc_result_t 148digest_sig(dst_context_t *ctx, dns_rdata_t *sigrdata, dns_rdata_rrsig_t *sig) { 149 isc_region_t r; 150 isc_result_t ret; 151 dns_fixedname_t fname; 152 153 dns_rdata_toregion(sigrdata, &r); 154 INSIST(r.length >= 19); 155 156 r.length = 18; 157 ret = dst_context_adddata(ctx, &r); 158 if (ret != ISC_R_SUCCESS) 159 return (ret); 160 dns_fixedname_init(&fname); 161 RUNTIME_CHECK(dns_name_downcase(&sig->signer, 162 dns_fixedname_name(&fname), NULL) 163 == ISC_R_SUCCESS); 164 dns_name_toregion(dns_fixedname_name(&fname), &r); 165 return (dst_context_adddata(ctx, &r)); 166} 167 168isc_result_t 169dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 170 isc_stdtime_t *inception, isc_stdtime_t *expire, 171 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) 172{ 173 dns_rdata_rrsig_t sig; 174 dns_rdata_t tmpsigrdata; 175 dns_rdata_t *rdatas; 176 int nrdatas, i; 177 isc_buffer_t sigbuf, envbuf; 178 isc_region_t r; 179 dst_context_t *ctx = NULL; 180 isc_result_t ret; 181 isc_buffer_t *databuf = NULL; 182 char data[256 + 8]; 183 isc_uint32_t flags; 184 unsigned int sigsize; 185 dns_fixedname_t fnewname; 186 187 REQUIRE(name != NULL); 188 REQUIRE(dns_name_countlabels(name) <= 255); 189 REQUIRE(set != NULL); 190 REQUIRE(key != NULL); 191 REQUIRE(inception != NULL); 192 REQUIRE(expire != NULL); 193 REQUIRE(mctx != NULL); 194 REQUIRE(sigrdata != NULL); 195 196 if (*inception >= *expire) 197 return (DNS_R_INVALIDTIME); 198 199 /* 200 * Is the key allowed to sign data? 201 */ 202 flags = dst_key_flags(key); 203 if (flags & DNS_KEYTYPE_NOAUTH) 204 return (DNS_R_KEYUNAUTHORIZED); 205 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) 206 return (DNS_R_KEYUNAUTHORIZED); 207 208 sig.mctx = mctx; 209 sig.common.rdclass = set->rdclass; 210 sig.common.rdtype = dns_rdatatype_rrsig; 211 ISC_LINK_INIT(&sig.common, link); 212 213 dns_name_init(&sig.signer, NULL); 214 dns_name_clone(dst_key_name(key), &sig.signer); 215 216 sig.covered = set->type; 217 sig.algorithm = dst_key_alg(key); 218 sig.labels = dns_name_countlabels(name) - 1; 219 if (dns_name_iswildcard(name)) 220 sig.labels--; 221 sig.originalttl = set->ttl; 222 sig.timesigned = *inception; 223 sig.timeexpire = *expire; 224 sig.keyid = dst_key_id(key); 225 ret = dst_key_sigsize(key, &sigsize); 226 if (ret != ISC_R_SUCCESS) 227 return (ret); 228 sig.siglen = sigsize; 229 /* 230 * The actual contents of sig.signature are not important yet, since 231 * they're not used in digest_sig(). 232 */ 233 sig.signature = isc_mem_get(mctx, sig.siglen); 234 if (sig.signature == NULL) 235 return (ISC_R_NOMEMORY); 236 237 ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18); 238 if (ret != ISC_R_SUCCESS) 239 goto cleanup_signature; 240 241 dns_rdata_init(&tmpsigrdata); 242 ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass, 243 sig.common.rdtype, &sig, databuf); 244 if (ret != ISC_R_SUCCESS) 245 goto cleanup_databuf; 246 247 ret = dst_context_create(key, mctx, &ctx); 248 if (ret != ISC_R_SUCCESS) 249 goto cleanup_databuf; 250 251 /* 252 * Digest the SIG rdata. 253 */ 254 ret = digest_sig(ctx, &tmpsigrdata, &sig); 255 if (ret != ISC_R_SUCCESS) 256 goto cleanup_context; 257 258 dns_fixedname_init(&fnewname); 259 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 260 NULL) == ISC_R_SUCCESS); 261 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 262 263 /* 264 * Create an envelope for each rdata: <name|type|class|ttl>. 265 */ 266 isc_buffer_init(&envbuf, data, sizeof(data)); 267 memcpy(data, r.base, r.length); 268 isc_buffer_add(&envbuf, r.length); 269 isc_buffer_putuint16(&envbuf, set->type); 270 isc_buffer_putuint16(&envbuf, set->rdclass); 271 isc_buffer_putuint32(&envbuf, set->ttl); 272 273 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 274 if (ret != ISC_R_SUCCESS) 275 goto cleanup_context; 276 isc_buffer_usedregion(&envbuf, &r); 277 278 for (i = 0; i < nrdatas; i++) { 279 isc_uint16_t len; 280 isc_buffer_t lenbuf; 281 isc_region_t lenr; 282 283 /* 284 * Skip duplicates. 285 */ 286 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) 287 continue; 288 289 /* 290 * Digest the envelope. 291 */ 292 ret = dst_context_adddata(ctx, &r); 293 if (ret != ISC_R_SUCCESS) 294 goto cleanup_array; 295 296 /* 297 * Digest the length of the rdata. 298 */ 299 isc_buffer_init(&lenbuf, &len, sizeof(len)); 300 INSIST(rdatas[i].length < 65536); 301 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); 302 isc_buffer_usedregion(&lenbuf, &lenr); 303 ret = dst_context_adddata(ctx, &lenr); 304 if (ret != ISC_R_SUCCESS) 305 goto cleanup_array; 306 307 /* 308 * Digest the rdata. 309 */ 310 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 311 if (ret != ISC_R_SUCCESS) 312 goto cleanup_array; 313 } 314 315 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 316 ret = dst_context_sign(ctx, &sigbuf); 317 if (ret != ISC_R_SUCCESS) 318 goto cleanup_array; 319 isc_buffer_usedregion(&sigbuf, &r); 320 if (r.length != sig.siglen) { 321 ret = ISC_R_NOSPACE; 322 goto cleanup_array; 323 } 324 memcpy(sig.signature, r.base, sig.siglen); 325 326 ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass, 327 sig.common.rdtype, &sig, buffer); 328 329cleanup_array: 330 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 331cleanup_context: 332 dst_context_destroy(&ctx); 333cleanup_databuf: 334 isc_buffer_free(&databuf); 335cleanup_signature: 336 isc_mem_put(mctx, sig.signature, sig.siglen); 337 338 return (ret); 339} 340 341isc_result_t 342dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 343 isc_boolean_t ignoretime, isc_mem_t *mctx, 344 dns_rdata_t *sigrdata, dns_name_t *wild) 345{ 346 dns_rdata_rrsig_t sig; 347 dns_fixedname_t fnewname; 348 isc_region_t r; 349 isc_buffer_t envbuf; 350 dns_rdata_t *rdatas; 351 int nrdatas, i; 352 isc_stdtime_t now; 353 isc_result_t ret; 354 unsigned char data[300]; 355 dst_context_t *ctx = NULL; 356 int labels = 0; 357 isc_uint32_t flags; 358 359 REQUIRE(name != NULL); 360 REQUIRE(set != NULL); 361 REQUIRE(key != NULL); 362 REQUIRE(mctx != NULL); 363 REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig); 364 365 ret = dns_rdata_tostruct(sigrdata, &sig, NULL); 366 if (ret != ISC_R_SUCCESS) 367 return (ret); 368 369 if (set->type != sig.covered) 370 return (DNS_R_SIGINVALID); 371 372 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) 373 return (DNS_R_SIGINVALID); 374 375 if (!ignoretime) { 376 isc_stdtime_get(&now); 377 378 /* 379 * Is SIG temporally valid? 380 */ 381 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) 382 return (DNS_R_SIGFUTURE); 383 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) 384 return (DNS_R_SIGEXPIRED); 385 } 386 387 /* 388 * NS, SOA and DNSSKEY records are signed by their owner. 389 * DS records are signed by the parent. 390 */ 391 switch (set->type) { 392 case dns_rdatatype_ns: 393 case dns_rdatatype_soa: 394 case dns_rdatatype_dnskey: 395 if (!dns_name_equal(name, &sig.signer)) 396 return (DNS_R_SIGINVALID); 397 break; 398 case dns_rdatatype_ds: 399 if (dns_name_equal(name, &sig.signer)) 400 return (DNS_R_SIGINVALID); 401 /* FALLTHROUGH */ 402 default: 403 if (!dns_name_issubdomain(name, &sig.signer)) 404 return (DNS_R_SIGINVALID); 405 break; 406 } 407 408 /* 409 * Is the key allowed to sign data? 410 */ 411 flags = dst_key_flags(key); 412 if (flags & DNS_KEYTYPE_NOAUTH) 413 return (DNS_R_KEYUNAUTHORIZED); 414 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) 415 return (DNS_R_KEYUNAUTHORIZED); 416 417 ret = dst_context_create(key, mctx, &ctx); 418 if (ret != ISC_R_SUCCESS) 419 goto cleanup_struct; 420 421 /* 422 * Digest the SIG rdata (not including the signature). 423 */ 424 ret = digest_sig(ctx, sigrdata, &sig); 425 if (ret != ISC_R_SUCCESS) 426 goto cleanup_context; 427 428 /* 429 * If the name is an expanded wildcard, use the wildcard name. 430 */ 431 dns_fixedname_init(&fnewname); 432 labels = dns_name_countlabels(name) - 1; 433 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 434 NULL) == ISC_R_SUCCESS); 435 if (labels - sig.labels > 0) 436 dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1, 437 NULL, dns_fixedname_name(&fnewname)); 438 439 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 440 441 /* 442 * Create an envelope for each rdata: <name|type|class|ttl>. 443 */ 444 isc_buffer_init(&envbuf, data, sizeof(data)); 445 if (labels - sig.labels > 0) { 446 isc_buffer_putuint8(&envbuf, 1); 447 isc_buffer_putuint8(&envbuf, '*'); 448 memcpy(data + 2, r.base, r.length); 449 } 450 else 451 memcpy(data, r.base, r.length); 452 isc_buffer_add(&envbuf, r.length); 453 isc_buffer_putuint16(&envbuf, set->type); 454 isc_buffer_putuint16(&envbuf, set->rdclass); 455 isc_buffer_putuint32(&envbuf, sig.originalttl); 456 457 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 458 if (ret != ISC_R_SUCCESS) 459 goto cleanup_context; 460 461 isc_buffer_usedregion(&envbuf, &r); 462 463 for (i = 0; i < nrdatas; i++) { 464 isc_uint16_t len; 465 isc_buffer_t lenbuf; 466 isc_region_t lenr; 467 468 /* 469 * Skip duplicates. 470 */ 471 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) 472 continue; 473 474 /* 475 * Digest the envelope. 476 */ 477 ret = dst_context_adddata(ctx, &r); 478 if (ret != ISC_R_SUCCESS) 479 goto cleanup_array; 480 481 /* 482 * Digest the rdata length. 483 */ 484 isc_buffer_init(&lenbuf, &len, sizeof(len)); 485 INSIST(rdatas[i].length < 65536); 486 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); 487 isc_buffer_usedregion(&lenbuf, &lenr); 488 489 /* 490 * Digest the rdata. 491 */ 492 ret = dst_context_adddata(ctx, &lenr); 493 if (ret != ISC_R_SUCCESS) 494 goto cleanup_array; 495 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 496 if (ret != ISC_R_SUCCESS) 497 goto cleanup_array; 498 } 499 500 r.base = sig.signature; 501 r.length = sig.siglen; 502 ret = dst_context_verify(ctx, &r); 503 if (ret == DST_R_VERIFYFAILURE) 504 ret = DNS_R_SIGINVALID; 505 506cleanup_array: 507 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 508cleanup_context: 509 dst_context_destroy(&ctx); 510cleanup_struct: 511 dns_rdata_freestruct(&sig); 512 513 if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) { 514 if (wild != NULL) 515 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, 516 dns_fixedname_name(&fnewname), 517 wild, NULL) == ISC_R_SUCCESS); 518 ret = DNS_R_FROMWILDCARD; 519 } 520 return (ret); 521} 522 523isc_result_t 524dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 525 isc_boolean_t ignoretime, isc_mem_t *mctx, 526 dns_rdata_t *sigrdata) 527{ 528 isc_result_t result; 529 530 result = dns_dnssec_verify2(name, set, key, ignoretime, mctx, 531 sigrdata, NULL); 532 if (result == DNS_R_FROMWILDCARD) 533 result = ISC_R_SUCCESS; 534 return (result); 535} 536 537#define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \ 538 == DNS_KEYOWNER_ZONE) 539 540isc_result_t 541dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, 542 dns_dbnode_t *node, dns_name_t *name, 543 const char *directory, isc_mem_t *mctx, 544 unsigned int maxkeys, dst_key_t **keys, 545 unsigned int *nkeys) 546{ 547 dns_rdataset_t rdataset; 548 dns_rdata_t rdata = DNS_RDATA_INIT; 549 isc_result_t result; 550 dst_key_t *pubkey = NULL; 551 unsigned int count = 0; 552 553 REQUIRE(nkeys != NULL); 554 REQUIRE(keys != NULL); 555 556 *nkeys = 0; 557 dns_rdataset_init(&rdataset); 558 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, 559 &rdataset, NULL)); 560 RETERR(dns_rdataset_first(&rdataset)); 561 while (result == ISC_R_SUCCESS && count < maxkeys) { 562 pubkey = NULL; 563 dns_rdataset_current(&rdataset, &rdata); 564 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey)); 565 if (!is_zone_key(pubkey) || 566 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) 567 goto next; 568 /* Corrupted .key file? */ 569 if (!dns_name_equal(name, dst_key_name(pubkey))) 570 goto next; 571 keys[count] = NULL; 572 result = dst_key_fromfile(dst_key_name(pubkey), 573 dst_key_id(pubkey), 574 dst_key_alg(pubkey), 575 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 576 directory, 577 mctx, &keys[count]); 578 if (result == ISC_R_FILENOTFOUND) { 579 keys[count] = pubkey; 580 pubkey = NULL; 581 count++; 582 goto next; 583 } 584 if (result != ISC_R_SUCCESS) 585 goto failure; 586 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) { 587 /* We should never get here. */ 588 dst_key_free(&keys[count]); 589 goto next; 590 } 591 count++; 592 next: 593 if (pubkey != NULL) 594 dst_key_free(&pubkey); 595 dns_rdata_reset(&rdata); 596 result = dns_rdataset_next(&rdataset); 597 } 598 if (result != ISC_R_NOMORE) 599 goto failure; 600 if (count == 0) 601 result = ISC_R_NOTFOUND; 602 else 603 result = ISC_R_SUCCESS; 604 605 failure: 606 if (dns_rdataset_isassociated(&rdataset)) 607 dns_rdataset_disassociate(&rdataset); 608 if (pubkey != NULL) 609 dst_key_free(&pubkey); 610 if (result != ISC_R_SUCCESS) 611 while (count > 0) 612 dst_key_free(&keys[--count]); 613 *nkeys = count; 614 return (result); 615} 616 617isc_result_t 618dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, 619 dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx, 620 unsigned int maxkeys, dst_key_t **keys, 621 unsigned int *nkeys) 622{ 623 return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx, 624 maxkeys, keys, nkeys)); 625} 626 627isc_result_t 628dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) { 629 dns_rdata_sig_t sig; /* SIG(0) */ 630 unsigned char data[512]; 631 unsigned char header[DNS_MESSAGE_HEADERLEN]; 632 isc_buffer_t headerbuf, databuf, sigbuf; 633 unsigned int sigsize; 634 isc_buffer_t *dynbuf = NULL; 635 dns_rdata_t *rdata; 636 dns_rdatalist_t *datalist; 637 dns_rdataset_t *dataset; 638 isc_region_t r; 639 isc_stdtime_t now; 640 dst_context_t *ctx = NULL; 641 isc_mem_t *mctx; 642 isc_result_t result; 643 isc_boolean_t signeedsfree = ISC_TRUE; 644 645 REQUIRE(msg != NULL); 646 REQUIRE(key != NULL); 647 648 if (is_response(msg)) 649 REQUIRE(msg->query.base != NULL); 650 651 mctx = msg->mctx; 652 653 memset(&sig, 0, sizeof(sig)); 654 655 sig.mctx = mctx; 656 sig.common.rdclass = dns_rdataclass_any; 657 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */ 658 ISC_LINK_INIT(&sig.common, link); 659 660 sig.covered = 0; 661 sig.algorithm = dst_key_alg(key); 662 sig.labels = 0; /* the root name */ 663 sig.originalttl = 0; 664 665 isc_stdtime_get(&now); 666 sig.timesigned = now - DNS_TSIG_FUDGE; 667 sig.timeexpire = now + DNS_TSIG_FUDGE; 668 669 sig.keyid = dst_key_id(key); 670 671 dns_name_init(&sig.signer, NULL); 672 dns_name_clone(dst_key_name(key), &sig.signer); 673 674 sig.siglen = 0; 675 sig.signature = NULL; 676 677 isc_buffer_init(&databuf, data, sizeof(data)); 678 679 RETERR(dst_context_create(key, mctx, &ctx)); 680 681 /* 682 * Digest the fields of the SIG - we can cheat and use 683 * dns_rdata_fromstruct. Since siglen is 0, the digested data 684 * is identical to dns format. 685 */ 686 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any, 687 dns_rdatatype_sig /* SIG(0) */, 688 &sig, &databuf)); 689 isc_buffer_usedregion(&databuf, &r); 690 RETERR(dst_context_adddata(ctx, &r)); 691 692 /* 693 * If this is a response, digest the query. 694 */ 695 if (is_response(msg)) 696 RETERR(dst_context_adddata(ctx, &msg->query)); 697 698 /* 699 * Digest the header. 700 */ 701 isc_buffer_init(&headerbuf, header, sizeof(header)); 702 dns_message_renderheader(msg, &headerbuf); 703 isc_buffer_usedregion(&headerbuf, &r); 704 RETERR(dst_context_adddata(ctx, &r)); 705 706 /* 707 * Digest the remainder of the message. 708 */ 709 isc_buffer_usedregion(msg->buffer, &r); 710 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 711 RETERR(dst_context_adddata(ctx, &r)); 712 713 RETERR(dst_key_sigsize(key, &sigsize)); 714 sig.siglen = sigsize; 715 sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen); 716 if (sig.signature == NULL) { 717 result = ISC_R_NOMEMORY; 718 goto failure; 719 } 720 721 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 722 RETERR(dst_context_sign(ctx, &sigbuf)); 723 dst_context_destroy(&ctx); 724 725 rdata = NULL; 726 RETERR(dns_message_gettemprdata(msg, &rdata)); 727 RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024)); 728 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any, 729 dns_rdatatype_sig /* SIG(0) */, 730 &sig, dynbuf)); 731 732 isc_mem_put(mctx, sig.signature, sig.siglen); 733 signeedsfree = ISC_FALSE; 734 735 dns_message_takebuffer(msg, &dynbuf); 736 737 datalist = NULL; 738 RETERR(dns_message_gettemprdatalist(msg, &datalist)); 739 datalist->rdclass = dns_rdataclass_any; 740 datalist->type = dns_rdatatype_sig; /* SIG(0) */ 741 datalist->covers = 0; 742 datalist->ttl = 0; 743 ISC_LIST_INIT(datalist->rdata); 744 ISC_LIST_APPEND(datalist->rdata, rdata, link); 745 dataset = NULL; 746 RETERR(dns_message_gettemprdataset(msg, &dataset)); 747 dns_rdataset_init(dataset); 748 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS); 749 msg->sig0 = dataset; 750 751 return (ISC_R_SUCCESS); 752 753failure: 754 if (dynbuf != NULL) 755 isc_buffer_free(&dynbuf); 756 if (signeedsfree) 757 isc_mem_put(mctx, sig.signature, sig.siglen); 758 if (ctx != NULL) 759 dst_context_destroy(&ctx); 760 761 return (result); 762} 763 764isc_result_t 765dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, 766 dst_key_t *key) 767{ 768 dns_rdata_sig_t sig; /* SIG(0) */ 769 unsigned char header[DNS_MESSAGE_HEADERLEN]; 770 dns_rdata_t rdata = DNS_RDATA_INIT; 771 isc_region_t r, source_r, sig_r, header_r; 772 isc_stdtime_t now; 773 dst_context_t *ctx = NULL; 774 isc_mem_t *mctx; 775 isc_result_t result; 776 isc_uint16_t addcount; 777 isc_boolean_t signeedsfree = ISC_FALSE; 778 779 REQUIRE(source != NULL); 780 REQUIRE(msg != NULL); 781 REQUIRE(key != NULL); 782 783 mctx = msg->mctx; 784 785 msg->verify_attempted = 1; 786 787 if (is_response(msg)) { 788 if (msg->query.base == NULL) 789 return (DNS_R_UNEXPECTEDTSIG); 790 } 791 792 isc_buffer_usedregion(source, &source_r); 793 794 RETERR(dns_rdataset_first(msg->sig0)); 795 dns_rdataset_current(msg->sig0, &rdata); 796 797 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL)); 798 signeedsfree = ISC_TRUE; 799 800 if (sig.labels != 0) { 801 result = DNS_R_SIGINVALID; 802 goto failure; 803 } 804 805 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) { 806 result = DNS_R_SIGINVALID; 807 msg->sig0status = dns_tsigerror_badtime; 808 goto failure; 809 } 810 811 isc_stdtime_get(&now); 812 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) { 813 result = DNS_R_SIGFUTURE; 814 msg->sig0status = dns_tsigerror_badtime; 815 goto failure; 816 } 817 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) { 818 result = DNS_R_SIGEXPIRED; 819 msg->sig0status = dns_tsigerror_badtime; 820 goto failure; 821 } 822 823 if (!dns_name_equal(dst_key_name(key), &sig.signer)) { 824 result = DNS_R_SIGINVALID; 825 msg->sig0status = dns_tsigerror_badkey; 826 goto failure; 827 } 828 829 RETERR(dst_context_create(key, mctx, &ctx)); 830 831 /* 832 * Digest the SIG(0) record, except for the signature. 833 */ 834 dns_rdata_toregion(&rdata, &r); 835 r.length -= sig.siglen; 836 RETERR(dst_context_adddata(ctx, &r)); 837 838 /* 839 * If this is a response, digest the query. 840 */ 841 if (is_response(msg)) 842 RETERR(dst_context_adddata(ctx, &msg->query)); 843 844 /* 845 * Extract the header. 846 */ 847 memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN); 848 849 /* 850 * Decrement the additional field counter. 851 */ 852 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 853 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); 854 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 855 856 /* 857 * Digest the modified header. 858 */ 859 header_r.base = (unsigned char *) header; 860 header_r.length = DNS_MESSAGE_HEADERLEN; 861 RETERR(dst_context_adddata(ctx, &header_r)); 862 863 /* 864 * Digest all non-SIG(0) records. 865 */ 866 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 867 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 868 RETERR(dst_context_adddata(ctx, &r)); 869 870 sig_r.base = sig.signature; 871 sig_r.length = sig.siglen; 872 result = dst_context_verify(ctx, &sig_r); 873 if (result != ISC_R_SUCCESS) { 874 msg->sig0status = dns_tsigerror_badsig; 875 goto failure; 876 } 877 878 msg->verified_sig = 1; 879 880 dst_context_destroy(&ctx); 881 dns_rdata_freestruct(&sig); 882 883 return (ISC_R_SUCCESS); 884 885failure: 886 if (signeedsfree) 887 dns_rdata_freestruct(&sig); 888 if (ctx != NULL) 889 dst_context_destroy(&ctx); 890 891 return (result); 892} 893