1 /* $NetBSD: dnssectool.c,v 1.9 2015/07/08 17:28:55 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2005, 2007, 2009-2015 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 2000, 2001, 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 /*! \file */ 21 22 /*% 23 * DNSSEC Support Routines. 24 */ 25 26 #include <config.h> 27 28 #include <stdlib.h> 29 30 #include <isc/base32.h> 31 #include <isc/buffer.h> 32 #include <isc/dir.h> 33 #include <isc/entropy.h> 34 #include <isc/heap.h> 35 #include <isc/list.h> 36 #include <isc/mem.h> 37 #include <isc/string.h> 38 #include <isc/time.h> 39 #include <isc/util.h> 40 #include <isc/print.h> 41 42 #include <dns/db.h> 43 #include <dns/dbiterator.h> 44 #include <dns/dnssec.h> 45 #include <dns/fixedname.h> 46 #include <dns/keyvalues.h> 47 #include <dns/log.h> 48 #include <dns/name.h> 49 #include <dns/nsec.h> 50 #include <dns/nsec3.h> 51 #include <dns/rdatastruct.h> 52 #include <dns/rdataclass.h> 53 #include <dns/rdataset.h> 54 #include <dns/rdatasetiter.h> 55 #include <dns/rdatatype.h> 56 #include <dns/result.h> 57 #include <dns/secalg.h> 58 #include <dns/time.h> 59 60 #include "dnssectool.h" 61 62 static isc_heap_t *expected_chains, *found_chains; 63 64 struct nsec3_chain_fixed { 65 isc_uint8_t hash; 66 isc_uint8_t salt_length; 67 isc_uint8_t next_length; 68 isc_uint16_t iterations; 69 /* unsigned char salt[0]; */ 70 /* unsigned char owner[0]; */ 71 /* unsigned char next[0]; */ 72 }; 73 74 extern int verbose; 75 extern const char *program; 76 77 typedef struct entropysource entropysource_t; 78 79 struct entropysource { 80 isc_entropysource_t *source; 81 isc_mem_t *mctx; 82 ISC_LINK(entropysource_t) link; 83 }; 84 85 static ISC_LIST(entropysource_t) sources; 86 static fatalcallback_t *fatalcallback = NULL; 87 88 void 89 fatal(const char *format, ...) { 90 va_list args; 91 92 fprintf(stderr, "%s: fatal: ", program); 93 va_start(args, format); 94 vfprintf(stderr, format, args); 95 va_end(args); 96 fprintf(stderr, "\n"); 97 if (fatalcallback != NULL) 98 (*fatalcallback)(); 99 exit(1); 100 } 101 102 void 103 setfatalcallback(fatalcallback_t *callback) { 104 fatalcallback = callback; 105 } 106 107 void 108 check_result(isc_result_t result, const char *message) { 109 if (result != ISC_R_SUCCESS) 110 fatal("%s: %s", message, isc_result_totext(result)); 111 } 112 113 void 114 vbprintf(int level, const char *fmt, ...) { 115 va_list ap; 116 if (level > verbose) 117 return; 118 va_start(ap, fmt); 119 fprintf(stderr, "%s: ", program); 120 vfprintf(stderr, fmt, ap); 121 va_end(ap); 122 } 123 124 void 125 version(const char *name) { 126 fprintf(stderr, "%s %s\n", name, VERSION); 127 exit(0); 128 } 129 130 void 131 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) { 132 isc_buffer_t b; 133 isc_region_t r; 134 isc_result_t result; 135 136 isc_buffer_init(&b, cp, size - 1); 137 result = dns_rdatatype_totext(type, &b); 138 check_result(result, "dns_rdatatype_totext()"); 139 isc_buffer_usedregion(&b, &r); 140 r.base[r.length] = 0; 141 } 142 143 void 144 sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) { 145 char namestr[DNS_NAME_FORMATSIZE]; 146 char algstr[DNS_NAME_FORMATSIZE]; 147 148 dns_name_format(&sig->signer, namestr, sizeof(namestr)); 149 dns_secalg_format(sig->algorithm, algstr, sizeof(algstr)); 150 snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid); 151 } 152 153 void 154 setup_logging(isc_mem_t *mctx, isc_log_t **logp) { 155 isc_result_t result; 156 isc_logdestination_t destination; 157 isc_logconfig_t *logconfig = NULL; 158 isc_log_t *log = NULL; 159 int level; 160 161 if (verbose < 0) 162 verbose = 0; 163 switch (verbose) { 164 case 0: 165 /* 166 * We want to see warnings about things like out-of-zone 167 * data in the master file even when not verbose. 168 */ 169 level = ISC_LOG_WARNING; 170 break; 171 case 1: 172 level = ISC_LOG_INFO; 173 break; 174 default: 175 level = ISC_LOG_DEBUG(verbose - 2 + 1); 176 break; 177 } 178 179 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS); 180 isc_log_setcontext(log); 181 dns_log_init(log); 182 dns_log_setcontext(log); 183 184 RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS); 185 186 /* 187 * Set up a channel similar to default_stderr except: 188 * - the logging level is passed in 189 * - the program name and logging level are printed 190 * - no time stamp is printed 191 */ 192 destination.file.stream = stderr; 193 destination.file.name = NULL; 194 destination.file.versions = ISC_LOG_ROLLNEVER; 195 destination.file.maximum_size = 0; 196 result = isc_log_createchannel(logconfig, "stderr", 197 ISC_LOG_TOFILEDESC, 198 level, 199 &destination, 200 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL); 201 check_result(result, "isc_log_createchannel()"); 202 203 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", 204 NULL, NULL) == ISC_R_SUCCESS); 205 206 *logp = log; 207 } 208 209 void 210 cleanup_logging(isc_log_t **logp) { 211 isc_log_t *log; 212 213 REQUIRE(logp != NULL); 214 215 log = *logp; 216 if (log == NULL) 217 return; 218 isc_log_destroy(&log); 219 isc_log_setcontext(NULL); 220 dns_log_setcontext(NULL); 221 logp = NULL; 222 } 223 224 void 225 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) { 226 isc_result_t result; 227 isc_entropysource_t *source = NULL; 228 entropysource_t *elt; 229 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE; 230 231 REQUIRE(ectx != NULL); 232 233 if (*ectx == NULL) { 234 result = isc_entropy_create(mctx, ectx); 235 if (result != ISC_R_SUCCESS) 236 fatal("could not create entropy object"); 237 ISC_LIST_INIT(sources); 238 } 239 240 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { 241 usekeyboard = ISC_ENTROPY_KEYBOARDYES; 242 randomfile = NULL; 243 } 244 245 result = isc_entropy_usebestsource(*ectx, &source, randomfile, 246 usekeyboard); 247 248 if (result != ISC_R_SUCCESS) 249 fatal("could not initialize entropy source: %s", 250 isc_result_totext(result)); 251 252 if (source != NULL) { 253 elt = isc_mem_get(mctx, sizeof(*elt)); 254 if (elt == NULL) 255 fatal("out of memory"); 256 elt->source = source; 257 elt->mctx = mctx; 258 ISC_LINK_INIT(elt, link); 259 ISC_LIST_APPEND(sources, elt, link); 260 } 261 } 262 263 void 264 cleanup_entropy(isc_entropy_t **ectx) { 265 entropysource_t *source; 266 while (!ISC_LIST_EMPTY(sources)) { 267 source = ISC_LIST_HEAD(sources); 268 ISC_LIST_UNLINK(sources, source, link); 269 isc_entropy_destroysource(&source->source); 270 isc_mem_put(source->mctx, source, sizeof(*source)); 271 } 272 isc_entropy_detach(ectx); 273 } 274 275 static isc_stdtime_t 276 time_units(isc_stdtime_t offset, char *suffix, const char *str) { 277 switch (suffix[0]) { 278 case 'Y': case 'y': 279 return (offset * (365 * 24 * 3600)); 280 case 'M': case 'm': 281 switch (suffix[1]) { 282 case 'O': case 'o': 283 return (offset * (30 * 24 * 3600)); 284 case 'I': case 'i': 285 return (offset * 60); 286 case '\0': 287 fatal("'%s' ambiguous: use 'mi' for minutes " 288 "or 'mo' for months", str); 289 default: 290 fatal("time value %s is invalid", str); 291 } 292 /* NOTREACHED */ 293 break; 294 case 'W': case 'w': 295 return (offset * (7 * 24 * 3600)); 296 case 'D': case 'd': 297 return (offset * (24 * 3600)); 298 case 'H': case 'h': 299 return (offset * 3600); 300 case 'S': case 's': case '\0': 301 return (offset); 302 default: 303 fatal("time value %s is invalid", str); 304 } 305 /* NOTREACHED */ 306 return(0); /* silence compiler warning */ 307 } 308 309 static inline isc_boolean_t 310 isnone(const char *str) { 311 return (ISC_TF((strcasecmp(str, "none") == 0) || 312 (strcasecmp(str, "never") == 0))); 313 } 314 315 dns_ttl_t 316 strtottl(const char *str) { 317 const char *orig = str; 318 dns_ttl_t ttl; 319 char *endp; 320 321 if (isnone(str)) 322 return ((dns_ttl_t) 0); 323 324 ttl = strtol(str, &endp, 0); 325 if (ttl == 0 && endp == str) 326 fatal("TTL must be numeric"); 327 ttl = time_units(ttl, endp, orig); 328 return (ttl); 329 } 330 331 isc_stdtime_t 332 strtotime(const char *str, isc_int64_t now, isc_int64_t base, 333 isc_boolean_t *setp) 334 { 335 isc_int64_t val, offset; 336 isc_result_t result; 337 const char *orig = str; 338 char *endp; 339 size_t n; 340 341 if (isnone(str)) { 342 if (setp != NULL) 343 *setp = ISC_FALSE; 344 return ((isc_stdtime_t) 0); 345 } 346 347 if (setp != NULL) 348 *setp = ISC_TRUE; 349 350 if ((str[0] == '0' || str[0] == '-') && str[1] == '\0') 351 return ((isc_stdtime_t) 0); 352 353 /* 354 * We accept times in the following formats: 355 * now([+-]offset) 356 * YYYYMMDD([+-]offset) 357 * YYYYMMDDhhmmss([+-]offset) 358 * [+-]offset 359 */ 360 n = strspn(str, "0123456789"); 361 if ((n == 8u || n == 14u) && 362 (str[n] == '\0' || str[n] == '-' || str[n] == '+')) 363 { 364 char timestr[15]; 365 366 strlcpy(timestr, str, sizeof(timestr)); 367 timestr[n] = 0; 368 if (n == 8u) 369 strlcat(timestr, "000000", sizeof(timestr)); 370 result = dns_time64_fromtext(timestr, &val); 371 if (result != ISC_R_SUCCESS) 372 fatal("time value %s is invalid: %s", orig, 373 isc_result_totext(result)); 374 base = val; 375 str += n; 376 } else if (strncmp(str, "now", 3) == 0) { 377 base = now; 378 str += 3; 379 } 380 381 if (str[0] == '\0') 382 return ((isc_stdtime_t) base); 383 else if (str[0] == '+') { 384 offset = strtol(str + 1, &endp, 0); 385 offset = time_units((isc_stdtime_t) offset, endp, orig); 386 val = base + offset; 387 } else if (str[0] == '-') { 388 offset = strtol(str + 1, &endp, 0); 389 offset = time_units((isc_stdtime_t) offset, endp, orig); 390 val = base - offset; 391 } else 392 fatal("time value %s is invalid", orig); 393 394 return ((isc_stdtime_t) val); 395 } 396 397 dns_rdataclass_t 398 strtoclass(const char *str) { 399 isc_textregion_t r; 400 dns_rdataclass_t rdclass; 401 isc_result_t ret; 402 403 if (str == NULL) 404 return dns_rdataclass_in; 405 DE_CONST(str, r.base); 406 r.length = strlen(str); 407 ret = dns_rdataclass_fromtext(&rdclass, &r); 408 if (ret != ISC_R_SUCCESS) 409 fatal("unknown class %s", str); 410 return (rdclass); 411 } 412 413 isc_result_t 414 try_dir(const char *dirname) { 415 isc_result_t result; 416 isc_dir_t d; 417 418 isc_dir_init(&d); 419 result = isc_dir_open(&d, dirname); 420 if (result == ISC_R_SUCCESS) { 421 isc_dir_close(&d); 422 } 423 return (result); 424 } 425 426 /* 427 * Check private key version compatibility. 428 */ 429 void 430 check_keyversion(dst_key_t *key, char *keystr) { 431 int major, minor; 432 dst_key_getprivateformat(key, &major, &minor); 433 INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */ 434 435 if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION) 436 fatal("Key %s has incompatible format version %d.%d, " 437 "use -f to force upgrade to new version.", 438 keystr, major, minor); 439 if (minor > DST_MINOR_VERSION) 440 fatal("Key %s has incompatible format version %d.%d, " 441 "use -f to force downgrade to current version.", 442 keystr, major, minor); 443 } 444 445 void 446 set_keyversion(dst_key_t *key) { 447 int major, minor; 448 dst_key_getprivateformat(key, &major, &minor); 449 INSIST(major <= DST_MAJOR_VERSION); 450 451 if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION) 452 dst_key_setprivateformat(key, DST_MAJOR_VERSION, 453 DST_MINOR_VERSION); 454 455 /* 456 * If the key is from a version older than 1.3, set 457 * set the creation date 458 */ 459 if (major < 1 || (major == 1 && minor <= 2)) { 460 isc_stdtime_t now; 461 isc_stdtime_get(&now); 462 dst_key_settime(key, DST_TIME_CREATED, now); 463 } 464 } 465 466 isc_boolean_t 467 key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir, 468 isc_mem_t *mctx, isc_boolean_t *exact) 469 { 470 isc_result_t result; 471 isc_boolean_t conflict = ISC_FALSE; 472 dns_dnsseckeylist_t matchkeys; 473 dns_dnsseckey_t *key = NULL; 474 isc_uint16_t id, oldid; 475 isc_uint32_t rid, roldid; 476 dns_secalg_t alg; 477 478 if (exact != NULL) 479 *exact = ISC_FALSE; 480 481 id = dst_key_id(dstkey); 482 rid = dst_key_rid(dstkey); 483 alg = dst_key_alg(dstkey); 484 485 ISC_LIST_INIT(matchkeys); 486 result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys); 487 if (result == ISC_R_NOTFOUND) 488 return (ISC_FALSE); 489 490 while (!ISC_LIST_EMPTY(matchkeys) && !conflict) { 491 key = ISC_LIST_HEAD(matchkeys); 492 if (dst_key_alg(key->key) != alg) 493 goto next; 494 495 oldid = dst_key_id(key->key); 496 roldid = dst_key_rid(key->key); 497 498 if (oldid == rid || roldid == id || id == oldid) { 499 conflict = ISC_TRUE; 500 if (id != oldid) { 501 if (verbose > 1) 502 fprintf(stderr, "Key ID %d could " 503 "collide with %d\n", 504 id, oldid); 505 } else { 506 if (exact != NULL) 507 *exact = ISC_TRUE; 508 if (verbose > 1) 509 fprintf(stderr, "Key ID %d exists\n", 510 id); 511 } 512 } 513 514 next: 515 ISC_LIST_UNLINK(matchkeys, key, link); 516 dns_dnsseckey_destroy(mctx, &key); 517 } 518 519 /* Finish freeing the list */ 520 while (!ISC_LIST_EMPTY(matchkeys)) { 521 key = ISC_LIST_HEAD(matchkeys); 522 ISC_LIST_UNLINK(matchkeys, key, link); 523 dns_dnsseckey_destroy(mctx, &key); 524 } 525 526 return (conflict); 527 } 528 529 isc_boolean_t 530 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 531 dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) 532 { 533 dns_rdataset_t nsset; 534 isc_result_t result; 535 536 if (dns_name_equal(name, origin)) 537 return (ISC_FALSE); 538 539 dns_rdataset_init(&nsset); 540 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns, 541 0, 0, &nsset, NULL); 542 if (dns_rdataset_isassociated(&nsset)) { 543 if (ttlp != NULL) 544 *ttlp = nsset.ttl; 545 dns_rdataset_disassociate(&nsset); 546 } 547 548 return (ISC_TF(result == ISC_R_SUCCESS)); 549 } 550 551 static isc_boolean_t 552 goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name, 553 dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx) 554 { 555 dns_rdata_dnskey_t key; 556 dns_rdata_rrsig_t sig; 557 dst_key_t *dstkey = NULL; 558 isc_result_t result; 559 560 result = dns_rdata_tostruct(sigrdata, &sig, NULL); 561 check_result(result, "dns_rdata_tostruct()"); 562 563 for (result = dns_rdataset_first(keyrdataset); 564 result == ISC_R_SUCCESS; 565 result = dns_rdataset_next(keyrdataset)) { 566 dns_rdata_t rdata = DNS_RDATA_INIT; 567 dns_rdataset_current(keyrdataset, &rdata); 568 result = dns_rdata_tostruct(&rdata, &key, NULL); 569 check_result(result, "dns_rdata_tostruct()"); 570 result = dns_dnssec_keyfromrdata(origin, &rdata, mctx, 571 &dstkey); 572 if (result != ISC_R_SUCCESS) 573 return (ISC_FALSE); 574 if (sig.algorithm != key.algorithm || 575 sig.keyid != dst_key_id(dstkey) || 576 !dns_name_equal(&sig.signer, origin)) { 577 dst_key_free(&dstkey); 578 continue; 579 } 580 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE, 581 mctx, sigrdata); 582 dst_key_free(&dstkey); 583 if (result == ISC_R_SUCCESS) 584 return(ISC_TRUE); 585 } 586 return (ISC_FALSE); 587 } 588 589 static isc_result_t 590 verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 591 dns_dbnode_t *node, dns_name_t *nextname) 592 { 593 unsigned char buffer[DNS_NSEC_BUFFERSIZE]; 594 char namebuf[DNS_NAME_FORMATSIZE]; 595 char nextbuf[DNS_NAME_FORMATSIZE]; 596 char found[DNS_NAME_FORMATSIZE]; 597 dns_rdataset_t rdataset; 598 dns_rdata_t rdata = DNS_RDATA_INIT; 599 dns_rdata_t tmprdata = DNS_RDATA_INIT; 600 dns_rdata_nsec_t nsec; 601 isc_result_t result; 602 603 dns_rdataset_init(&rdataset); 604 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 605 0, 0, &rdataset, NULL); 606 if (result != ISC_R_SUCCESS) { 607 dns_name_format(name, namebuf, sizeof(namebuf)); 608 fprintf(stderr, "Missing NSEC record for %s\n", namebuf); 609 goto failure; 610 } 611 612 result = dns_rdataset_first(&rdataset); 613 check_result(result, "dns_rdataset_first()"); 614 615 dns_rdataset_current(&rdataset, &rdata); 616 result = dns_rdata_tostruct(&rdata, &nsec, NULL); 617 check_result(result, "dns_rdata_tostruct()"); 618 /* Check bit next name is consistent */ 619 if (!dns_name_equal(&nsec.next, nextname)) { 620 dns_name_format(name, namebuf, sizeof(namebuf)); 621 dns_name_format(nextname, nextbuf, sizeof(nextbuf)); 622 dns_name_format(&nsec.next, found, sizeof(found)); 623 fprintf(stderr, "Bad NSEC record for %s, next name " 624 "mismatch (expected:%s, found:%s)\n", namebuf, 625 nextbuf, found); 626 goto failure; 627 } 628 /* Check bit map is consistent */ 629 result = dns_nsec_buildrdata(db, ver, node, nextname, buffer, 630 &tmprdata); 631 check_result(result, "dns_nsec_buildrdata()"); 632 if (dns_rdata_compare(&rdata, &tmprdata) != 0) { 633 dns_name_format(name, namebuf, sizeof(namebuf)); 634 fprintf(stderr, "Bad NSEC record for %s, bit map " 635 "mismatch\n", namebuf); 636 goto failure; 637 } 638 result = dns_rdataset_next(&rdataset); 639 if (result != ISC_R_NOMORE) { 640 dns_name_format(name, namebuf, sizeof(namebuf)); 641 fprintf(stderr, "Multipe NSEC records for %s\n", namebuf); 642 goto failure; 643 644 } 645 dns_rdataset_disassociate(&rdataset); 646 return (ISC_R_SUCCESS); 647 failure: 648 if (dns_rdataset_isassociated(&rdataset)) 649 dns_rdataset_disassociate(&rdataset); 650 return (ISC_R_FAILURE); 651 } 652 653 static void 654 check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset, 655 dns_name_t *name, dns_dbnode_t *node) 656 { 657 char namebuf[DNS_NAME_FORMATSIZE]; 658 char typebuf[80]; 659 dns_rdataset_t sigrdataset; 660 dns_rdatasetiter_t *rdsiter = NULL; 661 isc_result_t result; 662 663 dns_rdataset_init(&sigrdataset); 664 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); 665 check_result(result, "dns_db_allrdatasets()"); 666 for (result = dns_rdatasetiter_first(rdsiter); 667 result == ISC_R_SUCCESS; 668 result = dns_rdatasetiter_next(rdsiter)) { 669 dns_rdatasetiter_current(rdsiter, &sigrdataset); 670 if (sigrdataset.type == dns_rdatatype_rrsig && 671 sigrdataset.covers == rdataset->type) 672 break; 673 dns_rdataset_disassociate(&sigrdataset); 674 } 675 if (result == ISC_R_SUCCESS) { 676 dns_name_format(name, namebuf, sizeof(namebuf)); 677 type_format(rdataset->type, typebuf, sizeof(typebuf)); 678 fprintf(stderr, "Warning: Found unexpected signatures for " 679 "%s/%s\n", namebuf, typebuf); 680 } 681 if (dns_rdataset_isassociated(&sigrdataset)) 682 dns_rdataset_disassociate(&sigrdataset); 683 dns_rdatasetiter_destroy(&rdsiter); 684 } 685 686 static isc_boolean_t 687 chain_compare(void *arg1, void *arg2) { 688 struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2; 689 size_t len; 690 691 /* 692 * Do each element in turn to get a stable sort. 693 */ 694 if (e1->hash < e2->hash) 695 return (ISC_TRUE); 696 if (e1->hash > e2->hash) 697 return (ISC_FALSE); 698 if (e1->iterations < e2->iterations) 699 return (ISC_TRUE); 700 if (e1->iterations > e2->iterations) 701 return (ISC_FALSE); 702 if (e1->salt_length < e2->salt_length) 703 return (ISC_TRUE); 704 if (e1->salt_length > e2->salt_length) 705 return (ISC_FALSE); 706 if (e1->next_length < e2->next_length) 707 return (ISC_TRUE); 708 if (e1->next_length > e2->next_length) 709 return (ISC_FALSE); 710 len = e1->salt_length + 2 * e1->next_length; 711 if (memcmp(e1 + 1, e2 + 1, len) < 0) 712 return (ISC_TRUE); 713 return (ISC_FALSE); 714 } 715 716 static isc_boolean_t 717 chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) { 718 size_t len; 719 720 if (e1->hash != e2->hash) 721 return (ISC_FALSE); 722 if (e1->iterations != e2->iterations) 723 return (ISC_FALSE); 724 if (e1->salt_length != e2->salt_length) 725 return (ISC_FALSE); 726 if (e1->next_length != e2->next_length) 727 return (ISC_FALSE); 728 len = e1->salt_length + 2 * e1->next_length; 729 if (memcmp(e1 + 1, e2 + 1, len) != 0) 730 return (ISC_FALSE); 731 return (ISC_TRUE); 732 } 733 734 static isc_result_t 735 record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3, 736 isc_mem_t *mctx, isc_heap_t *chains) 737 { 738 struct nsec3_chain_fixed *element; 739 size_t len; 740 unsigned char *cp; 741 isc_result_t result; 742 743 len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length; 744 745 element = isc_mem_get(mctx, len); 746 if (element == NULL) 747 return (ISC_R_NOMEMORY); 748 memset(element, 0, len); 749 element->hash = nsec3->hash; 750 element->salt_length = nsec3->salt_length; 751 element->next_length = nsec3->next_length; 752 element->iterations = nsec3->iterations; 753 cp = (unsigned char *)(element + 1); 754 memmove(cp, nsec3->salt, nsec3->salt_length); 755 cp += nsec3->salt_length; 756 memmove(cp, rawhash, nsec3->next_length); 757 cp += nsec3->next_length; 758 memmove(cp, nsec3->next, nsec3->next_length); 759 result = isc_heap_insert(chains, element); 760 if (result != ISC_R_SUCCESS) { 761 fprintf(stderr, "isc_heap_insert failed: %s\n", 762 isc_result_totext(result)); 763 isc_mem_put(mctx, element, len); 764 } 765 return (result); 766 } 767 768 static isc_result_t 769 match_nsec3(dns_name_t *name, isc_mem_t *mctx, 770 dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset, 771 unsigned char types[8192], unsigned int maxtype, 772 unsigned char *rawhash, size_t rhsize) 773 { 774 unsigned char cbm[8244]; 775 char namebuf[DNS_NAME_FORMATSIZE]; 776 dns_rdata_nsec3_t nsec3; 777 isc_result_t result; 778 unsigned int len; 779 780 /* 781 * Find matching NSEC3 record. 782 */ 783 for (result = dns_rdataset_first(rdataset); 784 result == ISC_R_SUCCESS; 785 result = dns_rdataset_next(rdataset)) { 786 dns_rdata_t rdata = DNS_RDATA_INIT; 787 dns_rdataset_current(rdataset, &rdata); 788 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 789 check_result(result, "dns_rdata_tostruct()"); 790 if (nsec3.hash == nsec3param->hash && 791 nsec3.next_length == rhsize && 792 nsec3.iterations == nsec3param->iterations && 793 nsec3.salt_length == nsec3param->salt_length && 794 memcmp(nsec3.salt, nsec3param->salt, 795 nsec3param->salt_length) == 0) 796 break; 797 } 798 if (result != ISC_R_SUCCESS) { 799 dns_name_format(name, namebuf, sizeof(namebuf)); 800 fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf); 801 return (result); 802 } 803 804 /* 805 * Check the type list. 806 */ 807 len = dns_nsec_compressbitmap(cbm, types, maxtype); 808 if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) { 809 dns_name_format(name, namebuf, sizeof(namebuf)); 810 fprintf(stderr, "Bad NSEC3 record for %s, bit map " 811 "mismatch\n", namebuf); 812 return (ISC_R_FAILURE); 813 } 814 815 /* 816 * Record chain. 817 */ 818 result = record_nsec3(rawhash, &nsec3, mctx, expected_chains); 819 check_result(result, "record_nsec3()"); 820 821 /* 822 * Make sure there is only one NSEC3 record with this set of 823 * parameters. 824 */ 825 for (result = dns_rdataset_next(rdataset); 826 result == ISC_R_SUCCESS; 827 result = dns_rdataset_next(rdataset)) { 828 dns_rdata_t rdata = DNS_RDATA_INIT; 829 dns_rdataset_current(rdataset, &rdata); 830 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 831 check_result(result, "dns_rdata_tostruct()"); 832 if (nsec3.hash == nsec3param->hash && 833 nsec3.iterations == nsec3param->iterations && 834 nsec3.salt_length == nsec3param->salt_length && 835 memcmp(nsec3.salt, nsec3param->salt, 836 nsec3.salt_length) == 0) { 837 dns_name_format(name, namebuf, sizeof(namebuf)); 838 fprintf(stderr, "Multiple NSEC3 records with the " 839 "same parameter set for %s", namebuf); 840 result = DNS_R_DUPLICATE; 841 break; 842 } 843 } 844 if (result != ISC_R_NOMORE) 845 return (result); 846 847 result = ISC_R_SUCCESS; 848 return (result); 849 } 850 851 static isc_boolean_t 852 innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) { 853 dns_rdata_nsec3param_t nsec3param; 854 isc_result_t result; 855 856 for (result = dns_rdataset_first(nsec3paramset); 857 result == ISC_R_SUCCESS; 858 result = dns_rdataset_next(nsec3paramset)) { 859 dns_rdata_t rdata = DNS_RDATA_INIT; 860 861 dns_rdataset_current(nsec3paramset, &rdata); 862 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); 863 check_result(result, "dns_rdata_tostruct()"); 864 if (nsec3param.flags == 0 && 865 nsec3param.hash == nsec3->hash && 866 nsec3param.iterations == nsec3->iterations && 867 nsec3param.salt_length == nsec3->salt_length && 868 memcmp(nsec3param.salt, nsec3->salt, 869 nsec3->salt_length) == 0) 870 return (ISC_TRUE); 871 } 872 return (ISC_FALSE); 873 } 874 875 static isc_result_t 876 record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx, 877 dns_name_t *name, dns_dbnode_t *node, 878 dns_rdataset_t *nsec3paramset) 879 { 880 unsigned char owner[NSEC3_MAX_HASH_LENGTH]; 881 dns_rdata_nsec3_t nsec3; 882 dns_rdataset_t rdataset; 883 dns_label_t hashlabel; 884 isc_buffer_t b; 885 isc_result_t result; 886 887 if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset)) 888 return (ISC_R_SUCCESS); 889 890 dns_rdataset_init(&rdataset); 891 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 892 0, 0, &rdataset, NULL); 893 if (result != ISC_R_SUCCESS) 894 return (ISC_R_SUCCESS); 895 896 dns_name_getlabel(name, 0, &hashlabel); 897 isc_region_consume(&hashlabel, 1); 898 isc_buffer_init(&b, owner, sizeof(owner)); 899 result = isc_base32hex_decoderegion(&hashlabel, &b); 900 if (result != ISC_R_SUCCESS) 901 goto cleanup; 902 903 for (result = dns_rdataset_first(&rdataset); 904 result == ISC_R_SUCCESS; 905 result = dns_rdataset_next(&rdataset)) { 906 dns_rdata_t rdata = DNS_RDATA_INIT; 907 dns_rdataset_current(&rdataset, &rdata); 908 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 909 check_result(result, "dns_rdata_tostruct()"); 910 if (nsec3.next_length != isc_buffer_usedlength(&b)) 911 continue; 912 /* 913 * We only care about NSEC3 records that match a NSEC3PARAM 914 * record. 915 */ 916 if (!innsec3params(&nsec3, nsec3paramset)) 917 continue; 918 919 /* 920 * Record chain. 921 */ 922 result = record_nsec3(owner, &nsec3, mctx, found_chains); 923 check_result(result, "record_nsec3()"); 924 } 925 926 cleanup: 927 dns_rdataset_disassociate(&rdataset); 928 return (ISC_R_SUCCESS); 929 } 930 931 static isc_boolean_t 932 isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 933 dns_rdata_t *nsec3rdata) 934 { 935 dns_rdataset_t rdataset; 936 dns_rdata_t rdata = DNS_RDATA_INIT; 937 dns_rdata_nsec3_t nsec3; 938 dns_rdata_nsec3param_t nsec3param; 939 dns_fixedname_t fixed; 940 dns_name_t *hashname; 941 isc_result_t result; 942 dns_dbnode_t *node = NULL; 943 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; 944 size_t rhsize = sizeof(rawhash); 945 isc_boolean_t ret; 946 947 result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL); 948 check_result(result, "dns_rdata_tostruct()"); 949 950 dns_fixedname_init(&fixed); 951 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, origin, origin, 952 nsec3param.hash, nsec3param.iterations, 953 nsec3param.salt, nsec3param.salt_length); 954 check_result(result, "dns_nsec3_hashname()"); 955 956 dns_rdataset_init(&rdataset); 957 hashname = dns_fixedname_name(&fixed); 958 result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node); 959 if (result == ISC_R_SUCCESS) 960 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 961 0, 0, &rdataset, NULL); 962 if (result != ISC_R_SUCCESS) 963 return (ISC_FALSE); 964 965 result = dns_rdataset_first(&rdataset); 966 check_result(result, "dns_rdataset_first()"); 967 968 dns_rdataset_current(&rdataset, &rdata); 969 970 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 971 if (result != ISC_R_SUCCESS) 972 ret = ISC_FALSE; 973 else 974 ret = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); 975 976 if (dns_rdataset_isassociated(&rdataset)) 977 dns_rdataset_disassociate(&rdataset); 978 if (node != NULL) 979 dns_db_detachnode(db, &node); 980 981 return (ret); 982 } 983 984 static isc_result_t 985 verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 986 isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata, 987 isc_boolean_t delegation, isc_boolean_t empty, 988 unsigned char types[8192], unsigned int maxtype) 989 { 990 char namebuf[DNS_NAME_FORMATSIZE]; 991 char hashbuf[DNS_NAME_FORMATSIZE]; 992 dns_rdataset_t rdataset; 993 dns_rdata_nsec3param_t nsec3param; 994 dns_fixedname_t fixed; 995 dns_name_t *hashname; 996 isc_result_t result; 997 dns_dbnode_t *node = NULL; 998 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; 999 size_t rhsize = sizeof(rawhash); 1000 isc_boolean_t optout; 1001 1002 result = dns_rdata_tostruct(rdata, &nsec3param, NULL); 1003 check_result(result, "dns_rdata_tostruct()"); 1004 1005 if (nsec3param.flags != 0) 1006 return (ISC_R_SUCCESS); 1007 1008 if (!dns_nsec3_supportedhash(nsec3param.hash)) 1009 return (ISC_R_SUCCESS); 1010 1011 optout = isoptout(db, ver, origin, rdata); 1012 1013 dns_fixedname_init(&fixed); 1014 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin, 1015 nsec3param.hash, nsec3param.iterations, 1016 nsec3param.salt, nsec3param.salt_length); 1017 check_result(result, "dns_nsec3_hashname()"); 1018 1019 /* 1020 * We don't use dns_db_find() here as it works with the choosen 1021 * nsec3 chain and we may also be called with uncommitted data 1022 * from dnssec-signzone so the secure status of the zone may not 1023 * be up to date. 1024 */ 1025 dns_rdataset_init(&rdataset); 1026 hashname = dns_fixedname_name(&fixed); 1027 result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node); 1028 if (result == ISC_R_SUCCESS) 1029 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 1030 0, 0, &rdataset, NULL); 1031 if (result != ISC_R_SUCCESS && 1032 (!delegation || (empty && !optout) || 1033 (!empty && dns_nsec_isset(types, dns_rdatatype_ds)))) 1034 { 1035 dns_name_format(name, namebuf, sizeof(namebuf)); 1036 dns_name_format(hashname, hashbuf, sizeof(hashbuf)); 1037 fprintf(stderr, "Missing NSEC3 record for %s (%s)\n", 1038 namebuf, hashbuf); 1039 } else if (result == ISC_R_NOTFOUND && 1040 delegation && (!empty || optout)) 1041 { 1042 result = ISC_R_SUCCESS; 1043 } else if (result == ISC_R_SUCCESS) { 1044 result = match_nsec3(name, mctx, &nsec3param, &rdataset, 1045 types, maxtype, rawhash, rhsize); 1046 } 1047 1048 if (dns_rdataset_isassociated(&rdataset)) 1049 dns_rdataset_disassociate(&rdataset); 1050 if (node != NULL) 1051 dns_db_detachnode(db, &node); 1052 1053 return (result); 1054 } 1055 1056 static isc_result_t 1057 verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 1058 isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset, 1059 isc_boolean_t delegation, isc_boolean_t empty, 1060 unsigned char types[8192], unsigned int maxtype) 1061 { 1062 isc_result_t result; 1063 1064 for (result = dns_rdataset_first(nsec3paramset); 1065 result == ISC_R_SUCCESS; 1066 result = dns_rdataset_next(nsec3paramset)) { 1067 dns_rdata_t rdata = DNS_RDATA_INIT; 1068 1069 dns_rdataset_current(nsec3paramset, &rdata); 1070 result = verifynsec3(db, ver, origin, mctx, name, &rdata, 1071 delegation, empty, types, maxtype); 1072 if (result != ISC_R_SUCCESS) 1073 break; 1074 } 1075 if (result == ISC_R_NOMORE) 1076 result = ISC_R_SUCCESS; 1077 return (result); 1078 } 1079 1080 static void 1081 verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 1082 isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name, 1083 dns_dbnode_t *node, dns_rdataset_t *keyrdataset, 1084 unsigned char *act_algorithms, unsigned char *bad_algorithms) 1085 { 1086 unsigned char set_algorithms[256]; 1087 char namebuf[DNS_NAME_FORMATSIZE]; 1088 char algbuf[80]; 1089 char typebuf[80]; 1090 dns_rdataset_t sigrdataset; 1091 dns_rdatasetiter_t *rdsiter = NULL; 1092 isc_result_t result; 1093 int i; 1094 1095 dns_rdataset_init(&sigrdataset); 1096 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); 1097 check_result(result, "dns_db_allrdatasets()"); 1098 for (result = dns_rdatasetiter_first(rdsiter); 1099 result == ISC_R_SUCCESS; 1100 result = dns_rdatasetiter_next(rdsiter)) { 1101 dns_rdatasetiter_current(rdsiter, &sigrdataset); 1102 if (sigrdataset.type == dns_rdatatype_rrsig && 1103 sigrdataset.covers == rdataset->type) 1104 break; 1105 dns_rdataset_disassociate(&sigrdataset); 1106 } 1107 if (result != ISC_R_SUCCESS) { 1108 dns_name_format(name, namebuf, sizeof(namebuf)); 1109 type_format(rdataset->type, typebuf, sizeof(typebuf)); 1110 fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf); 1111 for (i = 0; i < 256; i++) 1112 if (act_algorithms[i] != 0) 1113 bad_algorithms[i] = 1; 1114 dns_rdatasetiter_destroy(&rdsiter); 1115 return; 1116 } 1117 1118 memset(set_algorithms, 0, sizeof(set_algorithms)); 1119 for (result = dns_rdataset_first(&sigrdataset); 1120 result == ISC_R_SUCCESS; 1121 result = dns_rdataset_next(&sigrdataset)) { 1122 dns_rdata_t rdata = DNS_RDATA_INIT; 1123 dns_rdata_rrsig_t sig; 1124 1125 dns_rdataset_current(&sigrdataset, &rdata); 1126 result = dns_rdata_tostruct(&rdata, &sig, NULL); 1127 check_result(result, "dns_rdata_tostruct()"); 1128 if (rdataset->ttl != sig.originalttl) { 1129 dns_name_format(name, namebuf, sizeof(namebuf)); 1130 type_format(rdataset->type, typebuf, sizeof(typebuf)); 1131 fprintf(stderr, "TTL mismatch for %s %s keytag %u\n", 1132 namebuf, typebuf, sig.keyid); 1133 continue; 1134 } 1135 if ((set_algorithms[sig.algorithm] != 0) || 1136 (act_algorithms[sig.algorithm] == 0)) 1137 continue; 1138 if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx)) 1139 set_algorithms[sig.algorithm] = 1; 1140 } 1141 dns_rdatasetiter_destroy(&rdsiter); 1142 if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) { 1143 dns_name_format(name, namebuf, sizeof(namebuf)); 1144 type_format(rdataset->type, typebuf, sizeof(typebuf)); 1145 for (i = 0; i < 256; i++) 1146 if ((act_algorithms[i] != 0) && 1147 (set_algorithms[i] == 0)) { 1148 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1149 fprintf(stderr, "No correct %s signature for " 1150 "%s %s\n", algbuf, namebuf, typebuf); 1151 bad_algorithms[i] = 1; 1152 } 1153 } 1154 dns_rdataset_disassociate(&sigrdataset); 1155 } 1156 1157 static isc_result_t 1158 verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 1159 isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node, 1160 isc_boolean_t delegation, dns_rdataset_t *keyrdataset, 1161 unsigned char *act_algorithms, unsigned char *bad_algorithms, 1162 dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset, 1163 dns_name_t *nextname) 1164 { 1165 unsigned char types[8192]; 1166 unsigned int maxtype = 0; 1167 dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL; 1168 isc_result_t result, tresult; 1169 1170 memset(types, 0, sizeof(types)); 1171 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); 1172 check_result(result, "dns_db_allrdatasets()"); 1173 result = dns_rdatasetiter_first(rdsiter); 1174 dns_rdataset_init(&rdataset); 1175 while (result == ISC_R_SUCCESS) { 1176 dns_rdatasetiter_current(rdsiter, &rdataset); 1177 /* 1178 * If we are not at a delegation then everything should be 1179 * signed. If we are at a delegation then only the DS set 1180 * is signed. The NS set is not signed at a delegation but 1181 * its existance is recorded in the bit map. Anything else 1182 * other than NSEC and DS is not signed at a delegation. 1183 */ 1184 if (rdataset.type != dns_rdatatype_rrsig && 1185 rdataset.type != dns_rdatatype_dnskey && 1186 (!delegation || rdataset.type == dns_rdatatype_ds || 1187 rdataset.type == dns_rdatatype_nsec)) { 1188 verifyset(db, ver, origin, mctx, &rdataset, 1189 name, node, keyrdataset, 1190 act_algorithms, bad_algorithms); 1191 dns_nsec_setbit(types, rdataset.type, 1); 1192 if (rdataset.type > maxtype) 1193 maxtype = rdataset.type; 1194 } else if (rdataset.type != dns_rdatatype_rrsig && 1195 rdataset.type != dns_rdatatype_dnskey) { 1196 if (rdataset.type == dns_rdatatype_ns) 1197 dns_nsec_setbit(types, rdataset.type, 1); 1198 check_no_rrsig(db, ver, &rdataset, name, node); 1199 } else 1200 dns_nsec_setbit(types, rdataset.type, 1); 1201 dns_rdataset_disassociate(&rdataset); 1202 result = dns_rdatasetiter_next(rdsiter); 1203 } 1204 if (result != ISC_R_NOMORE) 1205 fatal("rdataset iteration failed: %s", 1206 isc_result_totext(result)); 1207 dns_rdatasetiter_destroy(&rdsiter); 1208 1209 result = ISC_R_SUCCESS; 1210 1211 if (nsecset != NULL && dns_rdataset_isassociated(nsecset)) 1212 result = verifynsec(db, ver, name, node, nextname); 1213 1214 if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) { 1215 tresult = verifynsec3s(db, ver, origin, mctx, name, 1216 nsec3paramset, delegation, ISC_FALSE, 1217 types, maxtype); 1218 if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) 1219 result = tresult; 1220 } 1221 return (result); 1222 } 1223 1224 static isc_boolean_t 1225 is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) { 1226 dns_rdatasetiter_t *rdsiter = NULL; 1227 isc_result_t result; 1228 1229 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter); 1230 check_result(result, "dns_db_allrdatasets()"); 1231 result = dns_rdatasetiter_first(rdsiter); 1232 dns_rdatasetiter_destroy(&rdsiter); 1233 if (result == ISC_R_NOMORE) 1234 return (ISC_TRUE); 1235 return (ISC_FALSE); 1236 } 1237 1238 static void 1239 check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db, 1240 dns_dbversion_t *ver) 1241 { 1242 dns_rdataset_t rdataset; 1243 isc_result_t result; 1244 1245 dns_rdataset_init(&rdataset); 1246 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 1247 0, 0, &rdataset, NULL); 1248 if (result != ISC_R_NOTFOUND) { 1249 char namebuf[DNS_NAME_FORMATSIZE]; 1250 dns_name_format(name, namebuf, sizeof(namebuf)); 1251 fatal("unexpected NSEC RRset at %s\n", namebuf); 1252 } 1253 1254 if (dns_rdataset_isassociated(&rdataset)) 1255 dns_rdataset_disassociate(&rdataset); 1256 } 1257 1258 static isc_boolean_t 1259 newchain(const struct nsec3_chain_fixed *first, 1260 const struct nsec3_chain_fixed *e) 1261 { 1262 if (first->hash != e->hash || 1263 first->iterations != e->iterations || 1264 first->salt_length != e->salt_length || 1265 first->next_length != e->next_length || 1266 memcmp(first + 1, e + 1, first->salt_length) != 0) 1267 return (ISC_TRUE); 1268 return (ISC_FALSE); 1269 } 1270 1271 static void 1272 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) { 1273 size_t len; 1274 1275 len = sizeof(*e) + e->salt_length + 2 * e->next_length; 1276 isc_mem_put(mctx, e, len); 1277 } 1278 1279 static isc_boolean_t 1280 checknext(const struct nsec3_chain_fixed *first, 1281 const struct nsec3_chain_fixed *e) 1282 { 1283 char buf[512]; 1284 const unsigned char *d1 = (const unsigned char *)(first + 1); 1285 const unsigned char *d2 = (const unsigned char *)(e + 1); 1286 isc_buffer_t b; 1287 isc_region_t sr; 1288 1289 d1 += first->salt_length + first->next_length; 1290 d2 += e->salt_length; 1291 1292 if (memcmp(d1, d2, first->next_length) == 0) 1293 return (ISC_TRUE); 1294 1295 DE_CONST(d1 - first->next_length, sr.base); 1296 sr.length = first->next_length; 1297 isc_buffer_init(&b, buf, sizeof(buf)); 1298 isc_base32hex_totext(&sr, 1, "", &b); 1299 fprintf(stderr, "Break in NSEC3 chain at: %.*s\n", 1300 (int) isc_buffer_usedlength(&b), buf); 1301 1302 DE_CONST(d1, sr.base); 1303 sr.length = first->next_length; 1304 isc_buffer_init(&b, buf, sizeof(buf)); 1305 isc_base32hex_totext(&sr, 1, "", &b); 1306 fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b), 1307 buf); 1308 1309 DE_CONST(d2, sr.base); 1310 sr.length = first->next_length; 1311 isc_buffer_init(&b, buf, sizeof(buf)); 1312 isc_base32hex_totext(&sr, 1, "", &b); 1313 fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf); 1314 1315 return (ISC_FALSE); 1316 } 1317 1318 #define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n" 1319 1320 static isc_result_t 1321 verify_nsec3_chains(isc_mem_t *mctx) { 1322 isc_result_t result = ISC_R_SUCCESS; 1323 struct nsec3_chain_fixed *e, *f = NULL; 1324 struct nsec3_chain_fixed *first = NULL, *prev = NULL; 1325 1326 while ((e = isc_heap_element(expected_chains, 1)) != NULL) { 1327 isc_heap_delete(expected_chains, 1); 1328 if (f == NULL) 1329 f = isc_heap_element(found_chains, 1); 1330 if (f != NULL) { 1331 isc_heap_delete(found_chains, 1); 1332 1333 /* 1334 * Check that they match. 1335 */ 1336 if (chain_equal(e, f)) { 1337 free_element(mctx, f); 1338 f = NULL; 1339 } else { 1340 if (result == ISC_R_SUCCESS) 1341 fprintf(stderr, EXPECTEDANDFOUND); 1342 result = ISC_R_FAILURE; 1343 /* 1344 * Attempt to resync found_chain. 1345 */ 1346 while (f != NULL && !chain_compare(e, f)) { 1347 free_element(mctx, f); 1348 f = isc_heap_element(found_chains, 1); 1349 if (f != NULL) 1350 isc_heap_delete(found_chains, 1); 1351 if (f != NULL && chain_equal(e, f)) { 1352 free_element(mctx, f); 1353 f = NULL; 1354 break; 1355 } 1356 } 1357 } 1358 } else if (result == ISC_R_SUCCESS) { 1359 fprintf(stderr, EXPECTEDANDFOUND); 1360 result = ISC_R_FAILURE; 1361 } 1362 if (first == NULL || newchain(first, e)) { 1363 if (prev != NULL) { 1364 if (!checknext(prev, first)) 1365 result = ISC_R_FAILURE; 1366 if (prev != first) 1367 free_element(mctx, prev); 1368 } 1369 if (first != NULL) 1370 free_element(mctx, first); 1371 prev = first = e; 1372 continue; 1373 } 1374 if (!checknext(prev, e)) 1375 result = ISC_R_FAILURE; 1376 if (prev != first) 1377 free_element(mctx, prev); 1378 prev = e; 1379 } 1380 if (prev != NULL) { 1381 if (!checknext(prev, first)) 1382 result = ISC_R_FAILURE; 1383 if (prev != first) 1384 free_element(mctx, prev); 1385 } 1386 if (first != NULL) 1387 free_element(mctx, first); 1388 do { 1389 if (f != NULL) { 1390 if (result == ISC_R_SUCCESS) { 1391 fprintf(stderr, EXPECTEDANDFOUND); 1392 result = ISC_R_FAILURE; 1393 } 1394 free_element(mctx, f); 1395 } 1396 f = isc_heap_element(found_chains, 1); 1397 if (f != NULL) 1398 isc_heap_delete(found_chains, 1); 1399 } while (f != NULL); 1400 1401 return (result); 1402 } 1403 1404 static isc_result_t 1405 verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 1406 isc_mem_t *mctx, dns_name_t *name, dns_name_t *prevname, 1407 isc_boolean_t isdelegation, dns_rdataset_t *nsec3paramset) 1408 { 1409 dns_namereln_t reln; 1410 int order; 1411 unsigned int labels, nlabels, i; 1412 dns_name_t suffix; 1413 isc_result_t result = ISC_R_SUCCESS, tresult; 1414 1415 reln = dns_name_fullcompare(prevname, name, &order, &labels); 1416 if (order >= 0) 1417 return (result); 1418 1419 nlabels = dns_name_countlabels(name); 1420 1421 if (reln == dns_namereln_commonancestor || 1422 reln == dns_namereln_contains) { 1423 dns_name_init(&suffix, NULL); 1424 for (i = labels + 1; i < nlabels; i++) { 1425 dns_name_getlabelsequence(name, nlabels - i, i, 1426 &suffix); 1427 if (nsec3paramset != NULL && 1428 dns_rdataset_isassociated(nsec3paramset)) { 1429 tresult = verifynsec3s(db, ver, origin, mctx, 1430 &suffix, nsec3paramset, 1431 isdelegation, ISC_TRUE, 1432 NULL, 0); 1433 if (result == ISC_R_SUCCESS && 1434 tresult != ISC_R_SUCCESS) 1435 result = tresult; 1436 } 1437 } 1438 } 1439 return (result); 1440 } 1441 1442 /*% 1443 * Verify that certain things are sane: 1444 * 1445 * The apex has a DNSKEY record with at least one KSK, and at least 1446 * one ZSK if the -x flag was not used. 1447 * 1448 * The DNSKEY record was signed with at least one of the KSKs in this 1449 * set. 1450 * 1451 * The rest of the zone was signed with at least one of the ZSKs 1452 * present in the DNSKEY RRSET. 1453 */ 1454 void 1455 verifyzone(dns_db_t *db, dns_dbversion_t *ver, 1456 dns_name_t *origin, isc_mem_t *mctx, 1457 isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly) 1458 { 1459 char algbuf[80]; 1460 dns_dbiterator_t *dbiter = NULL; 1461 dns_dbnode_t *node = NULL, *nextnode = NULL; 1462 dns_fixedname_t fname, fnextname, fprevname, fzonecut; 1463 dns_name_t *name, *nextname, *prevname, *zonecut; 1464 dns_rdata_dnskey_t dnskey; 1465 dns_rdata_t rdata = DNS_RDATA_INIT; 1466 dns_rdataset_t keyset, soaset; 1467 dns_rdataset_t keysigs, soasigs; 1468 dns_rdataset_t nsecset, nsecsigs; 1469 dns_rdataset_t nsec3paramset, nsec3paramsigs; 1470 int i; 1471 isc_boolean_t done = ISC_FALSE; 1472 isc_boolean_t first = ISC_TRUE; 1473 isc_boolean_t goodksk = ISC_FALSE; 1474 isc_boolean_t goodzsk = ISC_FALSE; 1475 isc_result_t result, vresult = ISC_R_UNSET; 1476 unsigned char revoked_ksk[256]; 1477 unsigned char revoked_zsk[256]; 1478 unsigned char standby_ksk[256]; 1479 unsigned char standby_zsk[256]; 1480 unsigned char ksk_algorithms[256]; 1481 unsigned char zsk_algorithms[256]; 1482 unsigned char bad_algorithms[256]; 1483 unsigned char act_algorithms[256]; 1484 1485 result = isc_heap_create(mctx, chain_compare, NULL, 1024, 1486 &expected_chains); 1487 check_result(result, "isc_heap_create()"); 1488 result = isc_heap_create(mctx, chain_compare, NULL, 1024, 1489 &found_chains); 1490 check_result(result, "isc_heap_create()"); 1491 1492 result = dns_db_findnode(db, origin, ISC_FALSE, &node); 1493 if (result != ISC_R_SUCCESS) 1494 fatal("failed to find the zone's origin: %s", 1495 isc_result_totext(result)); 1496 1497 dns_rdataset_init(&keyset); 1498 dns_rdataset_init(&keysigs); 1499 dns_rdataset_init(&soaset); 1500 dns_rdataset_init(&soasigs); 1501 dns_rdataset_init(&nsecset); 1502 dns_rdataset_init(&nsecsigs); 1503 dns_rdataset_init(&nsec3paramset); 1504 dns_rdataset_init(&nsec3paramsigs); 1505 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 1506 0, 0, &keyset, &keysigs); 1507 if (result != ISC_R_SUCCESS) 1508 fatal("Zone contains no DNSSEC keys\n"); 1509 1510 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 1511 0, 0, &soaset, &soasigs); 1512 if (result != ISC_R_SUCCESS) 1513 fatal("Zone contains no SOA record\n"); 1514 1515 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 1516 0, 0, &nsecset, &nsecsigs); 1517 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) 1518 fatal("NSEC lookup failed\n"); 1519 1520 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 1521 0, 0, &nsec3paramset, &nsec3paramsigs); 1522 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) 1523 fatal("NSEC3PARAM lookup failed\n"); 1524 1525 if (!dns_rdataset_isassociated(&keysigs)) 1526 fatal("DNSKEY is not signed (keys offline or inactive?)\n"); 1527 1528 if (!dns_rdataset_isassociated(&soasigs)) 1529 fatal("SOA is not signed (keys offline or inactive?)\n"); 1530 1531 if (dns_rdataset_isassociated(&nsecset) && 1532 !dns_rdataset_isassociated(&nsecsigs)) 1533 fatal("NSEC is not signed (keys offline or inactive?)\n"); 1534 1535 if (dns_rdataset_isassociated(&nsec3paramset) && 1536 !dns_rdataset_isassociated(&nsec3paramsigs)) 1537 fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n"); 1538 1539 if (!dns_rdataset_isassociated(&nsecset) && 1540 !dns_rdataset_isassociated(&nsec3paramset)) 1541 fatal("No valid NSEC/NSEC3 chain for testing\n"); 1542 1543 dns_db_detachnode(db, &node); 1544 1545 memset(revoked_ksk, 0, sizeof(revoked_ksk)); 1546 memset(revoked_zsk, 0, sizeof(revoked_zsk)); 1547 memset(standby_ksk, 0, sizeof(standby_ksk)); 1548 memset(standby_zsk, 0, sizeof(standby_zsk)); 1549 memset(ksk_algorithms, 0, sizeof(ksk_algorithms)); 1550 memset(zsk_algorithms, 0, sizeof(zsk_algorithms)); 1551 memset(bad_algorithms, 0, sizeof(bad_algorithms)); 1552 memset(act_algorithms, 0, sizeof(act_algorithms)); 1553 1554 /* 1555 * Check that the DNSKEY RR has at least one self signing KSK 1556 * and one ZSK per algorithm in it (or, if -x was used, one 1557 * self-signing KSK). 1558 */ 1559 for (result = dns_rdataset_first(&keyset); 1560 result == ISC_R_SUCCESS; 1561 result = dns_rdataset_next(&keyset)) { 1562 dns_rdataset_current(&keyset, &rdata); 1563 result = dns_rdata_tostruct(&rdata, &dnskey, NULL); 1564 check_result(result, "dns_rdata_tostruct"); 1565 1566 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0) 1567 ; 1568 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) { 1569 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && 1570 !dns_dnssec_selfsigns(&rdata, origin, &keyset, 1571 &keysigs, ISC_FALSE, 1572 mctx)) { 1573 char namebuf[DNS_NAME_FORMATSIZE]; 1574 char buffer[1024]; 1575 isc_buffer_t buf; 1576 1577 dns_name_format(origin, namebuf, 1578 sizeof(namebuf)); 1579 isc_buffer_init(&buf, buffer, sizeof(buffer)); 1580 result = dns_rdata_totext(&rdata, NULL, &buf); 1581 check_result(result, "dns_rdata_totext"); 1582 fatal("revoked KSK is not self signed:\n" 1583 "%s DNSKEY %.*s", namebuf, 1584 (int)isc_buffer_usedlength(&buf), buffer); 1585 } 1586 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && 1587 revoked_ksk[dnskey.algorithm] != 255) 1588 revoked_ksk[dnskey.algorithm]++; 1589 else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && 1590 revoked_zsk[dnskey.algorithm] != 255) 1591 revoked_zsk[dnskey.algorithm]++; 1592 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) { 1593 if (dns_dnssec_selfsigns(&rdata, origin, &keyset, 1594 &keysigs, ISC_FALSE, mctx)) { 1595 if (ksk_algorithms[dnskey.algorithm] != 255) 1596 ksk_algorithms[dnskey.algorithm]++; 1597 goodksk = ISC_TRUE; 1598 } else { 1599 if (standby_ksk[dnskey.algorithm] != 255) 1600 standby_ksk[dnskey.algorithm]++; 1601 } 1602 } else if (dns_dnssec_selfsigns(&rdata, origin, &keyset, 1603 &keysigs, ISC_FALSE, mctx)) { 1604 if (zsk_algorithms[dnskey.algorithm] != 255) 1605 zsk_algorithms[dnskey.algorithm]++; 1606 goodzsk = ISC_TRUE; 1607 } else if (dns_dnssec_signs(&rdata, origin, &soaset, 1608 &soasigs, ISC_FALSE, mctx)) { 1609 if (zsk_algorithms[dnskey.algorithm] != 255) 1610 zsk_algorithms[dnskey.algorithm]++; 1611 } else { 1612 if (standby_zsk[dnskey.algorithm] != 255) 1613 standby_zsk[dnskey.algorithm]++; 1614 } 1615 dns_rdata_freestruct(&dnskey); 1616 dns_rdata_reset(&rdata); 1617 } 1618 dns_rdataset_disassociate(&keysigs); 1619 dns_rdataset_disassociate(&soaset); 1620 dns_rdataset_disassociate(&soasigs); 1621 if (dns_rdataset_isassociated(&nsecsigs)) 1622 dns_rdataset_disassociate(&nsecsigs); 1623 if (dns_rdataset_isassociated(&nsec3paramsigs)) 1624 dns_rdataset_disassociate(&nsec3paramsigs); 1625 1626 if (ignore_kskflag ) { 1627 if (!goodksk && !goodzsk) 1628 fatal("No self-signed DNSKEY found."); 1629 } else if (!goodksk) 1630 fatal("No self-signed KSK DNSKEY found. Supply an active\n" 1631 "key with the KSK flag set, or use '-P'."); 1632 1633 fprintf(stderr, "Verifying the zone using the following algorithms:"); 1634 for (i = 0; i < 256; i++) { 1635 if (ignore_kskflag) 1636 act_algorithms[i] = (ksk_algorithms[i] != 0 || 1637 zsk_algorithms[i] != 0) ? 1 : 0; 1638 else 1639 act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0; 1640 if (act_algorithms[i] != 0) { 1641 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1642 fprintf(stderr, " %s", algbuf); 1643 } 1644 } 1645 fprintf(stderr, ".\n"); 1646 1647 if (!ignore_kskflag && !keyset_kskonly) { 1648 for (i = 0; i < 256; i++) { 1649 /* 1650 * The counts should both be zero or both be non-zero. 1651 * Mark the algorithm as bad if this is not met. 1652 */ 1653 if ((ksk_algorithms[i] != 0) == 1654 (zsk_algorithms[i] != 0)) 1655 continue; 1656 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1657 fprintf(stderr, "Missing %s for algorithm %s\n", 1658 (ksk_algorithms[i] != 0) 1659 ? "ZSK" 1660 : "self-signed KSK", 1661 algbuf); 1662 bad_algorithms[i] = 1; 1663 } 1664 } 1665 1666 /* 1667 * Check that all the other records were signed by keys that are 1668 * present in the DNSKEY RRSET. 1669 */ 1670 1671 dns_fixedname_init(&fname); 1672 name = dns_fixedname_name(&fname); 1673 dns_fixedname_init(&fnextname); 1674 nextname = dns_fixedname_name(&fnextname); 1675 dns_fixedname_init(&fprevname); 1676 prevname = NULL; 1677 dns_fixedname_init(&fzonecut); 1678 zonecut = NULL; 1679 1680 result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter); 1681 check_result(result, "dns_db_createiterator()"); 1682 1683 result = dns_dbiterator_first(dbiter); 1684 check_result(result, "dns_dbiterator_first()"); 1685 1686 while (!done) { 1687 isc_boolean_t isdelegation = ISC_FALSE; 1688 1689 result = dns_dbiterator_current(dbiter, &node, name); 1690 check_dns_dbiterator_current(result); 1691 if (!dns_name_issubdomain(name, origin)) { 1692 check_no_nsec(name, node, db, ver); 1693 dns_db_detachnode(db, &node); 1694 result = dns_dbiterator_next(dbiter); 1695 if (result == ISC_R_NOMORE) 1696 done = ISC_TRUE; 1697 else 1698 check_result(result, "dns_dbiterator_next()"); 1699 continue; 1700 } 1701 if (is_delegation(db, ver, origin, name, node, NULL)) { 1702 zonecut = dns_fixedname_name(&fzonecut); 1703 dns_name_copy(name, zonecut, NULL); 1704 isdelegation = ISC_TRUE; 1705 } 1706 nextnode = NULL; 1707 result = dns_dbiterator_next(dbiter); 1708 while (result == ISC_R_SUCCESS) { 1709 result = dns_dbiterator_current(dbiter, &nextnode, 1710 nextname); 1711 check_dns_dbiterator_current(result); 1712 if (!dns_name_issubdomain(nextname, origin) || 1713 (zonecut != NULL && 1714 dns_name_issubdomain(nextname, zonecut))) 1715 { 1716 check_no_nsec(nextname, nextnode, db, ver); 1717 dns_db_detachnode(db, &nextnode); 1718 result = dns_dbiterator_next(dbiter); 1719 continue; 1720 } 1721 if (is_empty(db, ver, nextnode)) { 1722 dns_db_detachnode(db, &nextnode); 1723 result = dns_dbiterator_next(dbiter); 1724 continue; 1725 } 1726 dns_db_detachnode(db, &nextnode); 1727 break; 1728 } 1729 if (result == ISC_R_NOMORE) { 1730 done = ISC_TRUE; 1731 nextname = origin; 1732 } else if (result != ISC_R_SUCCESS) 1733 fatal("iterating through the database failed: %s", 1734 isc_result_totext(result)); 1735 result = verifynode(db, ver, origin, mctx, name, node, 1736 isdelegation, &keyset, act_algorithms, 1737 bad_algorithms, &nsecset, &nsec3paramset, 1738 nextname); 1739 if (vresult == ISC_R_UNSET) 1740 vresult = ISC_R_SUCCESS; 1741 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS) 1742 vresult = result; 1743 if (prevname != NULL) { 1744 result = verifyemptynodes(db, ver, origin, mctx, name, 1745 prevname, isdelegation, 1746 &nsec3paramset); 1747 } else 1748 prevname = dns_fixedname_name(&fprevname); 1749 dns_name_copy(name, prevname, NULL); 1750 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS) 1751 vresult = result; 1752 dns_db_detachnode(db, &node); 1753 } 1754 1755 dns_dbiterator_destroy(&dbiter); 1756 1757 result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter); 1758 check_result(result, "dns_db_createiterator()"); 1759 1760 for (result = dns_dbiterator_first(dbiter); 1761 result == ISC_R_SUCCESS; 1762 result = dns_dbiterator_next(dbiter) ) { 1763 result = dns_dbiterator_current(dbiter, &node, name); 1764 check_dns_dbiterator_current(result); 1765 result = verifynode(db, ver, origin, mctx, name, node, 1766 ISC_FALSE, &keyset, act_algorithms, 1767 bad_algorithms, NULL, NULL, NULL); 1768 check_result(result, "verifynode"); 1769 record_found(db, ver, mctx, name, node, &nsec3paramset); 1770 dns_db_detachnode(db, &node); 1771 } 1772 dns_dbiterator_destroy(&dbiter); 1773 1774 dns_rdataset_disassociate(&keyset); 1775 if (dns_rdataset_isassociated(&nsecset)) 1776 dns_rdataset_disassociate(&nsecset); 1777 if (dns_rdataset_isassociated(&nsec3paramset)) 1778 dns_rdataset_disassociate(&nsec3paramset); 1779 1780 result = verify_nsec3_chains(mctx); 1781 if (vresult == ISC_R_UNSET) 1782 vresult = ISC_R_SUCCESS; 1783 if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS) 1784 vresult = result; 1785 isc_heap_destroy(&expected_chains); 1786 isc_heap_destroy(&found_chains); 1787 1788 /* 1789 * If we made it this far, we have what we consider a properly signed 1790 * zone. Set the good flag. 1791 */ 1792 for (i = 0; i < 256; i++) { 1793 if (bad_algorithms[i] != 0) { 1794 if (first) 1795 fprintf(stderr, "The zone is not fully signed " 1796 "for the following algorithms:"); 1797 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1798 fprintf(stderr, " %s", algbuf); 1799 first = ISC_FALSE; 1800 } 1801 } 1802 if (!first) { 1803 fprintf(stderr, ".\n"); 1804 fatal("DNSSEC completeness test failed."); 1805 } 1806 1807 if (vresult != ISC_R_SUCCESS) 1808 fatal("DNSSEC completeness test failed (%s).", 1809 dns_result_totext(vresult)); 1810 1811 if (goodksk || ignore_kskflag) { 1812 /* 1813 * Print the success summary. 1814 */ 1815 fprintf(stderr, "Zone fully signed:\n"); 1816 for (i = 0; i < 256; i++) { 1817 if ((ksk_algorithms[i] != 0) || 1818 (standby_ksk[i] != 0) || 1819 (revoked_zsk[i] != 0) || 1820 (zsk_algorithms[i] != 0) || 1821 (standby_zsk[i] != 0) || 1822 (revoked_zsk[i] != 0)) { 1823 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1824 fprintf(stderr, "Algorithm: %s: KSKs: " 1825 "%u active, %u stand-by, %u revoked\n", 1826 algbuf, ksk_algorithms[i], 1827 standby_ksk[i], revoked_ksk[i]); 1828 fprintf(stderr, "%*sZSKs: " 1829 "%u active, %u %s, %u revoked\n", 1830 (int) strlen(algbuf) + 13, "", 1831 zsk_algorithms[i], 1832 standby_zsk[i], 1833 keyset_kskonly ? "present" : "stand-by", 1834 revoked_zsk[i]); 1835 } 1836 } 1837 } 1838 } 1839