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