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