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