1 /* $NetBSD: zoneverify.c,v 1.11 2024/02/21 22:52:08 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 /*! \file */ 17 18 #include <inttypes.h> 19 #include <stdarg.h> 20 #include <stdbool.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 #include <isc/base32.h> 25 #include <isc/buffer.h> 26 #include <isc/heap.h> 27 #include <isc/iterated_hash.h> 28 #include <isc/log.h> 29 #include <isc/mem.h> 30 #include <isc/region.h> 31 #include <isc/result.h> 32 #include <isc/types.h> 33 #include <isc/util.h> 34 35 #include <dns/db.h> 36 #include <dns/dbiterator.h> 37 #include <dns/dnssec.h> 38 #include <dns/fixedname.h> 39 #include <dns/keytable.h> 40 #include <dns/keyvalues.h> 41 #include <dns/log.h> 42 #include <dns/name.h> 43 #include <dns/nsec.h> 44 #include <dns/nsec3.h> 45 #include <dns/rdata.h> 46 #include <dns/rdataset.h> 47 #include <dns/rdatasetiter.h> 48 #include <dns/rdatastruct.h> 49 #include <dns/rdatatype.h> 50 #include <dns/secalg.h> 51 #include <dns/types.h> 52 #include <dns/zone.h> 53 #include <dns/zoneverify.h> 54 55 #include <dst/dst.h> 56 57 typedef struct vctx { 58 isc_mem_t *mctx; 59 dns_zone_t *zone; 60 dns_db_t *db; 61 dns_dbversion_t *ver; 62 dns_name_t *origin; 63 dns_keytable_t *secroots; 64 bool goodksk; 65 bool goodzsk; 66 dns_rdataset_t keyset; 67 dns_rdataset_t keysigs; 68 dns_rdataset_t soaset; 69 dns_rdataset_t soasigs; 70 dns_rdataset_t nsecset; 71 dns_rdataset_t nsecsigs; 72 dns_rdataset_t nsec3paramset; 73 dns_rdataset_t nsec3paramsigs; 74 unsigned char revoked_ksk[256]; 75 unsigned char revoked_zsk[256]; 76 unsigned char standby_ksk[256]; 77 unsigned char standby_zsk[256]; 78 unsigned char ksk_algorithms[256]; 79 unsigned char zsk_algorithms[256]; 80 unsigned char bad_algorithms[256]; 81 unsigned char act_algorithms[256]; 82 isc_heap_t *expected_chains; 83 isc_heap_t *found_chains; 84 } vctx_t; 85 86 struct nsec3_chain_fixed { 87 uint8_t hash; 88 uint8_t salt_length; 89 uint8_t next_length; 90 uint16_t iterations; 91 /* 92 * The following non-fixed-length data is stored in memory after the 93 * fields declared above for each NSEC3 chain element: 94 * 95 * unsigned char salt[salt_length]; 96 * unsigned char owner[next_length]; 97 * unsigned char next[next_length]; 98 */ 99 }; 100 101 /* 102 * Helper function used to calculate length of variable-length 103 * data section in object pointed to by 'chain'. 104 */ 105 static size_t 106 chain_length(struct nsec3_chain_fixed *chain) { 107 return (chain->salt_length + 2 * chain->next_length); 108 } 109 110 /*% 111 * Log a zone verification error described by 'fmt' and the variable arguments 112 * following it. Either use dns_zone_logv() or print to stderr, depending on 113 * whether the function was invoked from within named or by a standalone tool, 114 * respectively. 115 */ 116 static void 117 zoneverify_log_error(const vctx_t *vctx, const char *fmt, ...) { 118 va_list ap; 119 120 va_start(ap, fmt); 121 if (vctx->zone != NULL) { 122 dns_zone_logv(vctx->zone, DNS_LOGCATEGORY_GENERAL, 123 ISC_LOG_ERROR, NULL, fmt, ap); 124 } else { 125 vfprintf(stderr, fmt, ap); 126 fprintf(stderr, "\n"); 127 } 128 va_end(ap); 129 } 130 131 static bool 132 is_delegation(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 133 uint32_t *ttlp) { 134 dns_rdataset_t nsset; 135 isc_result_t result; 136 137 if (dns_name_equal(name, vctx->origin)) { 138 return (false); 139 } 140 141 dns_rdataset_init(&nsset); 142 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 143 dns_rdatatype_ns, 0, 0, &nsset, NULL); 144 if (dns_rdataset_isassociated(&nsset)) { 145 if (ttlp != NULL) { 146 *ttlp = nsset.ttl; 147 } 148 dns_rdataset_disassociate(&nsset); 149 } 150 151 return ((result == ISC_R_SUCCESS)); 152 } 153 154 /*% 155 * Return true if version 'ver' of database 'db' contains a DNAME RRset at 156 * 'node'; return false otherwise. 157 */ 158 static bool 159 has_dname(const vctx_t *vctx, dns_dbnode_t *node) { 160 dns_rdataset_t dnameset; 161 isc_result_t result; 162 163 dns_rdataset_init(&dnameset); 164 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 165 dns_rdatatype_dname, 0, 0, &dnameset, 166 NULL); 167 if (dns_rdataset_isassociated(&dnameset)) { 168 dns_rdataset_disassociate(&dnameset); 169 } 170 171 return ((result == ISC_R_SUCCESS)); 172 } 173 174 static bool 175 goodsig(const vctx_t *vctx, dns_rdata_t *sigrdata, const dns_name_t *name, 176 dst_key_t **dstkeys, size_t nkeys, dns_rdataset_t *rdataset) { 177 dns_rdata_rrsig_t sig; 178 isc_result_t result; 179 180 result = dns_rdata_tostruct(sigrdata, &sig, NULL); 181 RUNTIME_CHECK(result == ISC_R_SUCCESS); 182 183 for (size_t key = 0; key < nkeys; key++) { 184 if (sig.algorithm != dst_key_alg(dstkeys[key]) || 185 sig.keyid != dst_key_id(dstkeys[key]) || 186 !dns_name_equal(&sig.signer, vctx->origin)) 187 { 188 continue; 189 } 190 result = dns_dnssec_verify(name, rdataset, dstkeys[key], false, 191 0, vctx->mctx, sigrdata, NULL); 192 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) { 193 return (true); 194 } 195 } 196 return (false); 197 } 198 199 static bool 200 nsec_bitmap_equal(dns_rdata_nsec_t *nsec, dns_rdata_t *rdata) { 201 isc_result_t result; 202 dns_rdata_nsec_t tmpnsec; 203 204 result = dns_rdata_tostruct(rdata, &tmpnsec, NULL); 205 RUNTIME_CHECK(result == ISC_R_SUCCESS); 206 207 if (nsec->len != tmpnsec.len || 208 memcmp(nsec->typebits, tmpnsec.typebits, nsec->len) != 0) 209 { 210 return (false); 211 } 212 return (true); 213 } 214 215 static isc_result_t 216 verifynsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 217 const dns_name_t *nextname, isc_result_t *vresult) { 218 unsigned char buffer[DNS_NSEC_BUFFERSIZE]; 219 char namebuf[DNS_NAME_FORMATSIZE]; 220 char nextbuf[DNS_NAME_FORMATSIZE]; 221 char found[DNS_NAME_FORMATSIZE]; 222 dns_rdataset_t rdataset; 223 dns_rdata_t rdata = DNS_RDATA_INIT; 224 dns_rdata_t tmprdata = DNS_RDATA_INIT; 225 dns_rdata_nsec_t nsec; 226 isc_result_t result; 227 228 dns_rdataset_init(&rdataset); 229 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 230 dns_rdatatype_nsec, 0, 0, &rdataset, NULL); 231 if (result != ISC_R_SUCCESS) { 232 dns_name_format(name, namebuf, sizeof(namebuf)); 233 zoneverify_log_error(vctx, "Missing NSEC record for %s", 234 namebuf); 235 *vresult = ISC_R_FAILURE; 236 result = ISC_R_SUCCESS; 237 goto done; 238 } 239 240 result = dns_rdataset_first(&rdataset); 241 if (result != ISC_R_SUCCESS) { 242 zoneverify_log_error(vctx, "dns_rdataset_first(): %s", 243 isc_result_totext(result)); 244 goto done; 245 } 246 247 dns_rdataset_current(&rdataset, &rdata); 248 result = dns_rdata_tostruct(&rdata, &nsec, NULL); 249 RUNTIME_CHECK(result == ISC_R_SUCCESS); 250 251 /* Check next name is consistent */ 252 if (!dns_name_equal(&nsec.next, nextname)) { 253 dns_name_format(name, namebuf, sizeof(namebuf)); 254 dns_name_format(nextname, nextbuf, sizeof(nextbuf)); 255 dns_name_format(&nsec.next, found, sizeof(found)); 256 zoneverify_log_error(vctx, 257 "Bad NSEC record for %s, next name " 258 "mismatch (expected:%s, found:%s)", 259 namebuf, nextbuf, found); 260 *vresult = ISC_R_FAILURE; 261 goto done; 262 } 263 264 /* Check bit map is consistent */ 265 result = dns_nsec_buildrdata(vctx->db, vctx->ver, node, nextname, 266 buffer, &tmprdata); 267 if (result != ISC_R_SUCCESS) { 268 zoneverify_log_error(vctx, "dns_nsec_buildrdata(): %s", 269 isc_result_totext(result)); 270 goto done; 271 } 272 if (!nsec_bitmap_equal(&nsec, &tmprdata)) { 273 dns_name_format(name, namebuf, sizeof(namebuf)); 274 zoneverify_log_error(vctx, 275 "Bad NSEC record for %s, bit map " 276 "mismatch", 277 namebuf); 278 *vresult = ISC_R_FAILURE; 279 goto done; 280 } 281 282 result = dns_rdataset_next(&rdataset); 283 if (result != ISC_R_NOMORE) { 284 dns_name_format(name, namebuf, sizeof(namebuf)); 285 zoneverify_log_error(vctx, "Multiple NSEC records for %s", 286 namebuf); 287 *vresult = ISC_R_FAILURE; 288 goto done; 289 } 290 291 *vresult = ISC_R_SUCCESS; 292 result = ISC_R_SUCCESS; 293 294 done: 295 if (dns_rdataset_isassociated(&rdataset)) { 296 dns_rdataset_disassociate(&rdataset); 297 } 298 299 return (result); 300 } 301 302 static isc_result_t 303 check_no_rrsig(const vctx_t *vctx, const dns_rdataset_t *rdataset, 304 const dns_name_t *name, dns_dbnode_t *node) { 305 char namebuf[DNS_NAME_FORMATSIZE]; 306 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 307 dns_rdataset_t sigrdataset; 308 dns_rdatasetiter_t *rdsiter = NULL; 309 isc_result_t result; 310 311 dns_rdataset_init(&sigrdataset); 312 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 313 if (result != ISC_R_SUCCESS) { 314 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 315 isc_result_totext(result)); 316 return (result); 317 } 318 for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; 319 result = dns_rdatasetiter_next(rdsiter)) 320 { 321 dns_rdatasetiter_current(rdsiter, &sigrdataset); 322 if (sigrdataset.type == dns_rdatatype_rrsig && 323 sigrdataset.covers == rdataset->type) 324 { 325 dns_name_format(name, namebuf, sizeof(namebuf)); 326 dns_rdatatype_format(rdataset->type, typebuf, 327 sizeof(typebuf)); 328 zoneverify_log_error( 329 vctx, 330 "Warning: Found unexpected signatures " 331 "for %s/%s", 332 namebuf, typebuf); 333 break; 334 } 335 dns_rdataset_disassociate(&sigrdataset); 336 } 337 if (dns_rdataset_isassociated(&sigrdataset)) { 338 dns_rdataset_disassociate(&sigrdataset); 339 } 340 dns_rdatasetiter_destroy(&rdsiter); 341 342 return (ISC_R_SUCCESS); 343 } 344 345 static bool 346 chain_compare(void *arg1, void *arg2) { 347 struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2; 348 /* 349 * Do each element in turn to get a stable sort. 350 */ 351 if (e1->hash < e2->hash) { 352 return (true); 353 } 354 if (e1->hash > e2->hash) { 355 return (false); 356 } 357 if (e1->iterations < e2->iterations) { 358 return (true); 359 } 360 if (e1->iterations > e2->iterations) { 361 return (false); 362 } 363 if (e1->salt_length < e2->salt_length) { 364 return (true); 365 } 366 if (e1->salt_length > e2->salt_length) { 367 return (false); 368 } 369 if (e1->next_length < e2->next_length) { 370 return (true); 371 } 372 if (e1->next_length > e2->next_length) { 373 return (false); 374 } 375 if (memcmp(e1 + 1, e2 + 1, chain_length(e1)) < 0) { 376 return (true); 377 } 378 return (false); 379 } 380 381 static bool 382 chain_equal(const struct nsec3_chain_fixed *e1, 383 const struct nsec3_chain_fixed *e2, size_t data_length) { 384 if (e1->hash != e2->hash) { 385 return (false); 386 } 387 if (e1->iterations != e2->iterations) { 388 return (false); 389 } 390 if (e1->salt_length != e2->salt_length) { 391 return (false); 392 } 393 if (e1->next_length != e2->next_length) { 394 return (false); 395 } 396 397 return (memcmp(e1 + 1, e2 + 1, data_length) == 0); 398 } 399 400 static void 401 record_nsec3(const vctx_t *vctx, const unsigned char *rawhash, 402 const dns_rdata_nsec3_t *nsec3, isc_heap_t *chains) { 403 struct nsec3_chain_fixed *element = NULL; 404 unsigned char *cp = NULL; 405 size_t len; 406 407 len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length; 408 409 element = isc_mem_get(vctx->mctx, len); 410 memset(element, 0, len); 411 element->hash = nsec3->hash; 412 element->salt_length = nsec3->salt_length; 413 element->next_length = nsec3->next_length; 414 element->iterations = nsec3->iterations; 415 cp = (unsigned char *)(element + 1); 416 memmove(cp, nsec3->salt, nsec3->salt_length); 417 cp += nsec3->salt_length; 418 memmove(cp, rawhash, nsec3->next_length); 419 cp += nsec3->next_length; 420 memmove(cp, nsec3->next, nsec3->next_length); 421 isc_heap_insert(chains, element); 422 } 423 424 /* 425 * Check whether any NSEC3 within 'rdataset' matches the parameters in 426 * 'nsec3param'. 427 */ 428 static isc_result_t 429 find_nsec3_match(const dns_rdata_nsec3param_t *nsec3param, 430 dns_rdataset_t *rdataset, size_t rhsize, 431 dns_rdata_nsec3_t *nsec3_match) { 432 isc_result_t result; 433 434 /* 435 * Find matching NSEC3 record. 436 */ 437 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 438 result = dns_rdataset_next(rdataset)) 439 { 440 dns_rdata_t rdata = DNS_RDATA_INIT; 441 dns_rdataset_current(rdataset, &rdata); 442 result = dns_rdata_tostruct(&rdata, nsec3_match, NULL); 443 RUNTIME_CHECK(result == ISC_R_SUCCESS); 444 if (nsec3_match->hash == nsec3param->hash && 445 nsec3_match->next_length == rhsize && 446 nsec3_match->iterations == nsec3param->iterations && 447 nsec3_match->salt_length == nsec3param->salt_length && 448 memcmp(nsec3_match->salt, nsec3param->salt, 449 nsec3param->salt_length) == 0) 450 { 451 return (ISC_R_SUCCESS); 452 } 453 } 454 455 return (result); 456 } 457 458 static isc_result_t 459 match_nsec3(const vctx_t *vctx, const dns_name_t *name, 460 const dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset, 461 const unsigned char types[8192], unsigned int maxtype, 462 const unsigned char *rawhash, size_t rhsize, 463 isc_result_t *vresult) { 464 unsigned char cbm[8244]; 465 char namebuf[DNS_NAME_FORMATSIZE]; 466 dns_rdata_nsec3_t nsec3; 467 isc_result_t result; 468 unsigned int len; 469 470 result = find_nsec3_match(nsec3param, rdataset, rhsize, &nsec3); 471 if (result != ISC_R_SUCCESS) { 472 dns_name_format(name, namebuf, sizeof(namebuf)); 473 zoneverify_log_error(vctx, "Missing NSEC3 record for %s", 474 namebuf); 475 *vresult = result; 476 return (ISC_R_SUCCESS); 477 } 478 479 /* 480 * Check the type list. 481 */ 482 len = dns_nsec_compressbitmap(cbm, types, maxtype); 483 if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) { 484 dns_name_format(name, namebuf, sizeof(namebuf)); 485 zoneverify_log_error(vctx, 486 "Bad NSEC3 record for %s, bit map " 487 "mismatch", 488 namebuf); 489 *vresult = ISC_R_FAILURE; 490 return (ISC_R_SUCCESS); 491 } 492 493 /* 494 * Record chain. 495 */ 496 record_nsec3(vctx, rawhash, &nsec3, vctx->expected_chains); 497 498 /* 499 * Make sure there is only one NSEC3 record with this set of 500 * parameters. 501 */ 502 for (result = dns_rdataset_next(rdataset); result == ISC_R_SUCCESS; 503 result = dns_rdataset_next(rdataset)) 504 { 505 dns_rdata_t rdata = DNS_RDATA_INIT; 506 dns_rdataset_current(rdataset, &rdata); 507 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 508 RUNTIME_CHECK(result == ISC_R_SUCCESS); 509 if (nsec3.hash == nsec3param->hash && 510 nsec3.iterations == nsec3param->iterations && 511 nsec3.salt_length == nsec3param->salt_length && 512 memcmp(nsec3.salt, nsec3param->salt, nsec3.salt_length) == 513 0) 514 { 515 dns_name_format(name, namebuf, sizeof(namebuf)); 516 zoneverify_log_error(vctx, 517 "Multiple NSEC3 records with the " 518 "same parameter set for %s", 519 namebuf); 520 *vresult = DNS_R_DUPLICATE; 521 return (ISC_R_SUCCESS); 522 } 523 } 524 if (result != ISC_R_NOMORE) { 525 return (result); 526 } 527 528 *vresult = ISC_R_SUCCESS; 529 530 return (ISC_R_SUCCESS); 531 } 532 533 static bool 534 innsec3params(const dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) { 535 dns_rdata_nsec3param_t nsec3param; 536 isc_result_t result; 537 538 for (result = dns_rdataset_first(nsec3paramset); 539 result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset)) 540 { 541 dns_rdata_t rdata = DNS_RDATA_INIT; 542 543 dns_rdataset_current(nsec3paramset, &rdata); 544 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); 545 RUNTIME_CHECK(result == ISC_R_SUCCESS); 546 if (nsec3param.flags == 0 && nsec3param.hash == nsec3->hash && 547 nsec3param.iterations == nsec3->iterations && 548 nsec3param.salt_length == nsec3->salt_length && 549 memcmp(nsec3param.salt, nsec3->salt, nsec3->salt_length) == 550 0) 551 { 552 return (true); 553 } 554 } 555 return (false); 556 } 557 558 static isc_result_t 559 record_found(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 560 dns_rdataset_t *nsec3paramset) { 561 unsigned char owner[NSEC3_MAX_HASH_LENGTH]; 562 dns_rdata_nsec3_t nsec3; 563 dns_rdataset_t rdataset; 564 dns_label_t hashlabel; 565 isc_buffer_t b; 566 isc_result_t result; 567 568 if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset)) 569 { 570 return (ISC_R_SUCCESS); 571 } 572 573 dns_rdataset_init(&rdataset); 574 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 575 dns_rdatatype_nsec3, 0, 0, &rdataset, 576 NULL); 577 if (result != ISC_R_SUCCESS) { 578 return (ISC_R_SUCCESS); 579 } 580 581 dns_name_getlabel(name, 0, &hashlabel); 582 isc_region_consume(&hashlabel, 1); 583 isc_buffer_init(&b, owner, sizeof(owner)); 584 result = isc_base32hex_decoderegion(&hashlabel, &b); 585 if (result != ISC_R_SUCCESS) { 586 result = ISC_R_SUCCESS; 587 goto cleanup; 588 } 589 590 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; 591 result = dns_rdataset_next(&rdataset)) 592 { 593 dns_rdata_t rdata = DNS_RDATA_INIT; 594 dns_rdataset_current(&rdataset, &rdata); 595 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 596 RUNTIME_CHECK(result == ISC_R_SUCCESS); 597 if (nsec3.next_length != isc_buffer_usedlength(&b)) { 598 continue; 599 } 600 601 /* 602 * We only care about NSEC3 records that match a NSEC3PARAM 603 * record. 604 */ 605 if (!innsec3params(&nsec3, nsec3paramset)) { 606 continue; 607 } 608 609 /* 610 * Record chain. 611 */ 612 record_nsec3(vctx, owner, &nsec3, vctx->found_chains); 613 } 614 result = ISC_R_SUCCESS; 615 616 cleanup: 617 dns_rdataset_disassociate(&rdataset); 618 return (result); 619 } 620 621 static isc_result_t 622 isoptout(const vctx_t *vctx, const dns_rdata_nsec3param_t *nsec3param, 623 bool *optout) { 624 dns_rdataset_t rdataset; 625 dns_rdata_t rdata = DNS_RDATA_INIT; 626 dns_rdata_nsec3_t nsec3; 627 dns_fixedname_t fixed; 628 dns_name_t *hashname; 629 isc_result_t result; 630 dns_dbnode_t *node = NULL; 631 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; 632 size_t rhsize = sizeof(rawhash); 633 634 dns_fixedname_init(&fixed); 635 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, vctx->origin, 636 vctx->origin, nsec3param->hash, 637 nsec3param->iterations, nsec3param->salt, 638 nsec3param->salt_length); 639 if (result != ISC_R_SUCCESS) { 640 zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s", 641 isc_result_totext(result)); 642 return (result); 643 } 644 645 dns_rdataset_init(&rdataset); 646 hashname = dns_fixedname_name(&fixed); 647 result = dns_db_findnsec3node(vctx->db, hashname, false, &node); 648 if (result == ISC_R_SUCCESS) { 649 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 650 dns_rdatatype_nsec3, 0, 0, 651 &rdataset, NULL); 652 } 653 if (result != ISC_R_SUCCESS) { 654 *optout = false; 655 result = ISC_R_SUCCESS; 656 goto done; 657 } 658 659 result = dns_rdataset_first(&rdataset); 660 if (result != ISC_R_SUCCESS) { 661 zoneverify_log_error(vctx, "dns_rdataset_first(): %s", 662 isc_result_totext(result)); 663 goto done; 664 } 665 666 dns_rdataset_current(&rdataset, &rdata); 667 668 result = dns_rdata_tostruct(&rdata, &nsec3, NULL); 669 RUNTIME_CHECK(result == ISC_R_SUCCESS); 670 *optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0); 671 672 done: 673 if (dns_rdataset_isassociated(&rdataset)) { 674 dns_rdataset_disassociate(&rdataset); 675 } 676 if (node != NULL) { 677 dns_db_detachnode(vctx->db, &node); 678 } 679 680 return (result); 681 } 682 683 static isc_result_t 684 verifynsec3(const vctx_t *vctx, const dns_name_t *name, 685 const dns_rdata_t *rdata, bool delegation, bool empty, 686 const unsigned char types[8192], unsigned int maxtype, 687 isc_result_t *vresult) { 688 char namebuf[DNS_NAME_FORMATSIZE]; 689 char hashbuf[DNS_NAME_FORMATSIZE]; 690 dns_rdataset_t rdataset; 691 dns_rdata_nsec3param_t nsec3param; 692 dns_fixedname_t fixed; 693 dns_name_t *hashname; 694 isc_result_t result, tvresult = ISC_R_UNSET; 695 dns_dbnode_t *node = NULL; 696 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH]; 697 size_t rhsize = sizeof(rawhash); 698 bool optout = false; 699 700 result = dns_rdata_tostruct(rdata, &nsec3param, NULL); 701 RUNTIME_CHECK(result == ISC_R_SUCCESS); 702 703 if (nsec3param.flags != 0) { 704 return (ISC_R_SUCCESS); 705 } 706 707 if (!dns_nsec3_supportedhash(nsec3param.hash)) { 708 return (ISC_R_SUCCESS); 709 } 710 711 if (nsec3param.iterations > DNS_NSEC3_MAXITERATIONS) { 712 result = DNS_R_NSEC3ITERRANGE; 713 zoneverify_log_error(vctx, "verifynsec3: %s", 714 isc_result_totext(result)); 715 return (result); 716 } 717 718 result = isoptout(vctx, &nsec3param, &optout); 719 if (result != ISC_R_SUCCESS) { 720 return (result); 721 } 722 723 dns_fixedname_init(&fixed); 724 result = dns_nsec3_hashname( 725 &fixed, rawhash, &rhsize, name, vctx->origin, nsec3param.hash, 726 nsec3param.iterations, nsec3param.salt, nsec3param.salt_length); 727 if (result != ISC_R_SUCCESS) { 728 zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s", 729 isc_result_totext(result)); 730 return (result); 731 } 732 733 /* 734 * We don't use dns_db_find() here as it works with the chosen 735 * nsec3 chain and we may also be called with uncommitted data 736 * from dnssec-signzone so the secure status of the zone may not 737 * be up to date. 738 */ 739 dns_rdataset_init(&rdataset); 740 hashname = dns_fixedname_name(&fixed); 741 result = dns_db_findnsec3node(vctx->db, hashname, false, &node); 742 if (result == ISC_R_SUCCESS) { 743 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 744 dns_rdatatype_nsec3, 0, 0, 745 &rdataset, NULL); 746 } 747 if (result != ISC_R_SUCCESS && 748 (!delegation || (empty && !optout) || 749 (!empty && dns_nsec_isset(types, dns_rdatatype_ds)))) 750 { 751 dns_name_format(name, namebuf, sizeof(namebuf)); 752 dns_name_format(hashname, hashbuf, sizeof(hashbuf)); 753 zoneverify_log_error(vctx, "Missing NSEC3 record for %s (%s)", 754 namebuf, hashbuf); 755 } else if (result == ISC_R_NOTFOUND && delegation && (!empty || optout)) 756 { 757 result = ISC_R_SUCCESS; 758 } else if (result == ISC_R_SUCCESS) { 759 result = match_nsec3(vctx, name, &nsec3param, &rdataset, types, 760 maxtype, rawhash, rhsize, &tvresult); 761 if (result != ISC_R_SUCCESS) { 762 goto done; 763 } 764 result = tvresult; 765 } 766 767 *vresult = result; 768 result = ISC_R_SUCCESS; 769 770 done: 771 if (dns_rdataset_isassociated(&rdataset)) { 772 dns_rdataset_disassociate(&rdataset); 773 } 774 if (node != NULL) { 775 dns_db_detachnode(vctx->db, &node); 776 } 777 778 return (result); 779 } 780 781 static isc_result_t 782 verifynsec3s(const vctx_t *vctx, const dns_name_t *name, 783 dns_rdataset_t *nsec3paramset, bool delegation, bool empty, 784 const unsigned char types[8192], unsigned int maxtype, 785 isc_result_t *vresult) { 786 isc_result_t result; 787 788 for (result = dns_rdataset_first(nsec3paramset); 789 result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset)) 790 { 791 dns_rdata_t rdata = DNS_RDATA_INIT; 792 793 dns_rdataset_current(nsec3paramset, &rdata); 794 result = verifynsec3(vctx, name, &rdata, delegation, empty, 795 types, maxtype, vresult); 796 if (result != ISC_R_SUCCESS) { 797 return (result); 798 } 799 if (*vresult != ISC_R_SUCCESS) { 800 break; 801 } 802 } 803 if (result == ISC_R_NOMORE) { 804 result = ISC_R_SUCCESS; 805 } 806 return (result); 807 } 808 809 static isc_result_t 810 verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name, 811 dns_dbnode_t *node, dst_key_t **dstkeys, size_t nkeys) { 812 unsigned char set_algorithms[256] = { 0 }; 813 char namebuf[DNS_NAME_FORMATSIZE]; 814 char algbuf[DNS_SECALG_FORMATSIZE]; 815 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 816 dns_rdataset_t sigrdataset; 817 dns_rdatasetiter_t *rdsiter = NULL; 818 isc_result_t result; 819 820 dns_rdataset_init(&sigrdataset); 821 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 822 if (result != ISC_R_SUCCESS) { 823 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 824 isc_result_totext(result)); 825 return (result); 826 } 827 for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS; 828 result = dns_rdatasetiter_next(rdsiter)) 829 { 830 dns_rdatasetiter_current(rdsiter, &sigrdataset); 831 if (sigrdataset.type == dns_rdatatype_rrsig && 832 sigrdataset.covers == rdataset->type) 833 { 834 break; 835 } 836 dns_rdataset_disassociate(&sigrdataset); 837 } 838 if (result != ISC_R_SUCCESS) { 839 dns_name_format(name, namebuf, sizeof(namebuf)); 840 dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); 841 zoneverify_log_error(vctx, "No signatures for %s/%s", namebuf, 842 typebuf); 843 for (size_t i = 0; i < ARRAY_SIZE(set_algorithms); i++) { 844 if (vctx->act_algorithms[i] != 0) { 845 vctx->bad_algorithms[i] = 1; 846 } 847 } 848 result = ISC_R_SUCCESS; 849 goto done; 850 } 851 852 for (result = dns_rdataset_first(&sigrdataset); result == ISC_R_SUCCESS; 853 result = dns_rdataset_next(&sigrdataset)) 854 { 855 dns_rdata_t rdata = DNS_RDATA_INIT; 856 dns_rdata_rrsig_t sig; 857 858 dns_rdataset_current(&sigrdataset, &rdata); 859 result = dns_rdata_tostruct(&rdata, &sig, NULL); 860 RUNTIME_CHECK(result == ISC_R_SUCCESS); 861 if (rdataset->ttl != sig.originalttl) { 862 dns_name_format(name, namebuf, sizeof(namebuf)); 863 dns_rdatatype_format(rdataset->type, typebuf, 864 sizeof(typebuf)); 865 zoneverify_log_error(vctx, 866 "TTL mismatch for " 867 "%s %s keytag %u", 868 namebuf, typebuf, sig.keyid); 869 continue; 870 } 871 if ((set_algorithms[sig.algorithm] != 0) || 872 (vctx->act_algorithms[sig.algorithm] == 0)) 873 { 874 continue; 875 } 876 if (goodsig(vctx, &rdata, name, dstkeys, nkeys, rdataset)) { 877 dns_rdataset_settrust(rdataset, dns_trust_secure); 878 dns_rdataset_settrust(&sigrdataset, dns_trust_secure); 879 set_algorithms[sig.algorithm] = 1; 880 } 881 } 882 result = ISC_R_SUCCESS; 883 884 if (memcmp(set_algorithms, vctx->act_algorithms, 885 sizeof(set_algorithms)) != 0) 886 { 887 dns_name_format(name, namebuf, sizeof(namebuf)); 888 dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf)); 889 for (size_t i = 0; i < ARRAY_SIZE(set_algorithms); i++) { 890 if ((vctx->act_algorithms[i] != 0) && 891 (set_algorithms[i] == 0)) 892 { 893 dns_secalg_format(i, algbuf, sizeof(algbuf)); 894 zoneverify_log_error(vctx, 895 "No correct %s signature " 896 "for %s %s", 897 algbuf, namebuf, typebuf); 898 vctx->bad_algorithms[i] = 1; 899 } 900 } 901 } 902 903 done: 904 if (dns_rdataset_isassociated(&sigrdataset)) { 905 dns_rdataset_disassociate(&sigrdataset); 906 } 907 dns_rdatasetiter_destroy(&rdsiter); 908 909 return (result); 910 } 911 912 static isc_result_t 913 verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node, 914 bool delegation, dst_key_t **dstkeys, size_t nkeys, 915 dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset, 916 const dns_name_t *nextname, isc_result_t *vresult) { 917 unsigned char types[8192] = { 0 }; 918 unsigned int maxtype = 0; 919 dns_rdataset_t rdataset; 920 dns_rdatasetiter_t *rdsiter = NULL; 921 isc_result_t result, tvresult = ISC_R_UNSET; 922 923 REQUIRE(vresult != NULL || (nsecset == NULL && nsec3paramset == NULL)); 924 925 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 926 if (result != ISC_R_SUCCESS) { 927 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 928 isc_result_totext(result)); 929 return (result); 930 } 931 932 result = dns_rdatasetiter_first(rdsiter); 933 dns_rdataset_init(&rdataset); 934 while (result == ISC_R_SUCCESS) { 935 dns_rdatasetiter_current(rdsiter, &rdataset); 936 /* 937 * If we are not at a delegation then everything should be 938 * signed. If we are at a delegation then only the DS set 939 * is signed. The NS set is not signed at a delegation but 940 * its existence is recorded in the bit map. Anything else 941 * other than NSEC and DS is not signed at a delegation. 942 */ 943 if (rdataset.type != dns_rdatatype_rrsig && 944 rdataset.type != dns_rdatatype_dnskey && 945 (!delegation || rdataset.type == dns_rdatatype_ds || 946 rdataset.type == dns_rdatatype_nsec)) 947 { 948 result = verifyset(vctx, &rdataset, name, node, dstkeys, 949 nkeys); 950 if (result != ISC_R_SUCCESS) { 951 dns_rdataset_disassociate(&rdataset); 952 dns_rdatasetiter_destroy(&rdsiter); 953 return (result); 954 } 955 dns_nsec_setbit(types, rdataset.type, 1); 956 if (rdataset.type > maxtype) { 957 maxtype = rdataset.type; 958 } 959 } else if (rdataset.type != dns_rdatatype_rrsig && 960 rdataset.type != dns_rdatatype_dnskey) 961 { 962 if (rdataset.type == dns_rdatatype_ns) { 963 dns_nsec_setbit(types, rdataset.type, 1); 964 } 965 result = check_no_rrsig(vctx, &rdataset, name, node); 966 if (result != ISC_R_SUCCESS) { 967 dns_rdataset_disassociate(&rdataset); 968 dns_rdatasetiter_destroy(&rdsiter); 969 return (result); 970 } 971 } else { 972 dns_nsec_setbit(types, rdataset.type, 1); 973 } 974 dns_rdataset_disassociate(&rdataset); 975 result = dns_rdatasetiter_next(rdsiter); 976 } 977 dns_rdatasetiter_destroy(&rdsiter); 978 if (result != ISC_R_NOMORE) { 979 zoneverify_log_error(vctx, "rdataset iteration failed: %s", 980 isc_result_totext(result)); 981 return (result); 982 } 983 984 if (vresult == NULL) { 985 return (ISC_R_SUCCESS); 986 } 987 988 *vresult = ISC_R_SUCCESS; 989 990 if (nsecset != NULL && dns_rdataset_isassociated(nsecset)) { 991 result = verifynsec(vctx, name, node, nextname, &tvresult); 992 if (result != ISC_R_SUCCESS) { 993 return (result); 994 } 995 *vresult = tvresult; 996 } 997 998 if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) { 999 result = verifynsec3s(vctx, name, nsec3paramset, delegation, 1000 false, types, maxtype, &tvresult); 1001 if (result != ISC_R_SUCCESS) { 1002 return (result); 1003 } 1004 if (*vresult == ISC_R_SUCCESS) { 1005 *vresult = tvresult; 1006 } 1007 } 1008 1009 return (ISC_R_SUCCESS); 1010 } 1011 1012 static isc_result_t 1013 is_empty(const vctx_t *vctx, dns_dbnode_t *node, bool *empty) { 1014 dns_rdatasetiter_t *rdsiter = NULL; 1015 isc_result_t result; 1016 1017 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, 0, &rdsiter); 1018 if (result != ISC_R_SUCCESS) { 1019 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s", 1020 isc_result_totext(result)); 1021 return (result); 1022 } 1023 result = dns_rdatasetiter_first(rdsiter); 1024 dns_rdatasetiter_destroy(&rdsiter); 1025 1026 *empty = (result == ISC_R_NOMORE); 1027 1028 return (ISC_R_SUCCESS); 1029 } 1030 1031 static isc_result_t 1032 check_no_nsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node) { 1033 bool nsec_exists = false; 1034 dns_rdataset_t rdataset; 1035 isc_result_t result; 1036 1037 dns_rdataset_init(&rdataset); 1038 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1039 dns_rdatatype_nsec, 0, 0, &rdataset, NULL); 1040 if (result != ISC_R_NOTFOUND) { 1041 char namebuf[DNS_NAME_FORMATSIZE]; 1042 dns_name_format(name, namebuf, sizeof(namebuf)); 1043 zoneverify_log_error(vctx, "unexpected NSEC RRset at %s", 1044 namebuf); 1045 nsec_exists = true; 1046 } 1047 1048 if (dns_rdataset_isassociated(&rdataset)) { 1049 dns_rdataset_disassociate(&rdataset); 1050 } 1051 1052 return (nsec_exists ? ISC_R_FAILURE : ISC_R_SUCCESS); 1053 } 1054 1055 static void 1056 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) { 1057 size_t len; 1058 1059 len = sizeof(*e) + e->salt_length + 2 * e->next_length; 1060 isc_mem_put(mctx, e, len); 1061 } 1062 1063 static void 1064 free_element_heap(void *element, void *uap) { 1065 struct nsec3_chain_fixed *e = (struct nsec3_chain_fixed *)element; 1066 isc_mem_t *mctx = (isc_mem_t *)uap; 1067 1068 free_element(mctx, e); 1069 } 1070 1071 static bool 1072 _checknext(const vctx_t *vctx, const struct nsec3_chain_fixed *first, 1073 const struct nsec3_chain_fixed *e) { 1074 char buf[512]; 1075 const unsigned char *d1 = (const unsigned char *)(first + 1); 1076 const unsigned char *d2 = (const unsigned char *)(e + 1); 1077 isc_buffer_t b; 1078 isc_region_t sr; 1079 1080 d1 += first->salt_length + first->next_length; 1081 d2 += e->salt_length; 1082 1083 if (memcmp(d1, d2, first->next_length) == 0) { 1084 return (true); 1085 } 1086 1087 DE_CONST(d1 - first->next_length, sr.base); 1088 sr.length = first->next_length; 1089 isc_buffer_init(&b, buf, sizeof(buf)); 1090 isc_base32hex_totext(&sr, 1, "", &b); 1091 zoneverify_log_error(vctx, "Break in NSEC3 chain at: %.*s", 1092 (int)isc_buffer_usedlength(&b), buf); 1093 1094 DE_CONST(d1, sr.base); 1095 sr.length = first->next_length; 1096 isc_buffer_init(&b, buf, sizeof(buf)); 1097 isc_base32hex_totext(&sr, 1, "", &b); 1098 zoneverify_log_error(vctx, "Expected: %.*s", 1099 (int)isc_buffer_usedlength(&b), buf); 1100 1101 DE_CONST(d2, sr.base); 1102 sr.length = first->next_length; 1103 isc_buffer_init(&b, buf, sizeof(buf)); 1104 isc_base32hex_totext(&sr, 1, "", &b); 1105 zoneverify_log_error(vctx, "Found: %.*s", 1106 (int)isc_buffer_usedlength(&b), buf); 1107 1108 return (false); 1109 } 1110 1111 static bool 1112 checknext(isc_mem_t *mctx, const vctx_t *vctx, 1113 const struct nsec3_chain_fixed *first, struct nsec3_chain_fixed *prev, 1114 const struct nsec3_chain_fixed *cur) { 1115 bool result = _checknext(vctx, prev, cur); 1116 1117 if (prev != first) { 1118 free_element(mctx, prev); 1119 } 1120 1121 return (result); 1122 } 1123 1124 static bool 1125 checklast(isc_mem_t *mctx, const vctx_t *vctx, struct nsec3_chain_fixed *first, 1126 struct nsec3_chain_fixed *prev) { 1127 bool result = _checknext(vctx, prev, first); 1128 if (prev != first) { 1129 free_element(mctx, prev); 1130 } 1131 free_element(mctx, first); 1132 1133 return (result); 1134 } 1135 1136 static isc_result_t 1137 verify_nsec3_chains(const vctx_t *vctx, isc_mem_t *mctx) { 1138 isc_result_t result = ISC_R_SUCCESS; 1139 struct nsec3_chain_fixed *e, *f = NULL; 1140 struct nsec3_chain_fixed *first = NULL, *prev = NULL; 1141 1142 while ((e = isc_heap_element(vctx->expected_chains, 1)) != NULL) { 1143 isc_heap_delete(vctx->expected_chains, 1); 1144 if (f == NULL) { 1145 f = isc_heap_element(vctx->found_chains, 1); 1146 } 1147 if (f != NULL) { 1148 isc_heap_delete(vctx->found_chains, 1); 1149 1150 /* 1151 * Check that they match. 1152 */ 1153 if (chain_equal(e, f, chain_length(e))) { 1154 free_element(mctx, f); 1155 f = NULL; 1156 } else { 1157 if (result == ISC_R_SUCCESS) { 1158 zoneverify_log_error(vctx, "Expected " 1159 "and found " 1160 "NSEC3 " 1161 "chains not " 1162 "equal"); 1163 } 1164 result = ISC_R_FAILURE; 1165 /* 1166 * Attempt to resync found_chain. 1167 */ 1168 while (f != NULL && !chain_compare(e, f)) { 1169 free_element(mctx, f); 1170 f = isc_heap_element(vctx->found_chains, 1171 1); 1172 if (f != NULL) { 1173 isc_heap_delete( 1174 vctx->found_chains, 1); 1175 } 1176 if (f != NULL && 1177 chain_equal(e, f, chain_length(e))) 1178 { 1179 free_element(mctx, f); 1180 f = NULL; 1181 break; 1182 } 1183 } 1184 } 1185 } else if (result == ISC_R_SUCCESS) { 1186 zoneverify_log_error(vctx, "Expected and found NSEC3 " 1187 "chains " 1188 "not equal"); 1189 result = ISC_R_FAILURE; 1190 } 1191 1192 if (first == NULL) { 1193 prev = first = e; 1194 } else if (!chain_equal(first, e, first->salt_length)) { 1195 if (!checklast(mctx, vctx, first, prev)) { 1196 result = ISC_R_FAILURE; 1197 } 1198 1199 prev = first = e; 1200 } else { 1201 if (!checknext(mctx, vctx, first, prev, e)) { 1202 result = ISC_R_FAILURE; 1203 } 1204 1205 prev = e; 1206 } 1207 } 1208 if (prev != NULL) { 1209 if (!checklast(mctx, vctx, first, prev)) { 1210 result = ISC_R_FAILURE; 1211 } 1212 } 1213 do { 1214 if (f != NULL) { 1215 if (result == ISC_R_SUCCESS) { 1216 zoneverify_log_error(vctx, "Expected and found " 1217 "NSEC3 chains not " 1218 "equal"); 1219 result = ISC_R_FAILURE; 1220 } 1221 free_element(mctx, f); 1222 } 1223 f = isc_heap_element(vctx->found_chains, 1); 1224 if (f != NULL) { 1225 isc_heap_delete(vctx->found_chains, 1); 1226 } 1227 } while (f != NULL); 1228 1229 return (result); 1230 } 1231 1232 static isc_result_t 1233 verifyemptynodes(const vctx_t *vctx, const dns_name_t *name, 1234 const dns_name_t *prevname, bool isdelegation, 1235 dns_rdataset_t *nsec3paramset, isc_result_t *vresult) { 1236 dns_namereln_t reln; 1237 int order; 1238 unsigned int labels, nlabels, i; 1239 dns_name_t suffix; 1240 isc_result_t result, tvresult = ISC_R_UNSET; 1241 1242 *vresult = ISC_R_SUCCESS; 1243 1244 reln = dns_name_fullcompare(prevname, name, &order, &labels); 1245 if (order >= 0) { 1246 return (ISC_R_SUCCESS); 1247 } 1248 1249 nlabels = dns_name_countlabels(name); 1250 1251 if (reln == dns_namereln_commonancestor || 1252 reln == dns_namereln_contains) 1253 { 1254 dns_name_init(&suffix, NULL); 1255 for (i = labels + 1; i < nlabels; i++) { 1256 dns_name_getlabelsequence(name, nlabels - i, i, 1257 &suffix); 1258 if (nsec3paramset != NULL && 1259 dns_rdataset_isassociated(nsec3paramset)) 1260 { 1261 result = verifynsec3s( 1262 vctx, &suffix, nsec3paramset, 1263 isdelegation, true, NULL, 0, &tvresult); 1264 if (result != ISC_R_SUCCESS) { 1265 return (result); 1266 } 1267 if (*vresult == ISC_R_SUCCESS) { 1268 *vresult = tvresult; 1269 } 1270 } 1271 } 1272 } 1273 1274 return (ISC_R_SUCCESS); 1275 } 1276 1277 static void 1278 vctx_init(vctx_t *vctx, isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, 1279 dns_dbversion_t *ver, dns_name_t *origin, dns_keytable_t *secroots) { 1280 memset(vctx, 0, sizeof(*vctx)); 1281 1282 vctx->mctx = mctx; 1283 vctx->zone = zone; 1284 vctx->db = db; 1285 vctx->ver = ver; 1286 vctx->origin = origin; 1287 vctx->secroots = secroots; 1288 vctx->goodksk = false; 1289 vctx->goodzsk = false; 1290 1291 dns_rdataset_init(&vctx->keyset); 1292 dns_rdataset_init(&vctx->keysigs); 1293 dns_rdataset_init(&vctx->soaset); 1294 dns_rdataset_init(&vctx->soasigs); 1295 dns_rdataset_init(&vctx->nsecset); 1296 dns_rdataset_init(&vctx->nsecsigs); 1297 dns_rdataset_init(&vctx->nsec3paramset); 1298 dns_rdataset_init(&vctx->nsec3paramsigs); 1299 1300 vctx->expected_chains = NULL; 1301 isc_heap_create(mctx, chain_compare, NULL, 1024, 1302 &vctx->expected_chains); 1303 1304 vctx->found_chains = NULL; 1305 isc_heap_create(mctx, chain_compare, NULL, 1024, &vctx->found_chains); 1306 } 1307 1308 static void 1309 vctx_destroy(vctx_t *vctx) { 1310 if (dns_rdataset_isassociated(&vctx->keyset)) { 1311 dns_rdataset_disassociate(&vctx->keyset); 1312 } 1313 if (dns_rdataset_isassociated(&vctx->keysigs)) { 1314 dns_rdataset_disassociate(&vctx->keysigs); 1315 } 1316 if (dns_rdataset_isassociated(&vctx->soaset)) { 1317 dns_rdataset_disassociate(&vctx->soaset); 1318 } 1319 if (dns_rdataset_isassociated(&vctx->soasigs)) { 1320 dns_rdataset_disassociate(&vctx->soasigs); 1321 } 1322 if (dns_rdataset_isassociated(&vctx->nsecset)) { 1323 dns_rdataset_disassociate(&vctx->nsecset); 1324 } 1325 if (dns_rdataset_isassociated(&vctx->nsecsigs)) { 1326 dns_rdataset_disassociate(&vctx->nsecsigs); 1327 } 1328 if (dns_rdataset_isassociated(&vctx->nsec3paramset)) { 1329 dns_rdataset_disassociate(&vctx->nsec3paramset); 1330 } 1331 if (dns_rdataset_isassociated(&vctx->nsec3paramsigs)) { 1332 dns_rdataset_disassociate(&vctx->nsec3paramsigs); 1333 } 1334 isc_heap_foreach(vctx->expected_chains, free_element_heap, vctx->mctx); 1335 isc_heap_destroy(&vctx->expected_chains); 1336 isc_heap_foreach(vctx->found_chains, free_element_heap, vctx->mctx); 1337 isc_heap_destroy(&vctx->found_chains); 1338 } 1339 1340 static isc_result_t 1341 check_apex_rrsets(vctx_t *vctx) { 1342 dns_dbnode_t *node = NULL; 1343 isc_result_t result; 1344 1345 result = dns_db_findnode(vctx->db, vctx->origin, false, &node); 1346 if (result != ISC_R_SUCCESS) { 1347 zoneverify_log_error(vctx, 1348 "failed to find the zone's origin: %s", 1349 isc_result_totext(result)); 1350 return (result); 1351 } 1352 1353 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1354 dns_rdatatype_dnskey, 0, 0, &vctx->keyset, 1355 &vctx->keysigs); 1356 if (result != ISC_R_SUCCESS) { 1357 zoneverify_log_error(vctx, "Zone contains no DNSSEC keys"); 1358 goto done; 1359 } 1360 1361 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1362 dns_rdatatype_soa, 0, 0, &vctx->soaset, 1363 &vctx->soasigs); 1364 if (result != ISC_R_SUCCESS) { 1365 zoneverify_log_error(vctx, "Zone contains no SOA record"); 1366 goto done; 1367 } 1368 1369 result = dns_db_findrdataset(vctx->db, node, vctx->ver, 1370 dns_rdatatype_nsec, 0, 0, &vctx->nsecset, 1371 &vctx->nsecsigs); 1372 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { 1373 zoneverify_log_error(vctx, "NSEC lookup failed"); 1374 goto done; 1375 } 1376 1377 result = dns_db_findrdataset( 1378 vctx->db, node, vctx->ver, dns_rdatatype_nsec3param, 0, 0, 1379 &vctx->nsec3paramset, &vctx->nsec3paramsigs); 1380 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) { 1381 zoneverify_log_error(vctx, "NSEC3PARAM lookup failed"); 1382 goto done; 1383 } 1384 1385 if (!dns_rdataset_isassociated(&vctx->keysigs)) { 1386 zoneverify_log_error(vctx, "DNSKEY is not signed " 1387 "(keys offline or inactive?)"); 1388 result = ISC_R_FAILURE; 1389 goto done; 1390 } 1391 1392 if (!dns_rdataset_isassociated(&vctx->soasigs)) { 1393 zoneverify_log_error(vctx, "SOA is not signed " 1394 "(keys offline or inactive?)"); 1395 result = ISC_R_FAILURE; 1396 goto done; 1397 } 1398 1399 if (dns_rdataset_isassociated(&vctx->nsecset) && 1400 !dns_rdataset_isassociated(&vctx->nsecsigs)) 1401 { 1402 zoneverify_log_error(vctx, "NSEC is not signed " 1403 "(keys offline or inactive?)"); 1404 result = ISC_R_FAILURE; 1405 goto done; 1406 } 1407 1408 if (dns_rdataset_isassociated(&vctx->nsec3paramset) && 1409 !dns_rdataset_isassociated(&vctx->nsec3paramsigs)) 1410 { 1411 zoneverify_log_error(vctx, "NSEC3PARAM is not signed " 1412 "(keys offline or inactive?)"); 1413 result = ISC_R_FAILURE; 1414 goto done; 1415 } 1416 1417 if (!dns_rdataset_isassociated(&vctx->nsecset) && 1418 !dns_rdataset_isassociated(&vctx->nsec3paramset)) 1419 { 1420 zoneverify_log_error(vctx, "No valid NSEC/NSEC3 chain for " 1421 "testing"); 1422 result = ISC_R_FAILURE; 1423 goto done; 1424 } 1425 1426 result = ISC_R_SUCCESS; 1427 1428 done: 1429 dns_db_detachnode(vctx->db, &node); 1430 1431 return (result); 1432 } 1433 1434 /*% 1435 * Update 'vctx' tables tracking active and standby key algorithms used in the 1436 * verified zone based on the signatures made using 'dnskey' (prepared from 1437 * 'rdata') found at zone apex. Set 'vctx->goodksk' or 'vctx->goodzsk' to true 1438 * if 'dnskey' correctly signs the DNSKEY RRset at zone apex and either 1439 * 'vctx->secroots' is NULL or 'dnskey' is present in 'vctx->secroots'. 1440 * 1441 * The variables to update are chosen based on 'is_ksk', which is true when 1442 * 'dnskey' is a KSK and false otherwise. 1443 */ 1444 static void 1445 check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey, 1446 dns_rdata_t *keyrdata, bool is_ksk) { 1447 unsigned char *active_keys = NULL, *standby_keys = NULL; 1448 dns_keynode_t *keynode = NULL; 1449 bool *goodkey = NULL; 1450 dst_key_t *key = NULL; 1451 isc_result_t result; 1452 dns_rdataset_t dsset; 1453 1454 active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms); 1455 standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk); 1456 goodkey = (is_ksk ? &vctx->goodksk : &vctx->goodzsk); 1457 1458 /* 1459 * First, does this key sign the DNSKEY rrset? 1460 */ 1461 if (!dns_dnssec_selfsigns(keyrdata, vctx->origin, &vctx->keyset, 1462 &vctx->keysigs, false, vctx->mctx)) 1463 { 1464 if (!is_ksk && 1465 dns_dnssec_signs(keyrdata, vctx->origin, &vctx->soaset, 1466 &vctx->soasigs, false, vctx->mctx)) 1467 { 1468 if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) { 1469 active_keys[dnskey->algorithm]++; 1470 } 1471 } else { 1472 if (standby_keys[dnskey->algorithm] != DNS_KEYALG_MAX) { 1473 standby_keys[dnskey->algorithm]++; 1474 } 1475 } 1476 return; 1477 } 1478 1479 if (active_keys[dnskey->algorithm] != DNS_KEYALG_MAX) { 1480 active_keys[dnskey->algorithm]++; 1481 } 1482 1483 /* 1484 * If a trust anchor table was not supplied, a correctly self-signed 1485 * DNSKEY RRset is good enough. 1486 */ 1487 if (vctx->secroots == NULL) { 1488 *goodkey = true; 1489 return; 1490 } 1491 1492 /* 1493 * Convert the supplied key rdata to dst_key_t. (If this 1494 * fails we can't go further.) 1495 */ 1496 result = dns_dnssec_keyfromrdata(vctx->origin, keyrdata, vctx->mctx, 1497 &key); 1498 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1499 1500 /* 1501 * Look up the supplied key in the trust anchor table. 1502 * If we don't find an exact match, or if the keynode data 1503 * is NULL, then we have neither a DNSKEY nor a DS format 1504 * trust anchor, and can give up. 1505 */ 1506 result = dns_keytable_find(vctx->secroots, vctx->origin, &keynode); 1507 if (result != ISC_R_SUCCESS) { 1508 /* No such trust anchor */ 1509 goto cleanup; 1510 } 1511 1512 /* 1513 * If the keynode has any DS format trust anchors, that means 1514 * it doesn't have any DNSKEY ones. So, we can check for a DS 1515 * match and then stop. 1516 */ 1517 dns_rdataset_init(&dsset); 1518 if (dns_keynode_dsset(keynode, &dsset)) { 1519 for (result = dns_rdataset_first(&dsset); 1520 result == ISC_R_SUCCESS; 1521 result = dns_rdataset_next(&dsset)) 1522 { 1523 dns_rdata_t dsrdata = DNS_RDATA_INIT; 1524 dns_rdata_t newdsrdata = DNS_RDATA_INIT; 1525 unsigned char buf[DNS_DS_BUFFERSIZE]; 1526 dns_rdata_ds_t ds; 1527 1528 dns_rdata_reset(&dsrdata); 1529 dns_rdataset_current(&dsset, &dsrdata); 1530 result = dns_rdata_tostruct(&dsrdata, &ds, NULL); 1531 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1532 1533 if (ds.key_tag != dst_key_id(key) || 1534 ds.algorithm != dst_key_alg(key)) 1535 { 1536 continue; 1537 } 1538 1539 result = dns_ds_buildrdata(vctx->origin, keyrdata, 1540 ds.digest_type, buf, 1541 &newdsrdata); 1542 if (result != ISC_R_SUCCESS) { 1543 continue; 1544 } 1545 1546 if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) { 1547 dns_rdataset_settrust(&vctx->keyset, 1548 dns_trust_secure); 1549 dns_rdataset_settrust(&vctx->keysigs, 1550 dns_trust_secure); 1551 *goodkey = true; 1552 break; 1553 } 1554 } 1555 dns_rdataset_disassociate(&dsset); 1556 1557 goto cleanup; 1558 } 1559 1560 cleanup: 1561 if (keynode != NULL) { 1562 dns_keytable_detachkeynode(vctx->secroots, &keynode); 1563 } 1564 if (key != NULL) { 1565 dst_key_free(&key); 1566 } 1567 } 1568 1569 /*% 1570 * Check that the DNSKEY RR has at least one self signing KSK and one ZSK per 1571 * algorithm in it (or, if -x was used, one self-signing KSK). 1572 */ 1573 static isc_result_t 1574 check_dnskey(vctx_t *vctx) { 1575 dns_rdata_t rdata = DNS_RDATA_INIT; 1576 dns_rdata_dnskey_t dnskey; 1577 isc_result_t result; 1578 bool is_ksk; 1579 1580 for (result = dns_rdataset_first(&vctx->keyset); 1581 result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset)) 1582 { 1583 dns_rdataset_current(&vctx->keyset, &rdata); 1584 result = dns_rdata_tostruct(&rdata, &dnskey, NULL); 1585 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1586 is_ksk = ((dnskey.flags & DNS_KEYFLAG_KSK) != 0); 1587 1588 if ((dnskey.flags & DNS_KEYOWNER_ZONE) != 0 && 1589 (dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) 1590 { 1591 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && 1592 !dns_dnssec_selfsigns(&rdata, vctx->origin, 1593 &vctx->keyset, &vctx->keysigs, 1594 false, vctx->mctx)) 1595 { 1596 char namebuf[DNS_NAME_FORMATSIZE]; 1597 char buffer[1024]; 1598 isc_buffer_t buf; 1599 1600 dns_name_format(vctx->origin, namebuf, 1601 sizeof(namebuf)); 1602 isc_buffer_init(&buf, buffer, sizeof(buffer)); 1603 result = dns_rdata_totext(&rdata, NULL, &buf); 1604 if (result != ISC_R_SUCCESS) { 1605 zoneverify_log_error( 1606 vctx, "dns_rdata_totext: %s", 1607 isc_result_totext(result)); 1608 return (ISC_R_FAILURE); 1609 } 1610 zoneverify_log_error( 1611 vctx, 1612 "revoked KSK is not self signed:\n" 1613 "%s DNSKEY %.*s", 1614 namebuf, 1615 (int)isc_buffer_usedlength(&buf), 1616 buffer); 1617 return (ISC_R_FAILURE); 1618 } 1619 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 && 1620 vctx->revoked_ksk[dnskey.algorithm] != 1621 DNS_KEYALG_MAX) 1622 { 1623 vctx->revoked_ksk[dnskey.algorithm]++; 1624 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 && 1625 vctx->revoked_zsk[dnskey.algorithm] != 1626 DNS_KEYALG_MAX) 1627 { 1628 vctx->revoked_zsk[dnskey.algorithm]++; 1629 } 1630 } else { 1631 check_dnskey_sigs(vctx, &dnskey, &rdata, is_ksk); 1632 } 1633 dns_rdata_freestruct(&dnskey); 1634 dns_rdata_reset(&rdata); 1635 } 1636 1637 return (ISC_R_SUCCESS); 1638 } 1639 1640 static void 1641 determine_active_algorithms(vctx_t *vctx, bool ignore_kskflag, 1642 bool keyset_kskonly, 1643 void (*report)(const char *, ...)) { 1644 char algbuf[DNS_SECALG_FORMATSIZE]; 1645 1646 report("Verifying the zone using the following algorithms:"); 1647 1648 for (size_t i = 0; i < ARRAY_SIZE(vctx->act_algorithms); i++) { 1649 if (ignore_kskflag) { 1650 vctx->act_algorithms[i] = (vctx->ksk_algorithms[i] != 1651 0 || 1652 vctx->zsk_algorithms[i] != 0) 1653 ? 1 1654 : 0; 1655 } else { 1656 vctx->act_algorithms[i] = vctx->ksk_algorithms[i] != 0 1657 ? 1 1658 : 0; 1659 } 1660 if (vctx->act_algorithms[i] != 0) { 1661 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1662 report("- %s", algbuf); 1663 } 1664 } 1665 1666 if (ignore_kskflag || keyset_kskonly) { 1667 return; 1668 } 1669 1670 for (size_t i = 0; i < ARRAY_SIZE(vctx->ksk_algorithms); i++) { 1671 /* 1672 * The counts should both be zero or both be non-zero. Mark 1673 * the algorithm as bad if this is not met. 1674 */ 1675 if ((vctx->ksk_algorithms[i] != 0) == 1676 (vctx->zsk_algorithms[i] != 0)) 1677 { 1678 continue; 1679 } 1680 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1681 zoneverify_log_error(vctx, "Missing %s for algorithm %s", 1682 (vctx->ksk_algorithms[i] != 0) ? "ZSK" 1683 : "self-" 1684 "signed " 1685 "KSK", 1686 algbuf); 1687 vctx->bad_algorithms[i] = 1; 1688 } 1689 } 1690 1691 /*% 1692 * Check that all the records not yet verified were signed by keys that are 1693 * present in the DNSKEY RRset. 1694 */ 1695 static isc_result_t 1696 verify_nodes(vctx_t *vctx, isc_result_t *vresult) { 1697 dns_fixedname_t fname, fnextname, fprevname, fzonecut; 1698 dns_name_t *name, *nextname, *prevname, *zonecut; 1699 dns_dbnode_t *node = NULL, *nextnode; 1700 dns_dbiterator_t *dbiter = NULL; 1701 dst_key_t **dstkeys; 1702 size_t count, nkeys = 0; 1703 bool done = false; 1704 isc_result_t tvresult = ISC_R_UNSET; 1705 isc_result_t result; 1706 1707 name = dns_fixedname_initname(&fname); 1708 nextname = dns_fixedname_initname(&fnextname); 1709 dns_fixedname_init(&fprevname); 1710 prevname = NULL; 1711 dns_fixedname_init(&fzonecut); 1712 zonecut = NULL; 1713 1714 count = dns_rdataset_count(&vctx->keyset); 1715 dstkeys = isc_mem_get(vctx->mctx, sizeof(*dstkeys) * count); 1716 1717 for (result = dns_rdataset_first(&vctx->keyset); 1718 result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset)) 1719 { 1720 dns_rdata_t rdata = DNS_RDATA_INIT; 1721 dns_rdataset_current(&vctx->keyset, &rdata); 1722 dstkeys[nkeys] = NULL; 1723 result = dns_dnssec_keyfromrdata(vctx->origin, &rdata, 1724 vctx->mctx, &dstkeys[nkeys]); 1725 if (result == ISC_R_SUCCESS) { 1726 nkeys++; 1727 } 1728 } 1729 1730 result = dns_db_createiterator(vctx->db, DNS_DB_NONSEC3, &dbiter); 1731 if (result != ISC_R_SUCCESS) { 1732 zoneverify_log_error(vctx, "dns_db_createiterator(): %s", 1733 isc_result_totext(result)); 1734 goto done; 1735 } 1736 1737 result = dns_dbiterator_first(dbiter); 1738 if (result != ISC_R_SUCCESS) { 1739 zoneverify_log_error(vctx, "dns_dbiterator_first(): %s", 1740 isc_result_totext(result)); 1741 goto done; 1742 } 1743 1744 while (!done) { 1745 bool isdelegation = false; 1746 1747 result = dns_dbiterator_current(dbiter, &node, name); 1748 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 1749 zoneverify_log_error(vctx, 1750 "dns_dbiterator_current(): %s", 1751 isc_result_totext(result)); 1752 goto done; 1753 } 1754 if (!dns_name_issubdomain(name, vctx->origin)) { 1755 result = check_no_nsec(vctx, name, node); 1756 if (result != ISC_R_SUCCESS) { 1757 dns_db_detachnode(vctx->db, &node); 1758 goto done; 1759 } 1760 dns_db_detachnode(vctx->db, &node); 1761 result = dns_dbiterator_next(dbiter); 1762 if (result == ISC_R_NOMORE) { 1763 done = true; 1764 } else if (result != ISC_R_SUCCESS) { 1765 zoneverify_log_error(vctx, 1766 "dns_dbiterator_next(): " 1767 "%s", 1768 isc_result_totext(result)); 1769 goto done; 1770 } 1771 continue; 1772 } 1773 if (is_delegation(vctx, name, node, NULL)) { 1774 zonecut = dns_fixedname_name(&fzonecut); 1775 dns_name_copy(name, zonecut); 1776 isdelegation = true; 1777 } else if (has_dname(vctx, node)) { 1778 zonecut = dns_fixedname_name(&fzonecut); 1779 dns_name_copy(name, zonecut); 1780 } 1781 nextnode = NULL; 1782 result = dns_dbiterator_next(dbiter); 1783 while (result == ISC_R_SUCCESS) { 1784 bool empty; 1785 result = dns_dbiterator_current(dbiter, &nextnode, 1786 nextname); 1787 if (result != ISC_R_SUCCESS && 1788 result != DNS_R_NEWORIGIN) 1789 { 1790 zoneverify_log_error(vctx, 1791 "dns_dbiterator_current():" 1792 " %s", 1793 isc_result_totext(result)); 1794 dns_db_detachnode(vctx->db, &node); 1795 goto done; 1796 } 1797 if (!dns_name_issubdomain(nextname, vctx->origin) || 1798 (zonecut != NULL && 1799 dns_name_issubdomain(nextname, zonecut))) 1800 { 1801 result = check_no_nsec(vctx, nextname, 1802 nextnode); 1803 if (result != ISC_R_SUCCESS) { 1804 dns_db_detachnode(vctx->db, &node); 1805 dns_db_detachnode(vctx->db, &nextnode); 1806 goto done; 1807 } 1808 dns_db_detachnode(vctx->db, &nextnode); 1809 result = dns_dbiterator_next(dbiter); 1810 continue; 1811 } 1812 result = is_empty(vctx, nextnode, &empty); 1813 dns_db_detachnode(vctx->db, &nextnode); 1814 if (result != ISC_R_SUCCESS) { 1815 dns_db_detachnode(vctx->db, &node); 1816 goto done; 1817 } 1818 if (empty) { 1819 result = dns_dbiterator_next(dbiter); 1820 continue; 1821 } 1822 break; 1823 } 1824 if (result == ISC_R_NOMORE) { 1825 done = true; 1826 nextname = vctx->origin; 1827 } else if (result != ISC_R_SUCCESS) { 1828 zoneverify_log_error(vctx, 1829 "iterating through the database " 1830 "failed: %s", 1831 isc_result_totext(result)); 1832 dns_db_detachnode(vctx->db, &node); 1833 goto done; 1834 } 1835 result = verifynode(vctx, name, node, isdelegation, dstkeys, 1836 nkeys, &vctx->nsecset, &vctx->nsec3paramset, 1837 nextname, &tvresult); 1838 if (result != ISC_R_SUCCESS) { 1839 dns_db_detachnode(vctx->db, &node); 1840 goto done; 1841 } 1842 if (*vresult == ISC_R_UNSET) { 1843 *vresult = ISC_R_SUCCESS; 1844 } 1845 if (*vresult == ISC_R_SUCCESS) { 1846 *vresult = tvresult; 1847 } 1848 if (prevname != NULL) { 1849 result = verifyemptynodes( 1850 vctx, name, prevname, isdelegation, 1851 &vctx->nsec3paramset, &tvresult); 1852 if (result != ISC_R_SUCCESS) { 1853 dns_db_detachnode(vctx->db, &node); 1854 goto done; 1855 } 1856 } else { 1857 prevname = dns_fixedname_name(&fprevname); 1858 } 1859 dns_name_copy(name, prevname); 1860 if (*vresult == ISC_R_SUCCESS) { 1861 *vresult = tvresult; 1862 } 1863 dns_db_detachnode(vctx->db, &node); 1864 } 1865 1866 dns_dbiterator_destroy(&dbiter); 1867 1868 result = dns_db_createiterator(vctx->db, DNS_DB_NSEC3ONLY, &dbiter); 1869 if (result != ISC_R_SUCCESS) { 1870 zoneverify_log_error(vctx, "dns_db_createiterator(): %s", 1871 isc_result_totext(result)); 1872 return (result); 1873 } 1874 1875 for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS; 1876 result = dns_dbiterator_next(dbiter)) 1877 { 1878 result = dns_dbiterator_current(dbiter, &node, name); 1879 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) { 1880 zoneverify_log_error(vctx, 1881 "dns_dbiterator_current(): %s", 1882 isc_result_totext(result)); 1883 goto done; 1884 } 1885 result = verifynode(vctx, name, node, false, dstkeys, nkeys, 1886 NULL, NULL, NULL, NULL); 1887 if (result != ISC_R_SUCCESS) { 1888 zoneverify_log_error(vctx, "verifynode: %s", 1889 isc_result_totext(result)); 1890 dns_db_detachnode(vctx->db, &node); 1891 goto done; 1892 } 1893 result = record_found(vctx, name, node, &vctx->nsec3paramset); 1894 dns_db_detachnode(vctx->db, &node); 1895 if (result != ISC_R_SUCCESS) { 1896 goto done; 1897 } 1898 } 1899 1900 result = ISC_R_SUCCESS; 1901 1902 done: 1903 while (nkeys-- > 0U) { 1904 dst_key_free(&dstkeys[nkeys]); 1905 } 1906 isc_mem_put(vctx->mctx, dstkeys, sizeof(*dstkeys) * count); 1907 if (dbiter != NULL) { 1908 dns_dbiterator_destroy(&dbiter); 1909 } 1910 1911 return (result); 1912 } 1913 1914 static isc_result_t 1915 check_bad_algorithms(const vctx_t *vctx, void (*report)(const char *, ...)) { 1916 char algbuf[DNS_SECALG_FORMATSIZE]; 1917 bool first = true; 1918 1919 for (size_t i = 0; i < ARRAY_SIZE(vctx->bad_algorithms); i++) { 1920 if (vctx->bad_algorithms[i] == 0) { 1921 continue; 1922 } 1923 if (first) { 1924 report("The zone is not fully signed " 1925 "for the following algorithms:"); 1926 } 1927 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1928 report(" %s", algbuf); 1929 first = false; 1930 } 1931 1932 if (!first) { 1933 report("."); 1934 } 1935 1936 return (first ? ISC_R_SUCCESS : ISC_R_FAILURE); 1937 } 1938 1939 static void 1940 print_summary(const vctx_t *vctx, bool keyset_kskonly, 1941 void (*report)(const char *, ...)) { 1942 char algbuf[DNS_SECALG_FORMATSIZE]; 1943 1944 report("Zone fully signed:"); 1945 for (size_t i = 0; i < ARRAY_SIZE(vctx->ksk_algorithms); i++) { 1946 if ((vctx->ksk_algorithms[i] == 0) && 1947 (vctx->standby_ksk[i] == 0) && 1948 (vctx->revoked_ksk[i] == 0) && 1949 (vctx->zsk_algorithms[i] == 0) && 1950 (vctx->standby_zsk[i] == 0) && (vctx->revoked_zsk[i] == 0)) 1951 { 1952 continue; 1953 } 1954 dns_secalg_format(i, algbuf, sizeof(algbuf)); 1955 report("Algorithm: %s: KSKs: " 1956 "%u active, %u stand-by, %u revoked", 1957 algbuf, vctx->ksk_algorithms[i], vctx->standby_ksk[i], 1958 vctx->revoked_ksk[i]); 1959 report("%*sZSKs: " 1960 "%u active, %u %s, %u revoked", 1961 (int)strlen(algbuf) + 13, "", vctx->zsk_algorithms[i], 1962 vctx->standby_zsk[i], 1963 keyset_kskonly ? "present" : "stand-by", 1964 vctx->revoked_zsk[i]); 1965 } 1966 } 1967 1968 isc_result_t 1969 dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, 1970 dns_name_t *origin, dns_keytable_t *secroots, 1971 isc_mem_t *mctx, bool ignore_kskflag, bool keyset_kskonly, 1972 void (*report)(const char *, ...)) { 1973 const char *keydesc = (secroots == NULL ? "self-signed" : "trusted"); 1974 isc_result_t result, vresult = ISC_R_UNSET; 1975 vctx_t vctx; 1976 1977 vctx_init(&vctx, mctx, zone, db, ver, origin, secroots); 1978 1979 result = check_apex_rrsets(&vctx); 1980 if (result != ISC_R_SUCCESS) { 1981 goto done; 1982 } 1983 1984 result = check_dnskey(&vctx); 1985 if (result != ISC_R_SUCCESS) { 1986 goto done; 1987 } 1988 1989 if (ignore_kskflag) { 1990 if (!vctx.goodksk && !vctx.goodzsk) { 1991 zoneverify_log_error(&vctx, "No %s DNSKEY found", 1992 keydesc); 1993 result = ISC_R_FAILURE; 1994 goto done; 1995 } 1996 } else if (!vctx.goodksk) { 1997 zoneverify_log_error(&vctx, "No %s KSK DNSKEY found", keydesc); 1998 result = ISC_R_FAILURE; 1999 goto done; 2000 } 2001 2002 determine_active_algorithms(&vctx, ignore_kskflag, keyset_kskonly, 2003 report); 2004 2005 result = verify_nodes(&vctx, &vresult); 2006 if (result != ISC_R_SUCCESS) { 2007 goto done; 2008 } 2009 2010 result = verify_nsec3_chains(&vctx, mctx); 2011 if (vresult == ISC_R_UNSET) { 2012 vresult = ISC_R_SUCCESS; 2013 } 2014 if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS) { 2015 vresult = result; 2016 } 2017 2018 result = check_bad_algorithms(&vctx, report); 2019 if (result != ISC_R_SUCCESS) { 2020 report("DNSSEC completeness test failed."); 2021 goto done; 2022 } 2023 2024 result = vresult; 2025 if (result != ISC_R_SUCCESS) { 2026 report("DNSSEC completeness test failed (%s).", 2027 isc_result_totext(result)); 2028 goto done; 2029 } 2030 2031 if (vctx.goodksk || ignore_kskflag) { 2032 print_summary(&vctx, keyset_kskonly, report); 2033 } 2034 2035 done: 2036 vctx_destroy(&vctx); 2037 2038 return (result); 2039 } 2040