dnssec.c revision 224092
1/* 2 * Copyright (C) 2004-2010 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.119 2010-01-13 23:48:59 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/dir.h> 30#include <isc/mem.h> 31#include <isc/serial.h> 32#include <isc/string.h> 33#include <isc/util.h> 34 35#include <dns/db.h> 36#include <dns/diff.h> 37#include <dns/dnssec.h> 38#include <dns/fixedname.h> 39#include <dns/keyvalues.h> 40#include <dns/log.h> 41#include <dns/message.h> 42#include <dns/rdata.h> 43#include <dns/rdatalist.h> 44#include <dns/rdataset.h> 45#include <dns/rdatastruct.h> 46#include <dns/result.h> 47#include <dns/tsig.h> /* for DNS_TSIG_FUDGE */ 48 49#include <dst/result.h> 50 51#define is_response(msg) (msg->flags & DNS_MESSAGEFLAG_QR) 52 53#define RETERR(x) do { \ 54 result = (x); \ 55 if (result != ISC_R_SUCCESS) \ 56 goto failure; \ 57 } while (0) 58 59 60#define TYPE_SIGN 0 61#define TYPE_VERIFY 1 62 63static isc_result_t 64digest_callback(void *arg, isc_region_t *data); 65 66static int 67rdata_compare_wrapper(const void *rdata1, const void *rdata2); 68 69static isc_result_t 70rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 71 dns_rdata_t **rdata, int *nrdata); 72 73static isc_result_t 74digest_callback(void *arg, isc_region_t *data) { 75 dst_context_t *ctx = arg; 76 77 return (dst_context_adddata(ctx, data)); 78} 79 80/* 81 * Make qsort happy. 82 */ 83static int 84rdata_compare_wrapper(const void *rdata1, const void *rdata2) { 85 return (dns_rdata_compare((const dns_rdata_t *)rdata1, 86 (const dns_rdata_t *)rdata2)); 87} 88 89/* 90 * Sort the rdataset into an array. 91 */ 92static isc_result_t 93rdataset_to_sortedarray(dns_rdataset_t *set, isc_mem_t *mctx, 94 dns_rdata_t **rdata, int *nrdata) 95{ 96 isc_result_t ret; 97 int i = 0, n; 98 dns_rdata_t *data; 99 dns_rdataset_t rdataset; 100 101 n = dns_rdataset_count(set); 102 103 data = isc_mem_get(mctx, n * sizeof(dns_rdata_t)); 104 if (data == NULL) 105 return (ISC_R_NOMEMORY); 106 107 dns_rdataset_init(&rdataset); 108 dns_rdataset_clone(set, &rdataset); 109 ret = dns_rdataset_first(&rdataset); 110 if (ret != ISC_R_SUCCESS) { 111 dns_rdataset_disassociate(&rdataset); 112 isc_mem_put(mctx, data, n * sizeof(dns_rdata_t)); 113 return (ret); 114 } 115 116 /* 117 * Put them in the array. 118 */ 119 do { 120 dns_rdata_init(&data[i]); 121 dns_rdataset_current(&rdataset, &data[i++]); 122 } while (dns_rdataset_next(&rdataset) == ISC_R_SUCCESS); 123 124 /* 125 * Sort the array. 126 */ 127 qsort(data, n, sizeof(dns_rdata_t), rdata_compare_wrapper); 128 *rdata = data; 129 *nrdata = n; 130 dns_rdataset_disassociate(&rdataset); 131 return (ISC_R_SUCCESS); 132} 133 134isc_result_t 135dns_dnssec_keyfromrdata(dns_name_t *name, dns_rdata_t *rdata, isc_mem_t *mctx, 136 dst_key_t **key) 137{ 138 isc_buffer_t b; 139 isc_region_t r; 140 141 INSIST(name != NULL); 142 INSIST(rdata != NULL); 143 INSIST(mctx != NULL); 144 INSIST(key != NULL); 145 INSIST(*key == NULL); 146 REQUIRE(rdata->type == dns_rdatatype_key || 147 rdata->type == dns_rdatatype_dnskey); 148 149 dns_rdata_toregion(rdata, &r); 150 isc_buffer_init(&b, r.base, r.length); 151 isc_buffer_add(&b, r.length); 152 return (dst_key_fromdns(name, rdata->rdclass, &b, mctx, key)); 153} 154 155static isc_result_t 156digest_sig(dst_context_t *ctx, dns_rdata_t *sigrdata, dns_rdata_rrsig_t *sig) { 157 isc_region_t r; 158 isc_result_t ret; 159 dns_fixedname_t fname; 160 161 dns_rdata_toregion(sigrdata, &r); 162 INSIST(r.length >= 19); 163 164 r.length = 18; 165 ret = dst_context_adddata(ctx, &r); 166 if (ret != ISC_R_SUCCESS) 167 return (ret); 168 dns_fixedname_init(&fname); 169 RUNTIME_CHECK(dns_name_downcase(&sig->signer, 170 dns_fixedname_name(&fname), NULL) 171 == ISC_R_SUCCESS); 172 dns_name_toregion(dns_fixedname_name(&fname), &r); 173 return (dst_context_adddata(ctx, &r)); 174} 175 176isc_result_t 177dns_dnssec_sign(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 178 isc_stdtime_t *inception, isc_stdtime_t *expire, 179 isc_mem_t *mctx, isc_buffer_t *buffer, dns_rdata_t *sigrdata) 180{ 181 dns_rdata_rrsig_t sig; 182 dns_rdata_t tmpsigrdata; 183 dns_rdata_t *rdatas; 184 int nrdatas, i; 185 isc_buffer_t sigbuf, envbuf; 186 isc_region_t r; 187 dst_context_t *ctx = NULL; 188 isc_result_t ret; 189 isc_buffer_t *databuf = NULL; 190 char data[256 + 8]; 191 isc_uint32_t flags; 192 unsigned int sigsize; 193 dns_fixedname_t fnewname; 194 195 REQUIRE(name != NULL); 196 REQUIRE(dns_name_countlabels(name) <= 255); 197 REQUIRE(set != NULL); 198 REQUIRE(key != NULL); 199 REQUIRE(inception != NULL); 200 REQUIRE(expire != NULL); 201 REQUIRE(mctx != NULL); 202 REQUIRE(sigrdata != NULL); 203 204 if (*inception >= *expire) 205 return (DNS_R_INVALIDTIME); 206 207 /* 208 * Is the key allowed to sign data? 209 */ 210 flags = dst_key_flags(key); 211 if (flags & DNS_KEYTYPE_NOAUTH) 212 return (DNS_R_KEYUNAUTHORIZED); 213 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) 214 return (DNS_R_KEYUNAUTHORIZED); 215 216 sig.mctx = mctx; 217 sig.common.rdclass = set->rdclass; 218 sig.common.rdtype = dns_rdatatype_rrsig; 219 ISC_LINK_INIT(&sig.common, link); 220 221 dns_name_init(&sig.signer, NULL); 222 dns_name_clone(dst_key_name(key), &sig.signer); 223 224 sig.covered = set->type; 225 sig.algorithm = dst_key_alg(key); 226 sig.labels = dns_name_countlabels(name) - 1; 227 if (dns_name_iswildcard(name)) 228 sig.labels--; 229 sig.originalttl = set->ttl; 230 sig.timesigned = *inception; 231 sig.timeexpire = *expire; 232 sig.keyid = dst_key_id(key); 233 ret = dst_key_sigsize(key, &sigsize); 234 if (ret != ISC_R_SUCCESS) 235 return (ret); 236 sig.siglen = sigsize; 237 /* 238 * The actual contents of sig.signature are not important yet, since 239 * they're not used in digest_sig(). 240 */ 241 sig.signature = isc_mem_get(mctx, sig.siglen); 242 if (sig.signature == NULL) 243 return (ISC_R_NOMEMORY); 244 245 ret = isc_buffer_allocate(mctx, &databuf, sigsize + 256 + 18); 246 if (ret != ISC_R_SUCCESS) 247 goto cleanup_signature; 248 249 dns_rdata_init(&tmpsigrdata); 250 ret = dns_rdata_fromstruct(&tmpsigrdata, sig.common.rdclass, 251 sig.common.rdtype, &sig, databuf); 252 if (ret != ISC_R_SUCCESS) 253 goto cleanup_databuf; 254 255 ret = dst_context_create(key, mctx, &ctx); 256 if (ret != ISC_R_SUCCESS) 257 goto cleanup_databuf; 258 259 /* 260 * Digest the SIG rdata. 261 */ 262 ret = digest_sig(ctx, &tmpsigrdata, &sig); 263 if (ret != ISC_R_SUCCESS) 264 goto cleanup_context; 265 266 dns_fixedname_init(&fnewname); 267 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 268 NULL) == ISC_R_SUCCESS); 269 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 270 271 /* 272 * Create an envelope for each rdata: <name|type|class|ttl>. 273 */ 274 isc_buffer_init(&envbuf, data, sizeof(data)); 275 memcpy(data, r.base, r.length); 276 isc_buffer_add(&envbuf, r.length); 277 isc_buffer_putuint16(&envbuf, set->type); 278 isc_buffer_putuint16(&envbuf, set->rdclass); 279 isc_buffer_putuint32(&envbuf, set->ttl); 280 281 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 282 if (ret != ISC_R_SUCCESS) 283 goto cleanup_context; 284 isc_buffer_usedregion(&envbuf, &r); 285 286 for (i = 0; i < nrdatas; i++) { 287 isc_uint16_t len; 288 isc_buffer_t lenbuf; 289 isc_region_t lenr; 290 291 /* 292 * Skip duplicates. 293 */ 294 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) 295 continue; 296 297 /* 298 * Digest the envelope. 299 */ 300 ret = dst_context_adddata(ctx, &r); 301 if (ret != ISC_R_SUCCESS) 302 goto cleanup_array; 303 304 /* 305 * Digest the length of the rdata. 306 */ 307 isc_buffer_init(&lenbuf, &len, sizeof(len)); 308 INSIST(rdatas[i].length < 65536); 309 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); 310 isc_buffer_usedregion(&lenbuf, &lenr); 311 ret = dst_context_adddata(ctx, &lenr); 312 if (ret != ISC_R_SUCCESS) 313 goto cleanup_array; 314 315 /* 316 * Digest the rdata. 317 */ 318 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 319 if (ret != ISC_R_SUCCESS) 320 goto cleanup_array; 321 } 322 323 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 324 ret = dst_context_sign(ctx, &sigbuf); 325 if (ret != ISC_R_SUCCESS) 326 goto cleanup_array; 327 isc_buffer_usedregion(&sigbuf, &r); 328 if (r.length != sig.siglen) { 329 ret = ISC_R_NOSPACE; 330 goto cleanup_array; 331 } 332 memcpy(sig.signature, r.base, sig.siglen); 333 334 ret = dns_rdata_fromstruct(sigrdata, sig.common.rdclass, 335 sig.common.rdtype, &sig, buffer); 336 337cleanup_array: 338 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 339cleanup_context: 340 dst_context_destroy(&ctx); 341cleanup_databuf: 342 isc_buffer_free(&databuf); 343cleanup_signature: 344 isc_mem_put(mctx, sig.signature, sig.siglen); 345 346 return (ret); 347} 348 349isc_result_t 350dns_dnssec_verify2(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 351 isc_boolean_t ignoretime, isc_mem_t *mctx, 352 dns_rdata_t *sigrdata, dns_name_t *wild) 353{ 354 dns_rdata_rrsig_t sig; 355 dns_fixedname_t fnewname; 356 isc_region_t r; 357 isc_buffer_t envbuf; 358 dns_rdata_t *rdatas; 359 int nrdatas, i; 360 isc_stdtime_t now; 361 isc_result_t ret; 362 unsigned char data[300]; 363 dst_context_t *ctx = NULL; 364 int labels = 0; 365 isc_uint32_t flags; 366 367 REQUIRE(name != NULL); 368 REQUIRE(set != NULL); 369 REQUIRE(key != NULL); 370 REQUIRE(mctx != NULL); 371 REQUIRE(sigrdata != NULL && sigrdata->type == dns_rdatatype_rrsig); 372 373 ret = dns_rdata_tostruct(sigrdata, &sig, NULL); 374 if (ret != ISC_R_SUCCESS) 375 return (ret); 376 377 if (set->type != sig.covered) 378 return (DNS_R_SIGINVALID); 379 380 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) 381 return (DNS_R_SIGINVALID); 382 383 if (!ignoretime) { 384 isc_stdtime_get(&now); 385 386 /* 387 * Is SIG temporally valid? 388 */ 389 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) 390 return (DNS_R_SIGFUTURE); 391 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) 392 return (DNS_R_SIGEXPIRED); 393 } 394 395 /* 396 * NS, SOA and DNSSKEY records are signed by their owner. 397 * DS records are signed by the parent. 398 */ 399 switch (set->type) { 400 case dns_rdatatype_ns: 401 case dns_rdatatype_soa: 402 case dns_rdatatype_dnskey: 403 if (!dns_name_equal(name, &sig.signer)) 404 return (DNS_R_SIGINVALID); 405 break; 406 case dns_rdatatype_ds: 407 if (dns_name_equal(name, &sig.signer)) 408 return (DNS_R_SIGINVALID); 409 /* FALLTHROUGH */ 410 default: 411 if (!dns_name_issubdomain(name, &sig.signer)) 412 return (DNS_R_SIGINVALID); 413 break; 414 } 415 416 /* 417 * Is the key allowed to sign data? 418 */ 419 flags = dst_key_flags(key); 420 if (flags & DNS_KEYTYPE_NOAUTH) 421 return (DNS_R_KEYUNAUTHORIZED); 422 if ((flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE) 423 return (DNS_R_KEYUNAUTHORIZED); 424 425 ret = dst_context_create(key, mctx, &ctx); 426 if (ret != ISC_R_SUCCESS) 427 goto cleanup_struct; 428 429 /* 430 * Digest the SIG rdata (not including the signature). 431 */ 432 ret = digest_sig(ctx, sigrdata, &sig); 433 if (ret != ISC_R_SUCCESS) 434 goto cleanup_context; 435 436 /* 437 * If the name is an expanded wildcard, use the wildcard name. 438 */ 439 dns_fixedname_init(&fnewname); 440 labels = dns_name_countlabels(name) - 1; 441 RUNTIME_CHECK(dns_name_downcase(name, dns_fixedname_name(&fnewname), 442 NULL) == ISC_R_SUCCESS); 443 if (labels - sig.labels > 0) 444 dns_name_split(dns_fixedname_name(&fnewname), sig.labels + 1, 445 NULL, dns_fixedname_name(&fnewname)); 446 447 dns_name_toregion(dns_fixedname_name(&fnewname), &r); 448 449 /* 450 * Create an envelope for each rdata: <name|type|class|ttl>. 451 */ 452 isc_buffer_init(&envbuf, data, sizeof(data)); 453 if (labels - sig.labels > 0) { 454 isc_buffer_putuint8(&envbuf, 1); 455 isc_buffer_putuint8(&envbuf, '*'); 456 memcpy(data + 2, r.base, r.length); 457 } 458 else 459 memcpy(data, r.base, r.length); 460 isc_buffer_add(&envbuf, r.length); 461 isc_buffer_putuint16(&envbuf, set->type); 462 isc_buffer_putuint16(&envbuf, set->rdclass); 463 isc_buffer_putuint32(&envbuf, sig.originalttl); 464 465 ret = rdataset_to_sortedarray(set, mctx, &rdatas, &nrdatas); 466 if (ret != ISC_R_SUCCESS) 467 goto cleanup_context; 468 469 isc_buffer_usedregion(&envbuf, &r); 470 471 for (i = 0; i < nrdatas; i++) { 472 isc_uint16_t len; 473 isc_buffer_t lenbuf; 474 isc_region_t lenr; 475 476 /* 477 * Skip duplicates. 478 */ 479 if (i > 0 && dns_rdata_compare(&rdatas[i], &rdatas[i-1]) == 0) 480 continue; 481 482 /* 483 * Digest the envelope. 484 */ 485 ret = dst_context_adddata(ctx, &r); 486 if (ret != ISC_R_SUCCESS) 487 goto cleanup_array; 488 489 /* 490 * Digest the rdata length. 491 */ 492 isc_buffer_init(&lenbuf, &len, sizeof(len)); 493 INSIST(rdatas[i].length < 65536); 494 isc_buffer_putuint16(&lenbuf, (isc_uint16_t)rdatas[i].length); 495 isc_buffer_usedregion(&lenbuf, &lenr); 496 497 /* 498 * Digest the rdata. 499 */ 500 ret = dst_context_adddata(ctx, &lenr); 501 if (ret != ISC_R_SUCCESS) 502 goto cleanup_array; 503 ret = dns_rdata_digest(&rdatas[i], digest_callback, ctx); 504 if (ret != ISC_R_SUCCESS) 505 goto cleanup_array; 506 } 507 508 r.base = sig.signature; 509 r.length = sig.siglen; 510 ret = dst_context_verify(ctx, &r); 511 if (ret == DST_R_VERIFYFAILURE) 512 ret = DNS_R_SIGINVALID; 513 514cleanup_array: 515 isc_mem_put(mctx, rdatas, nrdatas * sizeof(dns_rdata_t)); 516cleanup_context: 517 dst_context_destroy(&ctx); 518cleanup_struct: 519 dns_rdata_freestruct(&sig); 520 521 if (ret == ISC_R_SUCCESS && labels - sig.labels > 0) { 522 if (wild != NULL) 523 RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, 524 dns_fixedname_name(&fnewname), 525 wild, NULL) == ISC_R_SUCCESS); 526 ret = DNS_R_FROMWILDCARD; 527 } 528 return (ret); 529} 530 531isc_result_t 532dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, 533 isc_boolean_t ignoretime, isc_mem_t *mctx, 534 dns_rdata_t *sigrdata) 535{ 536 isc_result_t result; 537 538 result = dns_dnssec_verify2(name, set, key, ignoretime, mctx, 539 sigrdata, NULL); 540 if (result == DNS_R_FROMWILDCARD) 541 result = ISC_R_SUCCESS; 542 return (result); 543} 544 545static isc_boolean_t 546key_active(dst_key_t *key) { 547 isc_result_t result; 548 isc_stdtime_t now, publish, active, revoke, inactive, delete; 549 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; 550 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; 551 isc_boolean_t delset = ISC_FALSE; 552 int major, minor; 553 554 /* Is this an old-style key? */ 555 result = dst_key_getprivateformat(key, &major, &minor); 556 557 /* 558 * Smart signing started with key format 1.3; prior to that, all 559 * keys are assumed active 560 */ 561 if (major == 1 && minor <= 2) 562 return (ISC_TRUE); 563 564 isc_stdtime_get(&now); 565 566 result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish); 567 if (result == ISC_R_SUCCESS) 568 pubset = ISC_TRUE; 569 570 result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active); 571 if (result == ISC_R_SUCCESS) 572 actset = ISC_TRUE; 573 574 result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke); 575 if (result == ISC_R_SUCCESS) 576 revset = ISC_TRUE; 577 578 result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive); 579 if (result == ISC_R_SUCCESS) 580 inactset = ISC_TRUE; 581 582 result = dst_key_gettime(key, DST_TIME_DELETE, &delete); 583 if (result == ISC_R_SUCCESS) 584 delset = ISC_TRUE; 585 586 if ((inactset && inactive <= now) || (delset && delete <= now)) 587 return (ISC_FALSE); 588 589 if (revset && revoke <= now && pubset && publish <= now) 590 return (ISC_TRUE); 591 592 if (actset && active <= now) 593 return (ISC_TRUE); 594 595 return (ISC_FALSE); 596} 597 598#define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \ 599 == DNS_KEYOWNER_ZONE) 600 601isc_result_t 602dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, 603 dns_dbnode_t *node, dns_name_t *name, 604 const char *directory, isc_mem_t *mctx, 605 unsigned int maxkeys, dst_key_t **keys, 606 unsigned int *nkeys) 607{ 608 dns_rdataset_t rdataset; 609 dns_rdata_t rdata = DNS_RDATA_INIT; 610 isc_result_t result; 611 dst_key_t *pubkey = NULL; 612 unsigned int count = 0; 613 614 REQUIRE(nkeys != NULL); 615 REQUIRE(keys != NULL); 616 617 *nkeys = 0; 618 dns_rdataset_init(&rdataset); 619 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, 620 &rdataset, NULL)); 621 RETERR(dns_rdataset_first(&rdataset)); 622 while (result == ISC_R_SUCCESS && count < maxkeys) { 623 pubkey = NULL; 624 dns_rdataset_current(&rdataset, &rdata); 625 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey)); 626 if (!is_zone_key(pubkey) || 627 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) 628 goto next; 629 /* Corrupted .key file? */ 630 if (!dns_name_equal(name, dst_key_name(pubkey))) 631 goto next; 632 keys[count] = NULL; 633 result = dst_key_fromfile(dst_key_name(pubkey), 634 dst_key_id(pubkey), 635 dst_key_alg(pubkey), 636 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 637 directory, 638 mctx, &keys[count]); 639 640 /* 641 * If the key was revoked and the private file 642 * doesn't exist, maybe it was revoked internally 643 * by named. Try loading the unrevoked version. 644 */ 645 if (result == ISC_R_FILENOTFOUND) { 646 isc_uint32_t flags; 647 flags = dst_key_flags(pubkey); 648 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 649 dst_key_setflags(pubkey, 650 flags & ~DNS_KEYFLAG_REVOKE); 651 result = dst_key_fromfile(dst_key_name(pubkey), 652 dst_key_id(pubkey), 653 dst_key_alg(pubkey), 654 DST_TYPE_PUBLIC| 655 DST_TYPE_PRIVATE, 656 directory, 657 mctx, &keys[count]); 658 if (result == ISC_R_SUCCESS && 659 dst_key_pubcompare(pubkey, keys[count], 660 ISC_FALSE)) { 661 dst_key_setflags(keys[count], flags); 662 } 663 dst_key_setflags(pubkey, flags); 664 } 665 } 666 667 if (result != ISC_R_SUCCESS) { 668 char keybuf[DNS_NAME_FORMATSIZE]; 669 char algbuf[DNS_SECALG_FORMATSIZE]; 670 dns_name_format(dst_key_name(pubkey), keybuf, 671 sizeof(keybuf)); 672 dns_secalg_format(dst_key_alg(pubkey), algbuf, 673 sizeof(algbuf)); 674 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 675 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 676 "dns_dnssec_findzonekeys2: error " 677 "reading private key file %s/%s/%d: %s", 678 keybuf, algbuf, dst_key_id(pubkey), 679 isc_result_totext(result)); 680 } 681 682 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 683 keys[count] = pubkey; 684 pubkey = NULL; 685 count++; 686 goto next; 687 } 688 689 if (result != ISC_R_SUCCESS) 690 goto failure; 691 692 /* 693 * If a key is marked inactive, skip it 694 */ 695 if (!key_active(keys[count])) { 696 dst_key_free(&keys[count]); 697 keys[count] = pubkey; 698 pubkey = NULL; 699 count++; 700 goto next; 701 } 702 703 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) { 704 /* We should never get here. */ 705 dst_key_free(&keys[count]); 706 goto next; 707 } 708 count++; 709 next: 710 if (pubkey != NULL) 711 dst_key_free(&pubkey); 712 dns_rdata_reset(&rdata); 713 result = dns_rdataset_next(&rdataset); 714 } 715 if (result != ISC_R_NOMORE) 716 goto failure; 717 if (count == 0) 718 result = ISC_R_NOTFOUND; 719 else 720 result = ISC_R_SUCCESS; 721 722 failure: 723 if (dns_rdataset_isassociated(&rdataset)) 724 dns_rdataset_disassociate(&rdataset); 725 if (pubkey != NULL) 726 dst_key_free(&pubkey); 727 if (result != ISC_R_SUCCESS) 728 while (count > 0) 729 dst_key_free(&keys[--count]); 730 *nkeys = count; 731 return (result); 732} 733 734isc_result_t 735dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, 736 dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx, 737 unsigned int maxkeys, dst_key_t **keys, 738 unsigned int *nkeys) 739{ 740 return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx, 741 maxkeys, keys, nkeys)); 742} 743 744isc_result_t 745dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) { 746 dns_rdata_sig_t sig; /* SIG(0) */ 747 unsigned char data[512]; 748 unsigned char header[DNS_MESSAGE_HEADERLEN]; 749 isc_buffer_t headerbuf, databuf, sigbuf; 750 unsigned int sigsize; 751 isc_buffer_t *dynbuf = NULL; 752 dns_rdata_t *rdata; 753 dns_rdatalist_t *datalist; 754 dns_rdataset_t *dataset; 755 isc_region_t r; 756 isc_stdtime_t now; 757 dst_context_t *ctx = NULL; 758 isc_mem_t *mctx; 759 isc_result_t result; 760 isc_boolean_t signeedsfree = ISC_TRUE; 761 762 REQUIRE(msg != NULL); 763 REQUIRE(key != NULL); 764 765 if (is_response(msg)) 766 REQUIRE(msg->query.base != NULL); 767 768 mctx = msg->mctx; 769 770 memset(&sig, 0, sizeof(sig)); 771 772 sig.mctx = mctx; 773 sig.common.rdclass = dns_rdataclass_any; 774 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */ 775 ISC_LINK_INIT(&sig.common, link); 776 777 sig.covered = 0; 778 sig.algorithm = dst_key_alg(key); 779 sig.labels = 0; /* the root name */ 780 sig.originalttl = 0; 781 782 isc_stdtime_get(&now); 783 sig.timesigned = now - DNS_TSIG_FUDGE; 784 sig.timeexpire = now + DNS_TSIG_FUDGE; 785 786 sig.keyid = dst_key_id(key); 787 788 dns_name_init(&sig.signer, NULL); 789 dns_name_clone(dst_key_name(key), &sig.signer); 790 791 sig.siglen = 0; 792 sig.signature = NULL; 793 794 isc_buffer_init(&databuf, data, sizeof(data)); 795 796 RETERR(dst_context_create(key, mctx, &ctx)); 797 798 /* 799 * Digest the fields of the SIG - we can cheat and use 800 * dns_rdata_fromstruct. Since siglen is 0, the digested data 801 * is identical to dns format. 802 */ 803 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any, 804 dns_rdatatype_sig /* SIG(0) */, 805 &sig, &databuf)); 806 isc_buffer_usedregion(&databuf, &r); 807 RETERR(dst_context_adddata(ctx, &r)); 808 809 /* 810 * If this is a response, digest the query. 811 */ 812 if (is_response(msg)) 813 RETERR(dst_context_adddata(ctx, &msg->query)); 814 815 /* 816 * Digest the header. 817 */ 818 isc_buffer_init(&headerbuf, header, sizeof(header)); 819 dns_message_renderheader(msg, &headerbuf); 820 isc_buffer_usedregion(&headerbuf, &r); 821 RETERR(dst_context_adddata(ctx, &r)); 822 823 /* 824 * Digest the remainder of the message. 825 */ 826 isc_buffer_usedregion(msg->buffer, &r); 827 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 828 RETERR(dst_context_adddata(ctx, &r)); 829 830 RETERR(dst_key_sigsize(key, &sigsize)); 831 sig.siglen = sigsize; 832 sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen); 833 if (sig.signature == NULL) { 834 result = ISC_R_NOMEMORY; 835 goto failure; 836 } 837 838 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 839 RETERR(dst_context_sign(ctx, &sigbuf)); 840 dst_context_destroy(&ctx); 841 842 rdata = NULL; 843 RETERR(dns_message_gettemprdata(msg, &rdata)); 844 RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024)); 845 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any, 846 dns_rdatatype_sig /* SIG(0) */, 847 &sig, dynbuf)); 848 849 isc_mem_put(mctx, sig.signature, sig.siglen); 850 signeedsfree = ISC_FALSE; 851 852 dns_message_takebuffer(msg, &dynbuf); 853 854 datalist = NULL; 855 RETERR(dns_message_gettemprdatalist(msg, &datalist)); 856 datalist->rdclass = dns_rdataclass_any; 857 datalist->type = dns_rdatatype_sig; /* SIG(0) */ 858 datalist->covers = 0; 859 datalist->ttl = 0; 860 ISC_LIST_INIT(datalist->rdata); 861 ISC_LIST_APPEND(datalist->rdata, rdata, link); 862 dataset = NULL; 863 RETERR(dns_message_gettemprdataset(msg, &dataset)); 864 dns_rdataset_init(dataset); 865 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS); 866 msg->sig0 = dataset; 867 868 return (ISC_R_SUCCESS); 869 870failure: 871 if (dynbuf != NULL) 872 isc_buffer_free(&dynbuf); 873 if (signeedsfree) 874 isc_mem_put(mctx, sig.signature, sig.siglen); 875 if (ctx != NULL) 876 dst_context_destroy(&ctx); 877 878 return (result); 879} 880 881isc_result_t 882dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, 883 dst_key_t *key) 884{ 885 dns_rdata_sig_t sig; /* SIG(0) */ 886 unsigned char header[DNS_MESSAGE_HEADERLEN]; 887 dns_rdata_t rdata = DNS_RDATA_INIT; 888 isc_region_t r, source_r, sig_r, header_r; 889 isc_stdtime_t now; 890 dst_context_t *ctx = NULL; 891 isc_mem_t *mctx; 892 isc_result_t result; 893 isc_uint16_t addcount; 894 isc_boolean_t signeedsfree = ISC_FALSE; 895 896 REQUIRE(source != NULL); 897 REQUIRE(msg != NULL); 898 REQUIRE(key != NULL); 899 900 mctx = msg->mctx; 901 902 msg->verify_attempted = 1; 903 904 if (is_response(msg)) { 905 if (msg->query.base == NULL) 906 return (DNS_R_UNEXPECTEDTSIG); 907 } 908 909 isc_buffer_usedregion(source, &source_r); 910 911 RETERR(dns_rdataset_first(msg->sig0)); 912 dns_rdataset_current(msg->sig0, &rdata); 913 914 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL)); 915 signeedsfree = ISC_TRUE; 916 917 if (sig.labels != 0) { 918 result = DNS_R_SIGINVALID; 919 goto failure; 920 } 921 922 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) { 923 result = DNS_R_SIGINVALID; 924 msg->sig0status = dns_tsigerror_badtime; 925 goto failure; 926 } 927 928 isc_stdtime_get(&now); 929 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) { 930 result = DNS_R_SIGFUTURE; 931 msg->sig0status = dns_tsigerror_badtime; 932 goto failure; 933 } 934 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) { 935 result = DNS_R_SIGEXPIRED; 936 msg->sig0status = dns_tsigerror_badtime; 937 goto failure; 938 } 939 940 if (!dns_name_equal(dst_key_name(key), &sig.signer)) { 941 result = DNS_R_SIGINVALID; 942 msg->sig0status = dns_tsigerror_badkey; 943 goto failure; 944 } 945 946 RETERR(dst_context_create(key, mctx, &ctx)); 947 948 /* 949 * Digest the SIG(0) record, except for the signature. 950 */ 951 dns_rdata_toregion(&rdata, &r); 952 r.length -= sig.siglen; 953 RETERR(dst_context_adddata(ctx, &r)); 954 955 /* 956 * If this is a response, digest the query. 957 */ 958 if (is_response(msg)) 959 RETERR(dst_context_adddata(ctx, &msg->query)); 960 961 /* 962 * Extract the header. 963 */ 964 memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN); 965 966 /* 967 * Decrement the additional field counter. 968 */ 969 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 970 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); 971 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 972 973 /* 974 * Digest the modified header. 975 */ 976 header_r.base = (unsigned char *) header; 977 header_r.length = DNS_MESSAGE_HEADERLEN; 978 RETERR(dst_context_adddata(ctx, &header_r)); 979 980 /* 981 * Digest all non-SIG(0) records. 982 */ 983 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 984 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 985 RETERR(dst_context_adddata(ctx, &r)); 986 987 sig_r.base = sig.signature; 988 sig_r.length = sig.siglen; 989 result = dst_context_verify(ctx, &sig_r); 990 if (result != ISC_R_SUCCESS) { 991 msg->sig0status = dns_tsigerror_badsig; 992 goto failure; 993 } 994 995 msg->verified_sig = 1; 996 997 dst_context_destroy(&ctx); 998 dns_rdata_freestruct(&sig); 999 1000 return (ISC_R_SUCCESS); 1001 1002failure: 1003 if (signeedsfree) 1004 dns_rdata_freestruct(&sig); 1005 if (ctx != NULL) 1006 dst_context_destroy(&ctx); 1007 1008 return (result); 1009} 1010 1011/*% 1012 * Does this key ('rdata') self sign the rrset ('rdataset')? 1013 */ 1014isc_boolean_t 1015dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name, 1016 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1017 isc_boolean_t ignoretime, isc_mem_t *mctx) 1018{ 1019 dst_key_t *dstkey = NULL; 1020 dns_keytag_t keytag; 1021 dns_rdata_dnskey_t key; 1022 dns_rdata_rrsig_t sig; 1023 dns_rdata_t sigrdata = DNS_RDATA_INIT; 1024 isc_result_t result; 1025 1026 INSIST(rdataset->type == dns_rdatatype_key || 1027 rdataset->type == dns_rdatatype_dnskey); 1028 if (rdataset->type == dns_rdatatype_key) { 1029 INSIST(sigrdataset->type == dns_rdatatype_sig); 1030 INSIST(sigrdataset->covers == dns_rdatatype_key); 1031 } else { 1032 INSIST(sigrdataset->type == dns_rdatatype_rrsig); 1033 INSIST(sigrdataset->covers == dns_rdatatype_dnskey); 1034 } 1035 1036 result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey); 1037 if (result != ISC_R_SUCCESS) 1038 return (ISC_FALSE); 1039 result = dns_rdata_tostruct(rdata, &key, NULL); 1040 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1041 1042 keytag = dst_key_id(dstkey); 1043 for (result = dns_rdataset_first(sigrdataset); 1044 result == ISC_R_SUCCESS; 1045 result = dns_rdataset_next(sigrdataset)) 1046 { 1047 dns_rdata_reset(&sigrdata); 1048 dns_rdataset_current(sigrdataset, &sigrdata); 1049 result = dns_rdata_tostruct(&sigrdata, &sig, NULL); 1050 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1051 1052 if (sig.algorithm == key.algorithm && 1053 sig.keyid == keytag) { 1054 result = dns_dnssec_verify2(name, rdataset, dstkey, 1055 ignoretime, mctx, 1056 &sigrdata, NULL); 1057 if (result == ISC_R_SUCCESS) { 1058 dst_key_free(&dstkey); 1059 return (ISC_TRUE); 1060 } 1061 } 1062 } 1063 dst_key_free(&dstkey); 1064 return (ISC_FALSE); 1065} 1066 1067isc_result_t 1068dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, 1069 dns_dnsseckey_t **dkp) 1070{ 1071 isc_result_t result; 1072 dns_dnsseckey_t *dk; 1073 int major, minor; 1074 1075 REQUIRE(dkp != NULL && *dkp == NULL); 1076 dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t)); 1077 if (dk == NULL) 1078 return (ISC_R_NOMEMORY); 1079 1080 dk->key = *dstkey; 1081 *dstkey = NULL; 1082 dk->force_publish = ISC_FALSE; 1083 dk->force_sign = ISC_FALSE; 1084 dk->hint_publish = ISC_FALSE; 1085 dk->hint_sign = ISC_FALSE; 1086 dk->hint_remove = ISC_FALSE; 1087 dk->first_sign = ISC_FALSE; 1088 dk->is_active = ISC_FALSE; 1089 dk->prepublish = 0; 1090 dk->source = dns_keysource_unknown; 1091 dk->index = 0; 1092 1093 /* KSK or ZSK? */ 1094 dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0); 1095 1096 /* Is this an old-style key? */ 1097 result = dst_key_getprivateformat(dk->key, &major, &minor); 1098 1099 /* Smart signing started with key format 1.3 */ 1100 dk->legacy = ISC_TF(major == 1 && minor <= 2); 1101 1102 ISC_LINK_INIT(dk, link); 1103 *dkp = dk; 1104 return (ISC_R_SUCCESS); 1105} 1106 1107void 1108dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) { 1109 dns_dnsseckey_t *dk; 1110 1111 REQUIRE(dkp != NULL && *dkp != NULL); 1112 dk = *dkp; 1113 if (dk->key != NULL) 1114 dst_key_free(&dk->key); 1115 isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t)); 1116 *dkp = NULL; 1117} 1118 1119static void 1120get_hints(dns_dnsseckey_t *key) { 1121 isc_result_t result; 1122 isc_stdtime_t now, publish, active, revoke, inactive, delete; 1123 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; 1124 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; 1125 isc_boolean_t delset = ISC_FALSE; 1126 1127 REQUIRE(key != NULL && key->key != NULL); 1128 1129 isc_stdtime_get(&now); 1130 1131 result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish); 1132 if (result == ISC_R_SUCCESS) 1133 pubset = ISC_TRUE; 1134 1135 result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); 1136 if (result == ISC_R_SUCCESS) 1137 actset = ISC_TRUE; 1138 1139 result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke); 1140 if (result == ISC_R_SUCCESS) 1141 revset = ISC_TRUE; 1142 1143 result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive); 1144 if (result == ISC_R_SUCCESS) 1145 inactset = ISC_TRUE; 1146 1147 result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete); 1148 if (result == ISC_R_SUCCESS) 1149 delset = ISC_TRUE; 1150 1151 /* Metadata says publish (but possibly not activate) */ 1152 if (pubset && publish <= now) 1153 key->hint_publish = ISC_TRUE; 1154 1155 /* Metadata says activate (so we must also publish) */ 1156 if (actset && active <= now) { 1157 key->hint_sign = ISC_TRUE; 1158 key->hint_publish = ISC_TRUE; 1159 } 1160 1161 /* 1162 * Activation date is set (maybe in the future), but 1163 * publication date isn't. Most likely the user wants to 1164 * publish now and activate later. 1165 */ 1166 if (actset && !pubset) 1167 key->hint_publish = ISC_TRUE; 1168 1169 /* 1170 * If activation date is in the future, make note of how far off 1171 */ 1172 if (key->hint_publish && actset && active > now) { 1173 key->prepublish = active - now; 1174 } 1175 1176 /* 1177 * Key has been marked inactive: we can continue publishing, 1178 * but don't sign. 1179 */ 1180 if (key->hint_publish && inactset && inactive <= now) { 1181 key->hint_sign = ISC_FALSE; 1182 } 1183 1184 /* 1185 * Metadata says revoke. If the key is published, 1186 * we *have to* sign with it per RFC5011--even if it was 1187 * not active before. 1188 * 1189 * If it hasn't already been done, we should also revoke it now. 1190 */ 1191 if (key->hint_publish && (revset && revoke <= now)) { 1192 isc_uint32_t flags; 1193 key->hint_sign = ISC_TRUE; 1194 flags = dst_key_flags(key->key); 1195 if ((flags & DNS_KEYFLAG_REVOKE) == 0) { 1196 flags |= DNS_KEYFLAG_REVOKE; 1197 dst_key_setflags(key->key, flags); 1198 } 1199 } 1200 1201 /* 1202 * Metadata says delete, so don't publish this key or sign with it. 1203 */ 1204 if (delset && delete <= now) { 1205 key->hint_publish = ISC_FALSE; 1206 key->hint_sign = ISC_FALSE; 1207 key->hint_remove = ISC_TRUE; 1208 } 1209} 1210 1211/*% 1212 * Get a list of DNSSEC keys from the key repository 1213 */ 1214isc_result_t 1215dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, 1216 isc_mem_t *mctx, dns_dnsseckeylist_t *keylist) 1217{ 1218 isc_result_t result = ISC_R_SUCCESS; 1219 isc_boolean_t dir_open = ISC_FALSE; 1220 dns_dnsseckeylist_t list; 1221 isc_dir_t dir; 1222 dns_dnsseckey_t *key = NULL; 1223 dst_key_t *dstkey = NULL; 1224 char namebuf[DNS_NAME_FORMATSIZE], *p; 1225 isc_buffer_t b; 1226 unsigned int len; 1227 1228 REQUIRE(keylist != NULL); 1229 ISC_LIST_INIT(list); 1230 isc_dir_init(&dir); 1231 1232 isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1); 1233 RETERR(dns_name_totext(origin, ISC_FALSE, &b)); 1234 len = isc_buffer_usedlength(&b); 1235 namebuf[len] = '\0'; 1236 1237 if (directory == NULL) 1238 directory = "."; 1239 RETERR(isc_dir_open(&dir, directory)); 1240 dir_open = ISC_TRUE; 1241 1242 while (isc_dir_read(&dir) == ISC_R_SUCCESS) { 1243 if (dir.entry.name[0] == 'K' && 1244 dir.entry.length > len + 1 && 1245 dir.entry.name[len + 1] == '+' && 1246 strncasecmp(dir.entry.name + 1, namebuf, len) == 0) { 1247 p = strrchr(dir.entry.name, '.'); 1248 if (p != NULL && strcmp(p, ".private") != 0) 1249 continue; 1250 1251 dstkey = NULL; 1252 result = dst_key_fromnamedfile(dir.entry.name, 1253 directory, 1254 DST_TYPE_PUBLIC | 1255 DST_TYPE_PRIVATE, 1256 mctx, &dstkey); 1257 1258 if (result != ISC_R_SUCCESS) { 1259 isc_log_write(dns_lctx, 1260 DNS_LOGCATEGORY_GENERAL, 1261 DNS_LOGMODULE_DNSSEC, 1262 ISC_LOG_WARNING, 1263 "dns_dnssec_findmatchingkeys: " 1264 "error reading key file %s: %s", 1265 dir.entry.name, 1266 isc_result_totext(result)); 1267 continue; 1268 } 1269 1270 RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); 1271 key->source = dns_keysource_repository; 1272 get_hints(key); 1273 1274 if (key->legacy) { 1275 dns_dnsseckey_destroy(mctx, &key); 1276 } else { 1277 ISC_LIST_APPEND(list, key, link); 1278 key = NULL; 1279 } 1280 } 1281 } 1282 1283 if (!ISC_LIST_EMPTY(list)) 1284 ISC_LIST_APPENDLIST(*keylist, list, link); 1285 else 1286 result = ISC_R_NOTFOUND; 1287 1288 failure: 1289 if (dir_open) 1290 isc_dir_close(&dir); 1291 INSIST(key == NULL); 1292 while ((key = ISC_LIST_HEAD(list)) != NULL) { 1293 ISC_LIST_UNLINK(list, key, link); 1294 INSIST(key->key != NULL); 1295 dst_key_free(&key->key); 1296 dns_dnsseckey_destroy(mctx, &key); 1297 } 1298 if (dstkey != NULL) 1299 dst_key_free(&dstkey); 1300 return (result); 1301} 1302 1303/*% 1304 * Add 'newkey' to 'keylist' if it's not already there. 1305 * 1306 * If 'savekeys' is ISC_TRUE, then we need to preserve all 1307 * the keys in the keyset, regardless of whether they have 1308 * metadata indicating they should be deactivated or removed. 1309 */ 1310static void 1311addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey, 1312 isc_boolean_t savekeys, isc_mem_t *mctx) 1313{ 1314 dns_dnsseckey_t *key; 1315 1316 /* Skip duplicates */ 1317 for (key = ISC_LIST_HEAD(*keylist); 1318 key != NULL; 1319 key = ISC_LIST_NEXT(key, link)) { 1320 if (dst_key_id(key->key) == dst_key_id(*newkey) && 1321 dst_key_alg(key->key) == dst_key_alg(*newkey) && 1322 dns_name_equal(dst_key_name(key->key), 1323 dst_key_name(*newkey))) 1324 break; 1325 } 1326 1327 if (key != NULL) { 1328 /* 1329 * Found a match. If the old key was only public and the 1330 * new key is private, replace the old one; otherwise 1331 * leave it. But either way, mark the key as having 1332 * been found in the zone. 1333 */ 1334 if (dst_key_isprivate(key->key)) { 1335 dst_key_free(newkey); 1336 } else if (dst_key_isprivate(*newkey)) { 1337 dst_key_free(&key->key); 1338 key->key = *newkey; 1339 } 1340 1341 key->source = dns_keysource_zoneapex; 1342 return; 1343 } 1344 1345 dns_dnsseckey_create(mctx, newkey, &key); 1346 if (key->legacy || savekeys) { 1347 key->force_publish = ISC_TRUE; 1348 key->force_sign = dst_key_isprivate(key->key); 1349 } 1350 key->source = dns_keysource_zoneapex; 1351 ISC_LIST_APPEND(*keylist, key, link); 1352 *newkey = NULL; 1353} 1354 1355 1356/*% 1357 * Mark all keys which signed the DNSKEY/SOA RRsets as "active", 1358 * for future reference. 1359 */ 1360static isc_result_t 1361mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) { 1362 isc_result_t result = ISC_R_SUCCESS; 1363 dns_rdata_t rdata = DNS_RDATA_INIT; 1364 dns_rdataset_t sigs; 1365 dns_dnsseckey_t *key; 1366 1367 REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs)); 1368 1369 dns_rdataset_init(&sigs); 1370 dns_rdataset_clone(rrsigs, &sigs); 1371 for (key = ISC_LIST_HEAD(*keylist); 1372 key != NULL; 1373 key = ISC_LIST_NEXT(key, link)) { 1374 isc_uint16_t keyid, sigid; 1375 dns_secalg_t keyalg, sigalg; 1376 keyid = dst_key_id(key->key); 1377 keyalg = dst_key_alg(key->key); 1378 1379 for (result = dns_rdataset_first(&sigs); 1380 result == ISC_R_SUCCESS; 1381 result = dns_rdataset_next(&sigs)) { 1382 dns_rdata_rrsig_t sig; 1383 1384 dns_rdata_reset(&rdata); 1385 dns_rdataset_current(&sigs, &rdata); 1386 result = dns_rdata_tostruct(&rdata, &sig, NULL); 1387 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1388 sigalg = sig.algorithm; 1389 sigid = sig.keyid; 1390 if (keyid == sigid && keyalg == sigalg) { 1391 key->is_active = ISC_TRUE; 1392 break; 1393 } 1394 } 1395 } 1396 1397 if (result == ISC_R_NOMORE) 1398 result = ISC_R_SUCCESS; 1399 1400 if (dns_rdataset_isassociated(&sigs)) 1401 dns_rdataset_disassociate(&sigs); 1402 return (result); 1403} 1404 1405/*% 1406 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'. 1407 */ 1408isc_result_t 1409dns_dnssec_keylistfromrdataset(dns_name_t *origin, 1410 const char *directory, isc_mem_t *mctx, 1411 dns_rdataset_t *keyset, dns_rdataset_t *keysigs, 1412 dns_rdataset_t *soasigs, isc_boolean_t savekeys, 1413 isc_boolean_t public, 1414 dns_dnsseckeylist_t *keylist) 1415{ 1416 dns_rdataset_t keys; 1417 dns_rdata_t rdata = DNS_RDATA_INIT; 1418 dst_key_t *pubkey = NULL, *privkey = NULL; 1419 isc_result_t result; 1420 1421 REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset)); 1422 1423 dns_rdataset_init(&keys); 1424 1425 dns_rdataset_clone(keyset, &keys); 1426 for (result = dns_rdataset_first(&keys); 1427 result == ISC_R_SUCCESS; 1428 result = dns_rdataset_next(&keys)) { 1429 dns_rdata_reset(&rdata); 1430 dns_rdataset_current(&keys, &rdata); 1431 RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey)); 1432 1433 if (!is_zone_key(pubkey) || 1434 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) 1435 goto skip; 1436 1437 /* Corrupted .key file? */ 1438 if (!dns_name_equal(origin, dst_key_name(pubkey))) 1439 goto skip; 1440 1441 if (public) { 1442 addkey(keylist, &pubkey, savekeys, mctx); 1443 goto skip; 1444 } 1445 1446 result = dst_key_fromfile(dst_key_name(pubkey), 1447 dst_key_id(pubkey), 1448 dst_key_alg(pubkey), 1449 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 1450 directory, mctx, &privkey); 1451 1452 /* 1453 * If the key was revoked and the private file 1454 * doesn't exist, maybe it was revoked internally 1455 * by named. Try loading the unrevoked version. 1456 */ 1457 if (result == ISC_R_FILENOTFOUND) { 1458 isc_uint32_t flags; 1459 flags = dst_key_flags(pubkey); 1460 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 1461 dst_key_setflags(pubkey, 1462 flags & ~DNS_KEYFLAG_REVOKE); 1463 result = dst_key_fromfile(dst_key_name(pubkey), 1464 dst_key_id(pubkey), 1465 dst_key_alg(pubkey), 1466 DST_TYPE_PUBLIC| 1467 DST_TYPE_PRIVATE, 1468 directory, 1469 mctx, &privkey); 1470 if (result == ISC_R_SUCCESS && 1471 dst_key_pubcompare(pubkey, privkey, 1472 ISC_FALSE)) { 1473 dst_key_setflags(privkey, flags); 1474 } 1475 dst_key_setflags(pubkey, flags); 1476 } 1477 } 1478 1479 if (result != ISC_R_SUCCESS) { 1480 char keybuf[DNS_NAME_FORMATSIZE]; 1481 char algbuf[DNS_SECALG_FORMATSIZE]; 1482 dns_name_format(dst_key_name(pubkey), keybuf, 1483 sizeof(keybuf)); 1484 dns_secalg_format(dst_key_alg(pubkey), algbuf, 1485 sizeof(algbuf)); 1486 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 1487 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1488 "dns_dnssec_keylistfromrdataset: error " 1489 "reading private key file %s/%s/%d: %s", 1490 keybuf, algbuf, dst_key_id(pubkey), 1491 isc_result_totext(result)); 1492 } 1493 1494 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 1495 addkey(keylist, &pubkey, savekeys, mctx); 1496 goto skip; 1497 } 1498 RETERR(result); 1499 1500 /* This should never happen. */ 1501 if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) 1502 goto skip; 1503 1504 addkey(keylist, &privkey, savekeys, mctx); 1505 skip: 1506 if (pubkey != NULL) 1507 dst_key_free(&pubkey); 1508 if (privkey != NULL) 1509 dst_key_free(&privkey); 1510 } 1511 1512 if (result != ISC_R_NOMORE) 1513 RETERR(result); 1514 1515 if (keysigs != NULL && dns_rdataset_isassociated(keysigs)) 1516 RETERR(mark_active_keys(keylist, keysigs)); 1517 1518 if (soasigs != NULL && dns_rdataset_isassociated(soasigs)) 1519 RETERR(mark_active_keys(keylist, soasigs)); 1520 1521 result = ISC_R_SUCCESS; 1522 1523 failure: 1524 if (dns_rdataset_isassociated(&keys)) 1525 dns_rdataset_disassociate(&keys); 1526 if (pubkey != NULL) 1527 dst_key_free(&pubkey); 1528 if (privkey != NULL) 1529 dst_key_free(&privkey); 1530 return (result); 1531} 1532 1533static isc_result_t 1534make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, 1535 dns_rdata_t *target) 1536{ 1537 isc_result_t result; 1538 isc_buffer_t b; 1539 isc_region_t r; 1540 1541 isc_buffer_init(&b, buf, bufsize); 1542 result = dst_key_todns(key, &b); 1543 if (result != ISC_R_SUCCESS) 1544 return (result); 1545 1546 dns_rdata_reset(target); 1547 isc_buffer_usedregion(&b, &r); 1548 dns_rdata_fromregion(target, dst_key_class(key), 1549 dns_rdatatype_dnskey, &r); 1550 return (ISC_R_SUCCESS); 1551} 1552 1553static isc_result_t 1554publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, 1555 dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk, 1556 void (*report)(const char *, ...)) 1557{ 1558 isc_result_t result; 1559 dns_difftuple_t *tuple = NULL; 1560 unsigned char buf[DST_KEY_MAXSIZE]; 1561 dns_rdata_t dnskey = DNS_RDATA_INIT; 1562 char alg[80]; 1563 1564 dns_rdata_reset(&dnskey); 1565 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1566 1567 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); 1568 report("Fetching %s %d/%s from key %s.", 1569 key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK", 1570 dst_key_id(key->key), alg, 1571 key->source == dns_keysource_user ? "file" : "repository"); 1572 1573 if (key->prepublish && ttl > key->prepublish) { 1574 char keystr[DST_KEY_FORMATSIZE]; 1575 isc_stdtime_t now; 1576 1577 dst_key_format(key->key, keystr, sizeof(keystr)); 1578 report("Key %s: Delaying activation to match the DNSKEY TTL.\n", 1579 keystr, ttl); 1580 1581 isc_stdtime_get(&now); 1582 dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl); 1583 } 1584 1585 /* publish key */ 1586 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl, 1587 &dnskey, &tuple)); 1588 dns_diff_appendminimal(diff, &tuple); 1589 result = ISC_R_SUCCESS; 1590 1591 failure: 1592 return (result); 1593} 1594 1595static isc_result_t 1596remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, 1597 dns_ttl_t ttl, isc_mem_t *mctx, const char *reason, 1598 void (*report)(const char *, ...)) 1599{ 1600 isc_result_t result; 1601 dns_difftuple_t *tuple = NULL; 1602 unsigned char buf[DST_KEY_MAXSIZE]; 1603 dns_rdata_t dnskey = DNS_RDATA_INIT; 1604 char alg[80]; 1605 1606 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); 1607 report("Removing %s key %d/%s from DNSKEY RRset.", 1608 reason, dst_key_id(key->key), alg); 1609 1610 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1611 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey, 1612 &tuple)); 1613 dns_diff_appendminimal(diff, &tuple); 1614 result = ISC_R_SUCCESS; 1615 1616 failure: 1617 return (result); 1618} 1619 1620/* 1621 * Update 'keys' with information from 'newkeys'. 1622 * 1623 * If 'removed' is not NULL, any keys that are being removed from 1624 * the zone will be added to the list for post-removal processing. 1625 */ 1626isc_result_t 1627dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, 1628 dns_dnsseckeylist_t *removed, dns_name_t *origin, 1629 dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk, 1630 isc_mem_t *mctx, void (*report)(const char *, ...)) 1631{ 1632 isc_result_t result; 1633 dns_dnsseckey_t *key, *key1, *key2, *next; 1634 1635 /* 1636 * First, look through the existing key list to find keys 1637 * supplied from the command line which are not in the zone. 1638 * Update the zone to include them. 1639 */ 1640 for (key = ISC_LIST_HEAD(*keys); 1641 key != NULL; 1642 key = ISC_LIST_NEXT(key, link)) { 1643 if (key->source == dns_keysource_user && 1644 (key->hint_publish || key->force_publish)) { 1645 RETERR(publish_key(diff, key, origin, ttl, 1646 mctx, allzsk, report)); 1647 } 1648 } 1649 1650 /* 1651 * Second, scan the list of newly found keys looking for matches 1652 * with known keys, and update accordingly. 1653 */ 1654 for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) { 1655 isc_boolean_t key_revoked = ISC_FALSE; 1656 1657 next = ISC_LIST_NEXT(key1, link); 1658 1659 for (key2 = ISC_LIST_HEAD(*keys); 1660 key2 != NULL; 1661 key2 = ISC_LIST_NEXT(key2, link)) { 1662 if (dst_key_pubcompare(key1->key, key2->key, 1663 ISC_TRUE)) { 1664 int r1, r2; 1665 r1 = dst_key_flags(key1->key) & 1666 DNS_KEYFLAG_REVOKE; 1667 r2 = dst_key_flags(key2->key) & 1668 DNS_KEYFLAG_REVOKE; 1669 key_revoked = ISC_TF(r1 != r2); 1670 break; 1671 } 1672 } 1673 1674 /* No match found in keys; add the new key. */ 1675 if (key2 == NULL) { 1676 dns_dnsseckey_t *next; 1677 1678 next = ISC_LIST_NEXT(key1, link); 1679 ISC_LIST_UNLINK(*newkeys, key1, link); 1680 ISC_LIST_APPEND(*keys, key1, link); 1681 1682 if (key1->source != dns_keysource_zoneapex && 1683 (key1->hint_publish || key1->force_publish)) { 1684 RETERR(publish_key(diff, key1, origin, ttl, 1685 mctx, allzsk, report)); 1686 if (key1->hint_sign || key1->force_sign) 1687 key1->first_sign = ISC_TRUE; 1688 } 1689 1690 continue; 1691 } 1692 1693 /* Match found: remove or update it as needed */ 1694 if (key1->hint_remove) { 1695 RETERR(remove_key(diff, key2, origin, ttl, mctx, 1696 "expired", report)); 1697 ISC_LIST_UNLINK(*keys, key2, link); 1698 if (removed != NULL) 1699 ISC_LIST_APPEND(*removed, key2, link); 1700 else 1701 dns_dnsseckey_destroy(mctx, &key2); 1702 } else if (key_revoked && 1703 (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) { 1704 1705 /* 1706 * A previously valid key has been revoked. 1707 * We need to remove the old version and pull 1708 * in the new one. 1709 */ 1710 RETERR(remove_key(diff, key2, origin, ttl, mctx, 1711 "revoked", report)); 1712 ISC_LIST_UNLINK(*keys, key2, link); 1713 if (removed != NULL) 1714 ISC_LIST_APPEND(*removed, key2, link); 1715 else 1716 dns_dnsseckey_destroy(mctx, &key2); 1717 1718 RETERR(publish_key(diff, key1, origin, ttl, 1719 mctx, allzsk, report)); 1720 ISC_LIST_UNLINK(*newkeys, key1, link); 1721 ISC_LIST_APPEND(*keys, key1, link); 1722 1723 /* 1724 * XXX: The revoke flag is only defined for trust 1725 * anchors. Setting the flag on a non-KSK is legal, 1726 * but not defined in any RFC. It seems reasonable 1727 * to treat it the same as a KSK: keep it in the 1728 * zone, sign the DNSKEY set with it, but not 1729 * sign other records with it. 1730 */ 1731 key1->ksk = ISC_TRUE; 1732 continue; 1733 } else { 1734 if (!key2->is_active && 1735 (key1->hint_sign || key1->force_sign)) 1736 key2->first_sign = ISC_TRUE; 1737 key2->hint_sign = key1->hint_sign; 1738 key2->hint_publish = key1->hint_publish; 1739 } 1740 } 1741 1742 /* Free any leftover keys in newkeys */ 1743 while (!ISC_LIST_EMPTY(*newkeys)) { 1744 key1 = ISC_LIST_HEAD(*newkeys); 1745 ISC_LIST_UNLINK(*newkeys, key1, link); 1746 dns_dnsseckey_destroy(mctx, &key1); 1747 } 1748 1749 result = ISC_R_SUCCESS; 1750 1751 failure: 1752 return (result); 1753} 1754