1/* 2 * Copyright (C) 2004-2012 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$ 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, isc_stdtime_t now) { 547 isc_result_t result; 548 isc_stdtime_t 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 RUNTIME_CHECK(result == ISC_R_SUCCESS); 557 558 /* 559 * Smart signing started with key format 1.3; prior to that, all 560 * keys are assumed active 561 */ 562 if (major == 1 && minor <= 2) 563 return (ISC_TRUE); 564 565 result = dst_key_gettime(key, DST_TIME_PUBLISH, &publish); 566 if (result == ISC_R_SUCCESS) 567 pubset = ISC_TRUE; 568 569 result = dst_key_gettime(key, DST_TIME_ACTIVATE, &active); 570 if (result == ISC_R_SUCCESS) 571 actset = ISC_TRUE; 572 573 result = dst_key_gettime(key, DST_TIME_REVOKE, &revoke); 574 if (result == ISC_R_SUCCESS) 575 revset = ISC_TRUE; 576 577 result = dst_key_gettime(key, DST_TIME_INACTIVE, &inactive); 578 if (result == ISC_R_SUCCESS) 579 inactset = ISC_TRUE; 580 581 result = dst_key_gettime(key, DST_TIME_DELETE, &delete); 582 if (result == ISC_R_SUCCESS) 583 delset = ISC_TRUE; 584 585 if ((inactset && inactive <= now) || (delset && delete <= now)) 586 return (ISC_FALSE); 587 588 if (revset && revoke <= now && pubset && publish <= now) 589 return (ISC_TRUE); 590 591 if (actset && active <= now) 592 return (ISC_TRUE); 593 594 return (ISC_FALSE); 595} 596 597#define is_zone_key(key) ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) \ 598 == DNS_KEYOWNER_ZONE) 599 600isc_result_t 601dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, 602 dns_dbnode_t *node, dns_name_t *name, 603 const char *directory, isc_mem_t *mctx, 604 unsigned int maxkeys, dst_key_t **keys, 605 unsigned int *nkeys) 606{ 607 dns_rdataset_t rdataset; 608 dns_rdata_t rdata = DNS_RDATA_INIT; 609 isc_result_t result; 610 dst_key_t *pubkey = NULL; 611 unsigned int count = 0; 612 isc_stdtime_t now; 613 614 REQUIRE(nkeys != NULL); 615 REQUIRE(keys != NULL); 616 617 isc_stdtime_get(&now); 618 619 *nkeys = 0; 620 dns_rdataset_init(&rdataset); 621 RETERR(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, 622 &rdataset, NULL)); 623 RETERR(dns_rdataset_first(&rdataset)); 624 while (result == ISC_R_SUCCESS && count < maxkeys) { 625 pubkey = NULL; 626 dns_rdataset_current(&rdataset, &rdata); 627 RETERR(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey)); 628 if (!is_zone_key(pubkey) || 629 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) 630 goto next; 631 /* Corrupted .key file? */ 632 if (!dns_name_equal(name, dst_key_name(pubkey))) 633 goto next; 634 keys[count] = NULL; 635 result = dst_key_fromfile(dst_key_name(pubkey), 636 dst_key_id(pubkey), 637 dst_key_alg(pubkey), 638 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 639 directory, 640 mctx, &keys[count]); 641 642 /* 643 * If the key was revoked and the private file 644 * doesn't exist, maybe it was revoked internally 645 * by named. Try loading the unrevoked version. 646 */ 647 if (result == ISC_R_FILENOTFOUND) { 648 isc_uint32_t flags; 649 flags = dst_key_flags(pubkey); 650 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 651 dst_key_setflags(pubkey, 652 flags & ~DNS_KEYFLAG_REVOKE); 653 result = dst_key_fromfile(dst_key_name(pubkey), 654 dst_key_id(pubkey), 655 dst_key_alg(pubkey), 656 DST_TYPE_PUBLIC| 657 DST_TYPE_PRIVATE, 658 directory, 659 mctx, &keys[count]); 660 if (result == ISC_R_SUCCESS && 661 dst_key_pubcompare(pubkey, keys[count], 662 ISC_FALSE)) { 663 dst_key_setflags(keys[count], flags); 664 } 665 dst_key_setflags(pubkey, flags); 666 } 667 } 668 669 if (result != ISC_R_SUCCESS) { 670 char keybuf[DNS_NAME_FORMATSIZE]; 671 char algbuf[DNS_SECALG_FORMATSIZE]; 672 dns_name_format(dst_key_name(pubkey), keybuf, 673 sizeof(keybuf)); 674 dns_secalg_format(dst_key_alg(pubkey), algbuf, 675 sizeof(algbuf)); 676 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 677 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 678 "dns_dnssec_findzonekeys2: error " 679 "reading private key file %s/%s/%d: %s", 680 keybuf, algbuf, dst_key_id(pubkey), 681 isc_result_totext(result)); 682 } 683 684 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 685 keys[count] = pubkey; 686 pubkey = NULL; 687 count++; 688 goto next; 689 } 690 691 if (result != ISC_R_SUCCESS) 692 goto failure; 693 694 /* 695 * If a key is marked inactive, skip it 696 */ 697 if (!key_active(keys[count], now)) { 698 dst_key_free(&keys[count]); 699 keys[count] = pubkey; 700 pubkey = NULL; 701 count++; 702 goto next; 703 } 704 705 if ((dst_key_flags(keys[count]) & DNS_KEYTYPE_NOAUTH) != 0) { 706 /* We should never get here. */ 707 dst_key_free(&keys[count]); 708 goto next; 709 } 710 count++; 711 next: 712 if (pubkey != NULL) 713 dst_key_free(&pubkey); 714 dns_rdata_reset(&rdata); 715 result = dns_rdataset_next(&rdataset); 716 } 717 if (result != ISC_R_NOMORE) 718 goto failure; 719 if (count == 0) 720 result = ISC_R_NOTFOUND; 721 else 722 result = ISC_R_SUCCESS; 723 724 failure: 725 if (dns_rdataset_isassociated(&rdataset)) 726 dns_rdataset_disassociate(&rdataset); 727 if (pubkey != NULL) 728 dst_key_free(&pubkey); 729 if (result != ISC_R_SUCCESS) 730 while (count > 0) 731 dst_key_free(&keys[--count]); 732 *nkeys = count; 733 return (result); 734} 735 736isc_result_t 737dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, 738 dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx, 739 unsigned int maxkeys, dst_key_t **keys, 740 unsigned int *nkeys) 741{ 742 return (dns_dnssec_findzonekeys2(db, ver, node, name, NULL, mctx, 743 maxkeys, keys, nkeys)); 744} 745 746isc_result_t 747dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key) { 748 dns_rdata_sig_t sig; /* SIG(0) */ 749 unsigned char data[512]; 750 unsigned char header[DNS_MESSAGE_HEADERLEN]; 751 isc_buffer_t headerbuf, databuf, sigbuf; 752 unsigned int sigsize; 753 isc_buffer_t *dynbuf = NULL; 754 dns_rdata_t *rdata; 755 dns_rdatalist_t *datalist; 756 dns_rdataset_t *dataset; 757 isc_region_t r; 758 isc_stdtime_t now; 759 dst_context_t *ctx = NULL; 760 isc_mem_t *mctx; 761 isc_result_t result; 762 isc_boolean_t signeedsfree = ISC_TRUE; 763 764 REQUIRE(msg != NULL); 765 REQUIRE(key != NULL); 766 767 if (is_response(msg)) 768 REQUIRE(msg->query.base != NULL); 769 770 mctx = msg->mctx; 771 772 memset(&sig, 0, sizeof(sig)); 773 774 sig.mctx = mctx; 775 sig.common.rdclass = dns_rdataclass_any; 776 sig.common.rdtype = dns_rdatatype_sig; /* SIG(0) */ 777 ISC_LINK_INIT(&sig.common, link); 778 779 sig.covered = 0; 780 sig.algorithm = dst_key_alg(key); 781 sig.labels = 0; /* the root name */ 782 sig.originalttl = 0; 783 784 isc_stdtime_get(&now); 785 sig.timesigned = now - DNS_TSIG_FUDGE; 786 sig.timeexpire = now + DNS_TSIG_FUDGE; 787 788 sig.keyid = dst_key_id(key); 789 790 dns_name_init(&sig.signer, NULL); 791 dns_name_clone(dst_key_name(key), &sig.signer); 792 793 sig.siglen = 0; 794 sig.signature = NULL; 795 796 isc_buffer_init(&databuf, data, sizeof(data)); 797 798 RETERR(dst_context_create(key, mctx, &ctx)); 799 800 /* 801 * Digest the fields of the SIG - we can cheat and use 802 * dns_rdata_fromstruct. Since siglen is 0, the digested data 803 * is identical to dns format. 804 */ 805 RETERR(dns_rdata_fromstruct(NULL, dns_rdataclass_any, 806 dns_rdatatype_sig /* SIG(0) */, 807 &sig, &databuf)); 808 isc_buffer_usedregion(&databuf, &r); 809 RETERR(dst_context_adddata(ctx, &r)); 810 811 /* 812 * If this is a response, digest the query. 813 */ 814 if (is_response(msg)) 815 RETERR(dst_context_adddata(ctx, &msg->query)); 816 817 /* 818 * Digest the header. 819 */ 820 isc_buffer_init(&headerbuf, header, sizeof(header)); 821 dns_message_renderheader(msg, &headerbuf); 822 isc_buffer_usedregion(&headerbuf, &r); 823 RETERR(dst_context_adddata(ctx, &r)); 824 825 /* 826 * Digest the remainder of the message. 827 */ 828 isc_buffer_usedregion(msg->buffer, &r); 829 isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); 830 RETERR(dst_context_adddata(ctx, &r)); 831 832 RETERR(dst_key_sigsize(key, &sigsize)); 833 sig.siglen = sigsize; 834 sig.signature = (unsigned char *) isc_mem_get(mctx, sig.siglen); 835 if (sig.signature == NULL) { 836 result = ISC_R_NOMEMORY; 837 goto failure; 838 } 839 840 isc_buffer_init(&sigbuf, sig.signature, sig.siglen); 841 RETERR(dst_context_sign(ctx, &sigbuf)); 842 dst_context_destroy(&ctx); 843 844 rdata = NULL; 845 RETERR(dns_message_gettemprdata(msg, &rdata)); 846 RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 1024)); 847 RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any, 848 dns_rdatatype_sig /* SIG(0) */, 849 &sig, dynbuf)); 850 851 isc_mem_put(mctx, sig.signature, sig.siglen); 852 signeedsfree = ISC_FALSE; 853 854 dns_message_takebuffer(msg, &dynbuf); 855 856 datalist = NULL; 857 RETERR(dns_message_gettemprdatalist(msg, &datalist)); 858 datalist->rdclass = dns_rdataclass_any; 859 datalist->type = dns_rdatatype_sig; /* SIG(0) */ 860 datalist->covers = 0; 861 datalist->ttl = 0; 862 ISC_LIST_INIT(datalist->rdata); 863 ISC_LIST_APPEND(datalist->rdata, rdata, link); 864 dataset = NULL; 865 RETERR(dns_message_gettemprdataset(msg, &dataset)); 866 dns_rdataset_init(dataset); 867 RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS); 868 msg->sig0 = dataset; 869 870 return (ISC_R_SUCCESS); 871 872failure: 873 if (dynbuf != NULL) 874 isc_buffer_free(&dynbuf); 875 if (signeedsfree) 876 isc_mem_put(mctx, sig.signature, sig.siglen); 877 if (ctx != NULL) 878 dst_context_destroy(&ctx); 879 880 return (result); 881} 882 883isc_result_t 884dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg, 885 dst_key_t *key) 886{ 887 dns_rdata_sig_t sig; /* SIG(0) */ 888 unsigned char header[DNS_MESSAGE_HEADERLEN]; 889 dns_rdata_t rdata = DNS_RDATA_INIT; 890 isc_region_t r, source_r, sig_r, header_r; 891 isc_stdtime_t now; 892 dst_context_t *ctx = NULL; 893 isc_mem_t *mctx; 894 isc_result_t result; 895 isc_uint16_t addcount; 896 isc_boolean_t signeedsfree = ISC_FALSE; 897 898 REQUIRE(source != NULL); 899 REQUIRE(msg != NULL); 900 REQUIRE(key != NULL); 901 902 mctx = msg->mctx; 903 904 msg->verify_attempted = 1; 905 906 if (is_response(msg)) { 907 if (msg->query.base == NULL) 908 return (DNS_R_UNEXPECTEDTSIG); 909 } 910 911 isc_buffer_usedregion(source, &source_r); 912 913 RETERR(dns_rdataset_first(msg->sig0)); 914 dns_rdataset_current(msg->sig0, &rdata); 915 916 RETERR(dns_rdata_tostruct(&rdata, &sig, NULL)); 917 signeedsfree = ISC_TRUE; 918 919 if (sig.labels != 0) { 920 result = DNS_R_SIGINVALID; 921 goto failure; 922 } 923 924 if (isc_serial_lt(sig.timeexpire, sig.timesigned)) { 925 result = DNS_R_SIGINVALID; 926 msg->sig0status = dns_tsigerror_badtime; 927 goto failure; 928 } 929 930 isc_stdtime_get(&now); 931 if (isc_serial_lt((isc_uint32_t)now, sig.timesigned)) { 932 result = DNS_R_SIGFUTURE; 933 msg->sig0status = dns_tsigerror_badtime; 934 goto failure; 935 } 936 else if (isc_serial_lt(sig.timeexpire, (isc_uint32_t)now)) { 937 result = DNS_R_SIGEXPIRED; 938 msg->sig0status = dns_tsigerror_badtime; 939 goto failure; 940 } 941 942 if (!dns_name_equal(dst_key_name(key), &sig.signer)) { 943 result = DNS_R_SIGINVALID; 944 msg->sig0status = dns_tsigerror_badkey; 945 goto failure; 946 } 947 948 RETERR(dst_context_create(key, mctx, &ctx)); 949 950 /* 951 * Digest the SIG(0) record, except for the signature. 952 */ 953 dns_rdata_toregion(&rdata, &r); 954 r.length -= sig.siglen; 955 RETERR(dst_context_adddata(ctx, &r)); 956 957 /* 958 * If this is a response, digest the query. 959 */ 960 if (is_response(msg)) 961 RETERR(dst_context_adddata(ctx, &msg->query)); 962 963 /* 964 * Extract the header. 965 */ 966 memcpy(header, source_r.base, DNS_MESSAGE_HEADERLEN); 967 968 /* 969 * Decrement the additional field counter. 970 */ 971 memcpy(&addcount, &header[DNS_MESSAGE_HEADERLEN - 2], 2); 972 addcount = htons((isc_uint16_t)(ntohs(addcount) - 1)); 973 memcpy(&header[DNS_MESSAGE_HEADERLEN - 2], &addcount, 2); 974 975 /* 976 * Digest the modified header. 977 */ 978 header_r.base = (unsigned char *) header; 979 header_r.length = DNS_MESSAGE_HEADERLEN; 980 RETERR(dst_context_adddata(ctx, &header_r)); 981 982 /* 983 * Digest all non-SIG(0) records. 984 */ 985 r.base = source_r.base + DNS_MESSAGE_HEADERLEN; 986 r.length = msg->sigstart - DNS_MESSAGE_HEADERLEN; 987 RETERR(dst_context_adddata(ctx, &r)); 988 989 sig_r.base = sig.signature; 990 sig_r.length = sig.siglen; 991 result = dst_context_verify(ctx, &sig_r); 992 if (result != ISC_R_SUCCESS) { 993 msg->sig0status = dns_tsigerror_badsig; 994 goto failure; 995 } 996 997 msg->verified_sig = 1; 998 999 dst_context_destroy(&ctx); 1000 dns_rdata_freestruct(&sig); 1001 1002 return (ISC_R_SUCCESS); 1003 1004failure: 1005 if (signeedsfree) 1006 dns_rdata_freestruct(&sig); 1007 if (ctx != NULL) 1008 dst_context_destroy(&ctx); 1009 1010 return (result); 1011} 1012 1013/*% 1014 * Does this key ('rdata') self sign the rrset ('rdataset')? 1015 */ 1016isc_boolean_t 1017dns_dnssec_selfsigns(dns_rdata_t *rdata, dns_name_t *name, 1018 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1019 isc_boolean_t ignoretime, isc_mem_t *mctx) 1020{ 1021 INSIST(rdataset->type == dns_rdatatype_key || 1022 rdataset->type == dns_rdatatype_dnskey); 1023 if (rdataset->type == dns_rdatatype_key) { 1024 INSIST(sigrdataset->type == dns_rdatatype_sig); 1025 INSIST(sigrdataset->covers == dns_rdatatype_key); 1026 } else { 1027 INSIST(sigrdataset->type == dns_rdatatype_rrsig); 1028 INSIST(sigrdataset->covers == dns_rdatatype_dnskey); 1029 } 1030 1031 return (dns_dnssec_signs(rdata, name, rdataset, sigrdataset, 1032 ignoretime, mctx)); 1033 1034} 1035 1036isc_boolean_t 1037dns_dnssec_signs(dns_rdata_t *rdata, dns_name_t *name, 1038 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1039 isc_boolean_t ignoretime, isc_mem_t *mctx) 1040{ 1041 dst_key_t *dstkey = NULL; 1042 dns_keytag_t keytag; 1043 dns_rdata_dnskey_t key; 1044 dns_rdata_rrsig_t sig; 1045 dns_rdata_t sigrdata = DNS_RDATA_INIT; 1046 isc_result_t result; 1047 1048 INSIST(sigrdataset->type == dns_rdatatype_rrsig); 1049 if (sigrdataset->covers != rdataset->type) 1050 return (ISC_FALSE); 1051 1052 result = dns_dnssec_keyfromrdata(name, rdata, mctx, &dstkey); 1053 if (result != ISC_R_SUCCESS) 1054 return (ISC_FALSE); 1055 result = dns_rdata_tostruct(rdata, &key, NULL); 1056 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1057 1058 keytag = dst_key_id(dstkey); 1059 for (result = dns_rdataset_first(sigrdataset); 1060 result == ISC_R_SUCCESS; 1061 result = dns_rdataset_next(sigrdataset)) 1062 { 1063 dns_rdata_reset(&sigrdata); 1064 dns_rdataset_current(sigrdataset, &sigrdata); 1065 result = dns_rdata_tostruct(&sigrdata, &sig, NULL); 1066 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1067 1068 if (sig.algorithm == key.algorithm && 1069 sig.keyid == keytag) { 1070 result = dns_dnssec_verify2(name, rdataset, dstkey, 1071 ignoretime, mctx, 1072 &sigrdata, NULL); 1073 if (result == ISC_R_SUCCESS) { 1074 dst_key_free(&dstkey); 1075 return (ISC_TRUE); 1076 } 1077 } 1078 } 1079 dst_key_free(&dstkey); 1080 return (ISC_FALSE); 1081} 1082 1083isc_result_t 1084dns_dnsseckey_create(isc_mem_t *mctx, dst_key_t **dstkey, 1085 dns_dnsseckey_t **dkp) 1086{ 1087 isc_result_t result; 1088 dns_dnsseckey_t *dk; 1089 int major, minor; 1090 1091 REQUIRE(dkp != NULL && *dkp == NULL); 1092 dk = isc_mem_get(mctx, sizeof(dns_dnsseckey_t)); 1093 if (dk == NULL) 1094 return (ISC_R_NOMEMORY); 1095 1096 dk->key = *dstkey; 1097 *dstkey = NULL; 1098 dk->force_publish = ISC_FALSE; 1099 dk->force_sign = ISC_FALSE; 1100 dk->hint_publish = ISC_FALSE; 1101 dk->hint_sign = ISC_FALSE; 1102 dk->hint_remove = ISC_FALSE; 1103 dk->first_sign = ISC_FALSE; 1104 dk->is_active = ISC_FALSE; 1105 dk->prepublish = 0; 1106 dk->source = dns_keysource_unknown; 1107 dk->index = 0; 1108 1109 /* KSK or ZSK? */ 1110 dk->ksk = ISC_TF((dst_key_flags(dk->key) & DNS_KEYFLAG_KSK) != 0); 1111 1112 /* Is this an old-style key? */ 1113 result = dst_key_getprivateformat(dk->key, &major, &minor); 1114 INSIST(result == ISC_R_SUCCESS); 1115 1116 /* Smart signing started with key format 1.3 */ 1117 dk->legacy = ISC_TF(major == 1 && minor <= 2); 1118 1119 ISC_LINK_INIT(dk, link); 1120 *dkp = dk; 1121 return (ISC_R_SUCCESS); 1122} 1123 1124void 1125dns_dnsseckey_destroy(isc_mem_t *mctx, dns_dnsseckey_t **dkp) { 1126 dns_dnsseckey_t *dk; 1127 1128 REQUIRE(dkp != NULL && *dkp != NULL); 1129 dk = *dkp; 1130 if (dk->key != NULL) 1131 dst_key_free(&dk->key); 1132 isc_mem_put(mctx, dk, sizeof(dns_dnsseckey_t)); 1133 *dkp = NULL; 1134} 1135 1136static void 1137get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) { 1138 isc_result_t result; 1139 isc_stdtime_t publish, active, revoke, inactive, delete; 1140 isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; 1141 isc_boolean_t revset = ISC_FALSE, inactset = ISC_FALSE; 1142 isc_boolean_t delset = ISC_FALSE; 1143 1144 REQUIRE(key != NULL && key->key != NULL); 1145 1146 result = dst_key_gettime(key->key, DST_TIME_PUBLISH, &publish); 1147 if (result == ISC_R_SUCCESS) 1148 pubset = ISC_TRUE; 1149 1150 result = dst_key_gettime(key->key, DST_TIME_ACTIVATE, &active); 1151 if (result == ISC_R_SUCCESS) 1152 actset = ISC_TRUE; 1153 1154 result = dst_key_gettime(key->key, DST_TIME_REVOKE, &revoke); 1155 if (result == ISC_R_SUCCESS) 1156 revset = ISC_TRUE; 1157 1158 result = dst_key_gettime(key->key, DST_TIME_INACTIVE, &inactive); 1159 if (result == ISC_R_SUCCESS) 1160 inactset = ISC_TRUE; 1161 1162 result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete); 1163 if (result == ISC_R_SUCCESS) 1164 delset = ISC_TRUE; 1165 1166 /* Metadata says publish (but possibly not activate) */ 1167 if (pubset && publish <= now) 1168 key->hint_publish = ISC_TRUE; 1169 1170 /* Metadata says activate (so we must also publish) */ 1171 if (actset && active <= now) { 1172 key->hint_sign = ISC_TRUE; 1173 key->hint_publish = ISC_TRUE; 1174 } 1175 1176 /* 1177 * Activation date is set (maybe in the future), but 1178 * publication date isn't. Most likely the user wants to 1179 * publish now and activate later. 1180 */ 1181 if (actset && !pubset) 1182 key->hint_publish = ISC_TRUE; 1183 1184 /* 1185 * If activation date is in the future, make note of how far off 1186 */ 1187 if (key->hint_publish && actset && active > now) { 1188 key->prepublish = active - now; 1189 } 1190 1191 /* 1192 * Key has been marked inactive: we can continue publishing, 1193 * but don't sign. 1194 */ 1195 if (key->hint_publish && inactset && inactive <= now) { 1196 key->hint_sign = ISC_FALSE; 1197 } 1198 1199 /* 1200 * Metadata says revoke. If the key is published, 1201 * we *have to* sign with it per RFC5011--even if it was 1202 * not active before. 1203 * 1204 * If it hasn't already been done, we should also revoke it now. 1205 */ 1206 if (key->hint_publish && (revset && revoke <= now)) { 1207 isc_uint32_t flags; 1208 key->hint_sign = ISC_TRUE; 1209 flags = dst_key_flags(key->key); 1210 if ((flags & DNS_KEYFLAG_REVOKE) == 0) { 1211 flags |= DNS_KEYFLAG_REVOKE; 1212 dst_key_setflags(key->key, flags); 1213 } 1214 } 1215 1216 /* 1217 * Metadata says delete, so don't publish this key or sign with it. 1218 */ 1219 if (delset && delete <= now) { 1220 key->hint_publish = ISC_FALSE; 1221 key->hint_sign = ISC_FALSE; 1222 key->hint_remove = ISC_TRUE; 1223 } 1224} 1225 1226/*% 1227 * Get a list of DNSSEC keys from the key repository 1228 */ 1229isc_result_t 1230dns_dnssec_findmatchingkeys(dns_name_t *origin, const char *directory, 1231 isc_mem_t *mctx, dns_dnsseckeylist_t *keylist) 1232{ 1233 isc_result_t result = ISC_R_SUCCESS; 1234 isc_boolean_t dir_open = ISC_FALSE; 1235 dns_dnsseckeylist_t list; 1236 isc_dir_t dir; 1237 dns_dnsseckey_t *key = NULL; 1238 dst_key_t *dstkey = NULL; 1239 char namebuf[DNS_NAME_FORMATSIZE], *p; 1240 isc_buffer_t b; 1241 unsigned int len; 1242 isc_stdtime_t now; 1243 1244 REQUIRE(keylist != NULL); 1245 ISC_LIST_INIT(list); 1246 isc_dir_init(&dir); 1247 1248 isc_buffer_init(&b, namebuf, sizeof(namebuf) - 1); 1249 RETERR(dns_name_tofilenametext(origin, ISC_FALSE, &b)); 1250 len = isc_buffer_usedlength(&b); 1251 namebuf[len] = '\0'; 1252 1253 if (directory == NULL) 1254 directory = "."; 1255 RETERR(isc_dir_open(&dir, directory)); 1256 dir_open = ISC_TRUE; 1257 1258 isc_stdtime_get(&now); 1259 1260 while (isc_dir_read(&dir) == ISC_R_SUCCESS) { 1261 if (dir.entry.name[0] == 'K' && 1262 dir.entry.length > len + 1 && 1263 dir.entry.name[len + 1] == '+' && 1264 strncasecmp(dir.entry.name + 1, namebuf, len) == 0) { 1265 p = strrchr(dir.entry.name, '.'); 1266 if (p != NULL && strcmp(p, ".private") != 0) 1267 continue; 1268 1269 dstkey = NULL; 1270 result = dst_key_fromnamedfile(dir.entry.name, 1271 directory, 1272 DST_TYPE_PUBLIC | 1273 DST_TYPE_PRIVATE, 1274 mctx, &dstkey); 1275 1276 if (result != ISC_R_SUCCESS) { 1277 isc_log_write(dns_lctx, 1278 DNS_LOGCATEGORY_GENERAL, 1279 DNS_LOGMODULE_DNSSEC, 1280 ISC_LOG_WARNING, 1281 "dns_dnssec_findmatchingkeys: " 1282 "error reading key file %s: %s", 1283 dir.entry.name, 1284 isc_result_totext(result)); 1285 continue; 1286 } 1287 1288 RETERR(dns_dnsseckey_create(mctx, &dstkey, &key)); 1289 key->source = dns_keysource_repository; 1290 get_hints(key, now); 1291 1292 if (key->legacy) { 1293 dns_dnsseckey_destroy(mctx, &key); 1294 } else { 1295 ISC_LIST_APPEND(list, key, link); 1296 key = NULL; 1297 } 1298 } 1299 } 1300 1301 if (!ISC_LIST_EMPTY(list)) 1302 ISC_LIST_APPENDLIST(*keylist, list, link); 1303 else 1304 result = ISC_R_NOTFOUND; 1305 1306 failure: 1307 if (dir_open) 1308 isc_dir_close(&dir); 1309 INSIST(key == NULL); 1310 while ((key = ISC_LIST_HEAD(list)) != NULL) { 1311 ISC_LIST_UNLINK(list, key, link); 1312 INSIST(key->key != NULL); 1313 dst_key_free(&key->key); 1314 dns_dnsseckey_destroy(mctx, &key); 1315 } 1316 if (dstkey != NULL) 1317 dst_key_free(&dstkey); 1318 return (result); 1319} 1320 1321/*% 1322 * Add 'newkey' to 'keylist' if it's not already there. 1323 * 1324 * If 'savekeys' is ISC_TRUE, then we need to preserve all 1325 * the keys in the keyset, regardless of whether they have 1326 * metadata indicating they should be deactivated or removed. 1327 */ 1328static void 1329addkey(dns_dnsseckeylist_t *keylist, dst_key_t **newkey, 1330 isc_boolean_t savekeys, isc_mem_t *mctx) 1331{ 1332 dns_dnsseckey_t *key; 1333 1334 /* Skip duplicates */ 1335 for (key = ISC_LIST_HEAD(*keylist); 1336 key != NULL; 1337 key = ISC_LIST_NEXT(key, link)) { 1338 if (dst_key_id(key->key) == dst_key_id(*newkey) && 1339 dst_key_alg(key->key) == dst_key_alg(*newkey) && 1340 dns_name_equal(dst_key_name(key->key), 1341 dst_key_name(*newkey))) 1342 break; 1343 } 1344 1345 if (key != NULL) { 1346 /* 1347 * Found a match. If the old key was only public and the 1348 * new key is private, replace the old one; otherwise 1349 * leave it. But either way, mark the key as having 1350 * been found in the zone. 1351 */ 1352 if (dst_key_isprivate(key->key)) { 1353 dst_key_free(newkey); 1354 } else if (dst_key_isprivate(*newkey)) { 1355 dst_key_free(&key->key); 1356 key->key = *newkey; 1357 } 1358 1359 key->source = dns_keysource_zoneapex; 1360 return; 1361 } 1362 1363 dns_dnsseckey_create(mctx, newkey, &key); 1364 if (key->legacy || savekeys) { 1365 key->force_publish = ISC_TRUE; 1366 key->force_sign = dst_key_isprivate(key->key); 1367 } 1368 key->source = dns_keysource_zoneapex; 1369 ISC_LIST_APPEND(*keylist, key, link); 1370 *newkey = NULL; 1371} 1372 1373 1374/*% 1375 * Mark all keys which signed the DNSKEY/SOA RRsets as "active", 1376 * for future reference. 1377 */ 1378static isc_result_t 1379mark_active_keys(dns_dnsseckeylist_t *keylist, dns_rdataset_t *rrsigs) { 1380 isc_result_t result = ISC_R_SUCCESS; 1381 dns_rdata_t rdata = DNS_RDATA_INIT; 1382 dns_rdataset_t sigs; 1383 dns_dnsseckey_t *key; 1384 1385 REQUIRE(rrsigs != NULL && dns_rdataset_isassociated(rrsigs)); 1386 1387 dns_rdataset_init(&sigs); 1388 dns_rdataset_clone(rrsigs, &sigs); 1389 for (key = ISC_LIST_HEAD(*keylist); 1390 key != NULL; 1391 key = ISC_LIST_NEXT(key, link)) { 1392 isc_uint16_t keyid, sigid; 1393 dns_secalg_t keyalg, sigalg; 1394 keyid = dst_key_id(key->key); 1395 keyalg = dst_key_alg(key->key); 1396 1397 for (result = dns_rdataset_first(&sigs); 1398 result == ISC_R_SUCCESS; 1399 result = dns_rdataset_next(&sigs)) { 1400 dns_rdata_rrsig_t sig; 1401 1402 dns_rdata_reset(&rdata); 1403 dns_rdataset_current(&sigs, &rdata); 1404 result = dns_rdata_tostruct(&rdata, &sig, NULL); 1405 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1406 sigalg = sig.algorithm; 1407 sigid = sig.keyid; 1408 if (keyid == sigid && keyalg == sigalg) { 1409 key->is_active = ISC_TRUE; 1410 break; 1411 } 1412 } 1413 } 1414 1415 if (result == ISC_R_NOMORE) 1416 result = ISC_R_SUCCESS; 1417 1418 if (dns_rdataset_isassociated(&sigs)) 1419 dns_rdataset_disassociate(&sigs); 1420 return (result); 1421} 1422 1423/*% 1424 * Add the contents of a DNSKEY rdataset 'keyset' to 'keylist'. 1425 */ 1426isc_result_t 1427dns_dnssec_keylistfromrdataset(dns_name_t *origin, 1428 const char *directory, isc_mem_t *mctx, 1429 dns_rdataset_t *keyset, dns_rdataset_t *keysigs, 1430 dns_rdataset_t *soasigs, isc_boolean_t savekeys, 1431 isc_boolean_t public, 1432 dns_dnsseckeylist_t *keylist) 1433{ 1434 dns_rdataset_t keys; 1435 dns_rdata_t rdata = DNS_RDATA_INIT; 1436 dst_key_t *pubkey = NULL, *privkey = NULL; 1437 isc_result_t result; 1438 1439 REQUIRE(keyset != NULL && dns_rdataset_isassociated(keyset)); 1440 1441 dns_rdataset_init(&keys); 1442 1443 dns_rdataset_clone(keyset, &keys); 1444 for (result = dns_rdataset_first(&keys); 1445 result == ISC_R_SUCCESS; 1446 result = dns_rdataset_next(&keys)) { 1447 dns_rdata_reset(&rdata); 1448 dns_rdataset_current(&keys, &rdata); 1449 RETERR(dns_dnssec_keyfromrdata(origin, &rdata, mctx, &pubkey)); 1450 1451 if (!is_zone_key(pubkey) || 1452 (dst_key_flags(pubkey) & DNS_KEYTYPE_NOAUTH) != 0) 1453 goto skip; 1454 1455 /* Corrupted .key file? */ 1456 if (!dns_name_equal(origin, dst_key_name(pubkey))) 1457 goto skip; 1458 1459 if (public) { 1460 addkey(keylist, &pubkey, savekeys, mctx); 1461 goto skip; 1462 } 1463 1464 result = dst_key_fromfile(dst_key_name(pubkey), 1465 dst_key_id(pubkey), 1466 dst_key_alg(pubkey), 1467 DST_TYPE_PUBLIC|DST_TYPE_PRIVATE, 1468 directory, mctx, &privkey); 1469 1470 /* 1471 * If the key was revoked and the private file 1472 * doesn't exist, maybe it was revoked internally 1473 * by named. Try loading the unrevoked version. 1474 */ 1475 if (result == ISC_R_FILENOTFOUND) { 1476 isc_uint32_t flags; 1477 flags = dst_key_flags(pubkey); 1478 if ((flags & DNS_KEYFLAG_REVOKE) != 0) { 1479 dst_key_setflags(pubkey, 1480 flags & ~DNS_KEYFLAG_REVOKE); 1481 result = dst_key_fromfile(dst_key_name(pubkey), 1482 dst_key_id(pubkey), 1483 dst_key_alg(pubkey), 1484 DST_TYPE_PUBLIC| 1485 DST_TYPE_PRIVATE, 1486 directory, 1487 mctx, &privkey); 1488 if (result == ISC_R_SUCCESS && 1489 dst_key_pubcompare(pubkey, privkey, 1490 ISC_FALSE)) { 1491 dst_key_setflags(privkey, flags); 1492 } 1493 dst_key_setflags(pubkey, flags); 1494 } 1495 } 1496 1497 if (result != ISC_R_SUCCESS) { 1498 char keybuf[DNS_NAME_FORMATSIZE]; 1499 char algbuf[DNS_SECALG_FORMATSIZE]; 1500 dns_name_format(dst_key_name(pubkey), keybuf, 1501 sizeof(keybuf)); 1502 dns_secalg_format(dst_key_alg(pubkey), algbuf, 1503 sizeof(algbuf)); 1504 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, 1505 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING, 1506 "dns_dnssec_keylistfromrdataset: error " 1507 "reading private key file %s/%s/%d: %s", 1508 keybuf, algbuf, dst_key_id(pubkey), 1509 isc_result_totext(result)); 1510 } 1511 1512 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) { 1513 addkey(keylist, &pubkey, savekeys, mctx); 1514 goto skip; 1515 } 1516 RETERR(result); 1517 1518 /* This should never happen. */ 1519 if ((dst_key_flags(privkey) & DNS_KEYTYPE_NOAUTH) != 0) 1520 goto skip; 1521 1522 addkey(keylist, &privkey, savekeys, mctx); 1523 skip: 1524 if (pubkey != NULL) 1525 dst_key_free(&pubkey); 1526 if (privkey != NULL) 1527 dst_key_free(&privkey); 1528 } 1529 1530 if (result != ISC_R_NOMORE) 1531 RETERR(result); 1532 1533 if (keysigs != NULL && dns_rdataset_isassociated(keysigs)) 1534 RETERR(mark_active_keys(keylist, keysigs)); 1535 1536 if (soasigs != NULL && dns_rdataset_isassociated(soasigs)) 1537 RETERR(mark_active_keys(keylist, soasigs)); 1538 1539 result = ISC_R_SUCCESS; 1540 1541 failure: 1542 if (dns_rdataset_isassociated(&keys)) 1543 dns_rdataset_disassociate(&keys); 1544 if (pubkey != NULL) 1545 dst_key_free(&pubkey); 1546 if (privkey != NULL) 1547 dst_key_free(&privkey); 1548 return (result); 1549} 1550 1551static isc_result_t 1552make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize, 1553 dns_rdata_t *target) 1554{ 1555 isc_result_t result; 1556 isc_buffer_t b; 1557 isc_region_t r; 1558 1559 isc_buffer_init(&b, buf, bufsize); 1560 result = dst_key_todns(key, &b); 1561 if (result != ISC_R_SUCCESS) 1562 return (result); 1563 1564 dns_rdata_reset(target); 1565 isc_buffer_usedregion(&b, &r); 1566 dns_rdata_fromregion(target, dst_key_class(key), 1567 dns_rdatatype_dnskey, &r); 1568 return (ISC_R_SUCCESS); 1569} 1570 1571static isc_result_t 1572publish_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, 1573 dns_ttl_t ttl, isc_mem_t *mctx, isc_boolean_t allzsk, 1574 void (*report)(const char *, ...)) 1575{ 1576 isc_result_t result; 1577 dns_difftuple_t *tuple = NULL; 1578 unsigned char buf[DST_KEY_MAXSIZE]; 1579 dns_rdata_t dnskey = DNS_RDATA_INIT; 1580 char alg[80]; 1581 1582 dns_rdata_reset(&dnskey); 1583 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1584 1585 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); 1586 report("Fetching %s %d/%s from key %s.", 1587 key->ksk ? (allzsk ? "KSK/ZSK" : "KSK") : "ZSK", 1588 dst_key_id(key->key), alg, 1589 key->source == dns_keysource_user ? "file" : "repository"); 1590 1591 if (key->prepublish && ttl > key->prepublish) { 1592 char keystr[DST_KEY_FORMATSIZE]; 1593 isc_stdtime_t now; 1594 1595 dst_key_format(key->key, keystr, sizeof(keystr)); 1596 report("Key %s: Delaying activation to match the DNSKEY TTL.\n", 1597 keystr, ttl); 1598 1599 isc_stdtime_get(&now); 1600 dst_key_settime(key->key, DST_TIME_ACTIVATE, now + ttl); 1601 } 1602 1603 /* publish key */ 1604 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_ADD, origin, ttl, 1605 &dnskey, &tuple)); 1606 dns_diff_appendminimal(diff, &tuple); 1607 result = ISC_R_SUCCESS; 1608 1609 failure: 1610 return (result); 1611} 1612 1613static isc_result_t 1614remove_key(dns_diff_t *diff, dns_dnsseckey_t *key, dns_name_t *origin, 1615 dns_ttl_t ttl, isc_mem_t *mctx, const char *reason, 1616 void (*report)(const char *, ...)) 1617{ 1618 isc_result_t result; 1619 dns_difftuple_t *tuple = NULL; 1620 unsigned char buf[DST_KEY_MAXSIZE]; 1621 dns_rdata_t dnskey = DNS_RDATA_INIT; 1622 char alg[80]; 1623 1624 dns_secalg_format(dst_key_alg(key->key), alg, sizeof(alg)); 1625 report("Removing %s key %d/%s from DNSKEY RRset.", 1626 reason, dst_key_id(key->key), alg); 1627 1628 RETERR(make_dnskey(key->key, buf, sizeof(buf), &dnskey)); 1629 RETERR(dns_difftuple_create(mctx, DNS_DIFFOP_DEL, origin, ttl, &dnskey, 1630 &tuple)); 1631 dns_diff_appendminimal(diff, &tuple); 1632 result = ISC_R_SUCCESS; 1633 1634 failure: 1635 return (result); 1636} 1637 1638/* 1639 * Update 'keys' with information from 'newkeys'. 1640 * 1641 * If 'removed' is not NULL, any keys that are being removed from 1642 * the zone will be added to the list for post-removal processing. 1643 */ 1644isc_result_t 1645dns_dnssec_updatekeys(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *newkeys, 1646 dns_dnsseckeylist_t *removed, dns_name_t *origin, 1647 dns_ttl_t ttl, dns_diff_t *diff, isc_boolean_t allzsk, 1648 isc_mem_t *mctx, void (*report)(const char *, ...)) 1649{ 1650 isc_result_t result; 1651 dns_dnsseckey_t *key, *key1, *key2, *next; 1652 1653 /* 1654 * First, look through the existing key list to find keys 1655 * supplied from the command line which are not in the zone. 1656 * Update the zone to include them. 1657 */ 1658 for (key = ISC_LIST_HEAD(*keys); 1659 key != NULL; 1660 key = ISC_LIST_NEXT(key, link)) { 1661 if (key->source == dns_keysource_user && 1662 (key->hint_publish || key->force_publish)) { 1663 RETERR(publish_key(diff, key, origin, ttl, 1664 mctx, allzsk, report)); 1665 } 1666 } 1667 1668 /* 1669 * Second, scan the list of newly found keys looking for matches 1670 * with known keys, and update accordingly. 1671 */ 1672 for (key1 = ISC_LIST_HEAD(*newkeys); key1 != NULL; key1 = next) { 1673 isc_boolean_t key_revoked = ISC_FALSE; 1674 1675 next = ISC_LIST_NEXT(key1, link); 1676 1677 for (key2 = ISC_LIST_HEAD(*keys); 1678 key2 != NULL; 1679 key2 = ISC_LIST_NEXT(key2, link)) { 1680 if (dst_key_pubcompare(key1->key, key2->key, 1681 ISC_TRUE)) { 1682 int r1, r2; 1683 r1 = dst_key_flags(key1->key) & 1684 DNS_KEYFLAG_REVOKE; 1685 r2 = dst_key_flags(key2->key) & 1686 DNS_KEYFLAG_REVOKE; 1687 key_revoked = ISC_TF(r1 != r2); 1688 break; 1689 } 1690 } 1691 1692 /* No match found in keys; add the new key. */ 1693 if (key2 == NULL) { 1694 ISC_LIST_UNLINK(*newkeys, key1, link); 1695 ISC_LIST_APPEND(*keys, key1, link); 1696 1697 if (key1->source != dns_keysource_zoneapex && 1698 (key1->hint_publish || key1->force_publish)) { 1699 RETERR(publish_key(diff, key1, origin, ttl, 1700 mctx, allzsk, report)); 1701 if (key1->hint_sign || key1->force_sign) 1702 key1->first_sign = ISC_TRUE; 1703 } 1704 1705 continue; 1706 } 1707 1708 /* Match found: remove or update it as needed */ 1709 if (key1->hint_remove) { 1710 RETERR(remove_key(diff, key2, origin, ttl, mctx, 1711 "expired", 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 } else if (key_revoked && 1718 (dst_key_flags(key1->key) & DNS_KEYFLAG_REVOKE) != 0) { 1719 1720 /* 1721 * A previously valid key has been revoked. 1722 * We need to remove the old version and pull 1723 * in the new one. 1724 */ 1725 RETERR(remove_key(diff, key2, origin, ttl, mctx, 1726 "revoked", report)); 1727 ISC_LIST_UNLINK(*keys, key2, link); 1728 if (removed != NULL) 1729 ISC_LIST_APPEND(*removed, key2, link); 1730 else 1731 dns_dnsseckey_destroy(mctx, &key2); 1732 1733 RETERR(publish_key(diff, key1, origin, ttl, 1734 mctx, allzsk, report)); 1735 ISC_LIST_UNLINK(*newkeys, key1, link); 1736 ISC_LIST_APPEND(*keys, key1, link); 1737 1738 /* 1739 * XXX: The revoke flag is only defined for trust 1740 * anchors. Setting the flag on a non-KSK is legal, 1741 * but not defined in any RFC. It seems reasonable 1742 * to treat it the same as a KSK: keep it in the 1743 * zone, sign the DNSKEY set with it, but not 1744 * sign other records with it. 1745 */ 1746 key1->ksk = ISC_TRUE; 1747 continue; 1748 } else { 1749 if (!key2->is_active && 1750 (key1->hint_sign || key1->force_sign)) 1751 key2->first_sign = ISC_TRUE; 1752 key2->hint_sign = key1->hint_sign; 1753 key2->hint_publish = key1->hint_publish; 1754 } 1755 } 1756 1757 /* Free any leftover keys in newkeys */ 1758 while (!ISC_LIST_EMPTY(*newkeys)) { 1759 key1 = ISC_LIST_HEAD(*newkeys); 1760 ISC_LIST_UNLINK(*newkeys, key1, link); 1761 dns_dnsseckey_destroy(mctx, &key1); 1762 } 1763 1764 result = ISC_R_SUCCESS; 1765 1766 failure: 1767 return (result); 1768} 1769