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