1 /* $NetBSD: validator.c,v 1.16 2024/09/22 00:14:06 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 #include <inttypes.h> 17 #include <stdbool.h> 18 19 #include <isc/base32.h> 20 #include <isc/counter.h> 21 #include <isc/md.h> 22 #include <isc/mem.h> 23 #include <isc/print.h> 24 #include <isc/result.h> 25 #include <isc/string.h> 26 #include <isc/task.h> 27 #include <isc/util.h> 28 29 #include <dns/client.h> 30 #include <dns/db.h> 31 #include <dns/dnssec.h> 32 #include <dns/ds.h> 33 #include <dns/events.h> 34 #include <dns/keytable.h> 35 #include <dns/keyvalues.h> 36 #include <dns/log.h> 37 #include <dns/message.h> 38 #include <dns/ncache.h> 39 #include <dns/nsec.h> 40 #include <dns/nsec3.h> 41 #include <dns/rdata.h> 42 #include <dns/rdataset.h> 43 #include <dns/rdatatype.h> 44 #include <dns/resolver.h> 45 #include <dns/validator.h> 46 #include <dns/view.h> 47 48 /*! \file 49 * \brief 50 * Basic processing sequences: 51 * 52 * \li When called with rdataset and sigrdataset: 53 * validator_start -> validate_answer -> proveunsecure 54 * validator_start -> validate_answer -> validate_nx (if secure wildcard) 55 * 56 * \li When called with rdataset but no sigrdataset: 57 * validator_start -> proveunsecure 58 * 59 * \li When called with no rdataset or sigrdataset: 60 * validator_start -> validate_nx-> proveunsecure 61 * 62 * validator_start: determine what type of validation to do. 63 * validate_answer: attempt to perform a positive validation. 64 * proveunsecure: attempt to prove the answer comes from an unsecure zone. 65 * validate_nx: attempt to prove a negative response. 66 */ 67 68 #define VALIDATOR_MAGIC ISC_MAGIC('V', 'a', 'l', '?') 69 #define VALID_VALIDATOR(v) ISC_MAGIC_VALID(v, VALIDATOR_MAGIC) 70 71 #define VALATTR_SHUTDOWN 0x0001 /*%< Shutting down. */ 72 #define VALATTR_CANCELED 0x0002 /*%< Canceled. */ 73 #define VALATTR_TRIEDVERIFY \ 74 0x0004 /*%< We have found a key and \ 75 * have attempted a verify. */ 76 #define VALATTR_INSECURITY 0x0010 /*%< Attempting proveunsecure. */ 77 78 /*! 79 * NSEC proofs to be looked for. 80 */ 81 #define VALATTR_NEEDNOQNAME 0x00000100 82 #define VALATTR_NEEDNOWILDCARD 0x00000200 83 #define VALATTR_NEEDNODATA 0x00000400 84 85 /*! 86 * NSEC proofs that have been found. 87 */ 88 #define VALATTR_FOUNDNOQNAME 0x00001000 89 #define VALATTR_FOUNDNOWILDCARD 0x00002000 90 #define VALATTR_FOUNDNODATA 0x00004000 91 #define VALATTR_FOUNDCLOSEST 0x00008000 92 #define VALATTR_FOUNDOPTOUT 0x00010000 93 #define VALATTR_FOUNDUNKNOWN 0x00020000 94 95 #define NEEDNODATA(val) ((val->attributes & VALATTR_NEEDNODATA) != 0) 96 #define NEEDNOQNAME(val) ((val->attributes & VALATTR_NEEDNOQNAME) != 0) 97 #define NEEDNOWILDCARD(val) ((val->attributes & VALATTR_NEEDNOWILDCARD) != 0) 98 #define FOUNDNODATA(val) ((val->attributes & VALATTR_FOUNDNODATA) != 0) 99 #define FOUNDNOQNAME(val) ((val->attributes & VALATTR_FOUNDNOQNAME) != 0) 100 #define FOUNDNOWILDCARD(val) ((val->attributes & VALATTR_FOUNDNOWILDCARD) != 0) 101 #define FOUNDCLOSEST(val) ((val->attributes & VALATTR_FOUNDCLOSEST) != 0) 102 #define FOUNDOPTOUT(val) ((val->attributes & VALATTR_FOUNDOPTOUT) != 0) 103 104 #define SHUTDOWN(v) (((v)->attributes & VALATTR_SHUTDOWN) != 0) 105 #define CANCELED(v) (((v)->attributes & VALATTR_CANCELED) != 0) 106 107 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) 108 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) 109 110 static void 111 destroy(dns_validator_t *val); 112 113 static isc_result_t 114 select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset); 115 116 static isc_result_t 117 validate_answer(dns_validator_t *val, bool resume); 118 119 static isc_result_t 120 validate_dnskey(dns_validator_t *val); 121 122 static isc_result_t 123 validate_nx(dns_validator_t *val, bool resume); 124 125 static isc_result_t 126 proveunsecure(dns_validator_t *val, bool have_ds, bool resume); 127 128 static void 129 validator_logv(dns_validator_t *val, isc_logcategory_t *category, 130 isc_logmodule_t *module, int level, const char *fmt, va_list ap) 131 ISC_FORMAT_PRINTF(5, 0); 132 133 static void 134 validator_log(void *val, int level, const char *fmt, ...) 135 ISC_FORMAT_PRINTF(3, 4); 136 137 static void 138 validator_logcreate(dns_validator_t *val, dns_name_t *name, 139 dns_rdatatype_t type, const char *caller, 140 const char *operation); 141 142 /*% 143 * Ensure the validator's rdatasets are marked as expired. 144 */ 145 static void 146 expire_rdatasets(dns_validator_t *val) { 147 if (dns_rdataset_isassociated(&val->frdataset)) { 148 dns_rdataset_expire(&val->frdataset); 149 } 150 if (dns_rdataset_isassociated(&val->fsigrdataset)) { 151 dns_rdataset_expire(&val->fsigrdataset); 152 } 153 } 154 155 /*% 156 * Ensure the validator's rdatasets are disassociated. 157 */ 158 static void 159 disassociate_rdatasets(dns_validator_t *val) { 160 if (dns_rdataset_isassociated(&val->fdsset)) { 161 dns_rdataset_disassociate(&val->fdsset); 162 } 163 if (dns_rdataset_isassociated(&val->frdataset)) { 164 dns_rdataset_disassociate(&val->frdataset); 165 } 166 if (dns_rdataset_isassociated(&val->fsigrdataset)) { 167 dns_rdataset_disassociate(&val->fsigrdataset); 168 } 169 } 170 171 /*% 172 * Mark the rdatasets in val->event with trust level "answer", 173 * indicating that they did not validate, but could be cached as insecure. 174 * 175 * If we are validating a name that is marked as "must be secure", log a 176 * warning and return DNS_R_MUSTBESECURE instead. 177 */ 178 static isc_result_t 179 markanswer(dns_validator_t *val, const char *where, const char *mbstext) { 180 if (val->mustbesecure && mbstext != NULL) { 181 validator_log(val, ISC_LOG_WARNING, 182 "must be secure failure, %s", mbstext); 183 return (DNS_R_MUSTBESECURE); 184 } 185 186 validator_log(val, ISC_LOG_DEBUG(3), "marking as answer (%s)", where); 187 if (val->event->rdataset != NULL) { 188 dns_rdataset_settrust(val->event->rdataset, dns_trust_answer); 189 } 190 if (val->event->sigrdataset != NULL) { 191 dns_rdataset_settrust(val->event->sigrdataset, 192 dns_trust_answer); 193 } 194 195 return (ISC_R_SUCCESS); 196 } 197 198 /*% 199 * Mark the RRsets in val->event with trust level secure. 200 */ 201 static void 202 marksecure(dns_validatorevent_t *event) { 203 dns_rdataset_settrust(event->rdataset, dns_trust_secure); 204 if (event->sigrdataset != NULL) { 205 dns_rdataset_settrust(event->sigrdataset, dns_trust_secure); 206 } 207 event->secure = true; 208 } 209 210 /* 211 * Validator 'val' is finished; send the completion event to the task 212 * that called dns_validator_create(), with result `result`. 213 */ 214 static void 215 validator_done(dns_validator_t *val, isc_result_t result) { 216 isc_task_t *task; 217 218 if (val->event == NULL) { 219 return; 220 } 221 222 /* 223 * Caller must be holding the lock. 224 */ 225 226 val->event->result = result; 227 task = val->event->ev_sender; 228 val->event->ev_sender = val; 229 val->event->ev_type = DNS_EVENT_VALIDATORDONE; 230 val->event->ev_action = val->action; 231 val->event->ev_arg = val->arg; 232 isc_task_sendanddetach(&task, (isc_event_t **)(void *)&val->event); 233 } 234 235 /* 236 * Called when deciding whether to destroy validator 'val'. 237 */ 238 static bool 239 exit_check(dns_validator_t *val) { 240 /* 241 * Caller must be holding the lock. 242 */ 243 if (!SHUTDOWN(val)) { 244 return (false); 245 } 246 247 INSIST(val->event == NULL); 248 249 if (val->fetch != NULL || val->subvalidator != NULL) { 250 return (false); 251 } 252 253 return (true); 254 } 255 256 /*% 257 * Look in the NSEC record returned from a DS query to see if there is 258 * a NS RRset at this name. If it is found we are at a delegation point. 259 */ 260 static bool 261 isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, 262 isc_result_t dbresult) { 263 dns_fixedname_t fixed; 264 dns_label_t hashlabel; 265 dns_name_t nsec3name; 266 dns_rdata_nsec3_t nsec3; 267 dns_rdata_t rdata = DNS_RDATA_INIT; 268 dns_rdataset_t set; 269 int order; 270 int scope; 271 bool found; 272 isc_buffer_t buffer; 273 isc_result_t result; 274 unsigned char hash[NSEC3_MAX_HASH_LENGTH]; 275 unsigned char owner[NSEC3_MAX_HASH_LENGTH]; 276 unsigned int length; 277 278 REQUIRE(dbresult == DNS_R_NXRRSET || dbresult == DNS_R_NCACHENXRRSET); 279 280 dns_rdataset_init(&set); 281 if (dbresult == DNS_R_NXRRSET) { 282 dns_rdataset_clone(rdataset, &set); 283 } else { 284 result = dns_ncache_getrdataset(rdataset, name, 285 dns_rdatatype_nsec, &set); 286 if (result == ISC_R_NOTFOUND) { 287 goto trynsec3; 288 } 289 if (result != ISC_R_SUCCESS) { 290 return (false); 291 } 292 } 293 294 INSIST(set.type == dns_rdatatype_nsec); 295 296 found = false; 297 result = dns_rdataset_first(&set); 298 if (result == ISC_R_SUCCESS) { 299 dns_rdataset_current(&set, &rdata); 300 found = dns_nsec_typepresent(&rdata, dns_rdatatype_ns); 301 dns_rdata_reset(&rdata); 302 } 303 dns_rdataset_disassociate(&set); 304 return (found); 305 306 trynsec3: 307 /* 308 * Iterate over the ncache entry. 309 */ 310 found = false; 311 dns_name_init(&nsec3name, NULL); 312 dns_fixedname_init(&fixed); 313 dns_name_downcase(name, dns_fixedname_name(&fixed), NULL); 314 name = dns_fixedname_name(&fixed); 315 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 316 result = dns_rdataset_next(rdataset)) 317 { 318 dns_ncache_current(rdataset, &nsec3name, &set); 319 if (set.type != dns_rdatatype_nsec3) { 320 dns_rdataset_disassociate(&set); 321 continue; 322 } 323 dns_name_getlabel(&nsec3name, 0, &hashlabel); 324 isc_region_consume(&hashlabel, 1); 325 isc_buffer_init(&buffer, owner, sizeof(owner)); 326 result = isc_base32hexnp_decoderegion(&hashlabel, &buffer); 327 if (result != ISC_R_SUCCESS) { 328 dns_rdataset_disassociate(&set); 329 continue; 330 } 331 for (result = dns_rdataset_first(&set); result == ISC_R_SUCCESS; 332 result = dns_rdataset_next(&set)) 333 { 334 dns_rdata_reset(&rdata); 335 dns_rdataset_current(&set, &rdata); 336 (void)dns_rdata_tostruct(&rdata, &nsec3, NULL); 337 if (nsec3.hash != 1) { 338 continue; 339 } 340 length = isc_iterated_hash( 341 hash, nsec3.hash, nsec3.iterations, nsec3.salt, 342 nsec3.salt_length, name->ndata, name->length); 343 if (length != isc_buffer_usedlength(&buffer)) { 344 continue; 345 } 346 order = memcmp(hash, owner, length); 347 if (order == 0) { 348 found = dns_nsec3_typepresent(&rdata, 349 dns_rdatatype_ns); 350 dns_rdataset_disassociate(&set); 351 return (found); 352 } 353 if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) == 0) { 354 continue; 355 } 356 /* 357 * Does this optout span cover the name? 358 */ 359 scope = memcmp(owner, nsec3.next, nsec3.next_length); 360 if ((scope < 0 && order > 0 && 361 memcmp(hash, nsec3.next, length) < 0) || 362 (scope >= 0 && 363 (order > 0 || 364 memcmp(hash, nsec3.next, length) < 0))) 365 { 366 dns_rdataset_disassociate(&set); 367 return (true); 368 } 369 } 370 dns_rdataset_disassociate(&set); 371 } 372 return (found); 373 } 374 375 /*% 376 * We have been asked to look for a key. 377 * If found, resume the validation process. 378 * If not found, fail the validation process. 379 */ 380 static void 381 fetch_callback_dnskey(isc_task_t *task, isc_event_t *event) { 382 dns_fetchevent_t *devent; 383 dns_validator_t *val; 384 dns_rdataset_t *rdataset; 385 bool want_destroy; 386 isc_result_t result; 387 isc_result_t eresult; 388 isc_result_t saved_result; 389 dns_fetch_t *fetch; 390 391 UNUSED(task); 392 INSIST(event->ev_type == DNS_EVENT_FETCHDONE); 393 devent = (dns_fetchevent_t *)event; 394 val = devent->ev_arg; 395 rdataset = &val->frdataset; 396 eresult = devent->result; 397 398 /* Free resources which are not of interest. */ 399 if (devent->node != NULL) { 400 dns_db_detachnode(devent->db, &devent->node); 401 } 402 if (devent->db != NULL) { 403 dns_db_detach(&devent->db); 404 } 405 if (dns_rdataset_isassociated(&val->fsigrdataset)) { 406 dns_rdataset_disassociate(&val->fsigrdataset); 407 } 408 isc_event_free(&event); 409 410 INSIST(val->event != NULL); 411 412 validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_dnskey"); 413 LOCK(&val->lock); 414 fetch = val->fetch; 415 val->fetch = NULL; 416 if (CANCELED(val)) { 417 validator_done(val, ISC_R_CANCELED); 418 } else if (eresult == ISC_R_SUCCESS || eresult == DNS_R_NCACHENXRRSET) { 419 /* 420 * We have an answer to our DNSKEY query. Either the DNSKEY 421 * RRset or a NODATA response. 422 */ 423 validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s", 424 eresult == ISC_R_SUCCESS ? "keyset" 425 : "NCACHENXRRSET", 426 dns_trust_totext(rdataset->trust)); 427 /* 428 * Only extract the dst key if the keyset exists and is secure. 429 */ 430 if (eresult == ISC_R_SUCCESS && 431 rdataset->trust >= dns_trust_secure) 432 { 433 result = select_signing_key(val, rdataset); 434 if (result == ISC_R_SUCCESS) { 435 val->keyset = &val->frdataset; 436 } 437 } 438 result = validate_answer(val, true); 439 if (result == DNS_R_NOVALIDSIG && 440 (val->attributes & VALATTR_TRIEDVERIFY) == 0) 441 { 442 saved_result = result; 443 validator_log(val, ISC_LOG_DEBUG(3), 444 "falling back to insecurity proof"); 445 result = proveunsecure(val, false, false); 446 if (result == DNS_R_NOTINSECURE) { 447 result = saved_result; 448 } 449 } 450 if (result != DNS_R_WAIT) { 451 validator_done(val, result); 452 } 453 } else { 454 validator_log(val, ISC_LOG_DEBUG(3), 455 "fetch_callback_dnskey: got %s", 456 isc_result_totext(eresult)); 457 if (eresult == ISC_R_CANCELED) { 458 validator_done(val, eresult); 459 } else { 460 validator_done(val, DNS_R_BROKENCHAIN); 461 } 462 } 463 464 want_destroy = exit_check(val); 465 UNLOCK(&val->lock); 466 467 if (fetch != NULL) { 468 dns_resolver_destroyfetch(&fetch); 469 } 470 471 if (want_destroy) { 472 destroy(val); 473 } 474 } 475 476 /*% 477 * We have been asked to look for a DS. This may be part of 478 * walking a trust chain, or an insecurity proof. 479 */ 480 static void 481 fetch_callback_ds(isc_task_t *task, isc_event_t *event) { 482 dns_fetchevent_t *devent; 483 dns_validator_t *val; 484 dns_rdataset_t *rdataset; 485 bool want_destroy, trustchain; 486 isc_result_t result; 487 isc_result_t eresult; 488 dns_fetch_t *fetch; 489 490 UNUSED(task); 491 INSIST(event->ev_type == DNS_EVENT_FETCHDONE); 492 devent = (dns_fetchevent_t *)event; 493 val = devent->ev_arg; 494 rdataset = &val->frdataset; 495 eresult = devent->result; 496 497 /* 498 * Set 'trustchain' to true if we're walking a chain of 499 * trust; false if we're attempting to prove insecurity. 500 */ 501 trustchain = ((val->attributes & VALATTR_INSECURITY) == 0); 502 503 /* Free resources which are not of interest. */ 504 if (devent->node != NULL) { 505 dns_db_detachnode(devent->db, &devent->node); 506 } 507 if (devent->db != NULL) { 508 dns_db_detach(&devent->db); 509 } 510 if (dns_rdataset_isassociated(&val->fsigrdataset)) { 511 dns_rdataset_disassociate(&val->fsigrdataset); 512 } 513 514 INSIST(val->event != NULL); 515 516 validator_log(val, ISC_LOG_DEBUG(3), "in fetch_callback_ds"); 517 LOCK(&val->lock); 518 fetch = val->fetch; 519 val->fetch = NULL; 520 521 if (CANCELED(val)) { 522 validator_done(val, ISC_R_CANCELED); 523 goto done; 524 } 525 526 switch (eresult) { 527 case DNS_R_NXDOMAIN: 528 case DNS_R_NCACHENXDOMAIN: 529 /* 530 * These results only make sense if we're attempting 531 * an insecurity proof, not when walking a chain of trust. 532 */ 533 if (trustchain) { 534 goto unexpected; 535 } 536 537 FALLTHROUGH; 538 case ISC_R_SUCCESS: 539 if (trustchain) { 540 /* 541 * We looked for a DS record as part of 542 * following a key chain upwards; resume following 543 * the chain. 544 */ 545 validator_log(val, ISC_LOG_DEBUG(3), 546 "dsset with trust %s", 547 dns_trust_totext(rdataset->trust)); 548 val->dsset = &val->frdataset; 549 result = validate_dnskey(val); 550 if (result != DNS_R_WAIT) { 551 validator_done(val, result); 552 } 553 } else { 554 /* 555 * There is a DS which may or may not be a zone cut. 556 * In either case we are still in a secure zone, 557 * so keep looking for the break in the chain 558 * of trust. 559 */ 560 result = proveunsecure(val, (eresult == ISC_R_SUCCESS), 561 true); 562 if (result != DNS_R_WAIT) { 563 validator_done(val, result); 564 } 565 } 566 break; 567 case DNS_R_CNAME: 568 case DNS_R_NXRRSET: 569 case DNS_R_NCACHENXRRSET: 570 case DNS_R_SERVFAIL: /* RFC 1034 parent? */ 571 if (trustchain) { 572 /* 573 * Failed to find a DS while following the 574 * chain of trust; now we need to prove insecurity. 575 */ 576 validator_log(val, ISC_LOG_DEBUG(3), 577 "falling back to insecurity proof (%s)", 578 isc_result_totext(eresult)); 579 result = proveunsecure(val, false, false); 580 if (result != DNS_R_WAIT) { 581 validator_done(val, result); 582 } 583 } else if (eresult == DNS_R_SERVFAIL) { 584 goto unexpected; 585 } else if (eresult != DNS_R_CNAME && 586 isdelegation(devent->foundname, &val->frdataset, 587 eresult)) 588 { 589 /* 590 * Failed to find a DS while trying to prove 591 * insecurity. If this is a zone cut, that 592 * means we're insecure. 593 */ 594 result = markanswer(val, "fetch_callback_ds", 595 "no DS and this is a delegation"); 596 validator_done(val, result); 597 } else { 598 /* 599 * Not a zone cut, so we have to keep looking for 600 * the break point in the chain of trust. 601 */ 602 result = proveunsecure(val, false, true); 603 if (result != DNS_R_WAIT) { 604 validator_done(val, result); 605 } 606 } 607 break; 608 609 default: 610 unexpected: 611 validator_log(val, ISC_LOG_DEBUG(3), 612 "fetch_callback_ds: got %s", 613 isc_result_totext(eresult)); 614 if (eresult == ISC_R_CANCELED) { 615 validator_done(val, eresult); 616 } else { 617 validator_done(val, DNS_R_BROKENCHAIN); 618 } 619 } 620 done: 621 622 isc_event_free(&event); 623 want_destroy = exit_check(val); 624 UNLOCK(&val->lock); 625 626 if (fetch != NULL) { 627 dns_resolver_destroyfetch(&fetch); 628 } 629 630 if (want_destroy) { 631 destroy(val); 632 } 633 } 634 635 /*% 636 * Callback from when a DNSKEY RRset has been validated. 637 * 638 * Resumes the stalled validation process. 639 */ 640 static void 641 validator_callback_dnskey(isc_task_t *task, isc_event_t *event) { 642 dns_validatorevent_t *devent; 643 dns_validator_t *val; 644 bool want_destroy; 645 isc_result_t result; 646 isc_result_t eresult; 647 isc_result_t saved_result; 648 649 UNUSED(task); 650 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); 651 652 devent = (dns_validatorevent_t *)event; 653 val = devent->ev_arg; 654 eresult = devent->result; 655 656 isc_event_free(&event); 657 dns_validator_destroy(&val->subvalidator); 658 659 INSIST(val->event != NULL); 660 661 validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_dnskey"); 662 LOCK(&val->lock); 663 if (CANCELED(val)) { 664 validator_done(val, ISC_R_CANCELED); 665 } else if (eresult == ISC_R_SUCCESS) { 666 validator_log(val, ISC_LOG_DEBUG(3), "keyset with trust %s", 667 dns_trust_totext(val->frdataset.trust)); 668 /* 669 * Only extract the dst key if the keyset is secure. 670 */ 671 if (val->frdataset.trust >= dns_trust_secure) { 672 (void)select_signing_key(val, &val->frdataset); 673 } 674 result = validate_answer(val, true); 675 if (result == DNS_R_NOVALIDSIG && 676 (val->attributes & VALATTR_TRIEDVERIFY) == 0) 677 { 678 saved_result = result; 679 validator_log(val, ISC_LOG_DEBUG(3), 680 "falling back to insecurity proof"); 681 result = proveunsecure(val, false, false); 682 if (result == DNS_R_NOTINSECURE) { 683 result = saved_result; 684 } 685 } 686 if (result != DNS_R_WAIT) { 687 validator_done(val, result); 688 } 689 } else { 690 if (eresult != DNS_R_BROKENCHAIN) { 691 expire_rdatasets(val); 692 } 693 validator_log(val, ISC_LOG_DEBUG(3), 694 "validator_callback_dnskey: got %s", 695 isc_result_totext(eresult)); 696 validator_done(val, DNS_R_BROKENCHAIN); 697 } 698 699 want_destroy = exit_check(val); 700 UNLOCK(&val->lock); 701 if (want_destroy) { 702 destroy(val); 703 } 704 } 705 706 /*% 707 * Callback when the DS record has been validated. 708 * 709 * Resumes validation of the zone key or the unsecure zone proof. 710 */ 711 static void 712 validator_callback_ds(isc_task_t *task, isc_event_t *event) { 713 dns_validatorevent_t *devent; 714 dns_validator_t *val; 715 bool want_destroy; 716 isc_result_t result; 717 isc_result_t eresult; 718 719 UNUSED(task); 720 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); 721 722 devent = (dns_validatorevent_t *)event; 723 val = devent->ev_arg; 724 eresult = devent->result; 725 726 isc_event_free(&event); 727 dns_validator_destroy(&val->subvalidator); 728 729 INSIST(val->event != NULL); 730 731 validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_ds"); 732 LOCK(&val->lock); 733 if (CANCELED(val)) { 734 validator_done(val, ISC_R_CANCELED); 735 } else if (eresult == ISC_R_SUCCESS) { 736 bool have_dsset; 737 dns_name_t *name; 738 validator_log(val, ISC_LOG_DEBUG(3), "%s with trust %s", 739 val->frdataset.type == dns_rdatatype_ds ? "dsset" 740 : "ds " 741 "non-" 742 "existe" 743 "nce", 744 dns_trust_totext(val->frdataset.trust)); 745 have_dsset = (val->frdataset.type == dns_rdatatype_ds); 746 name = dns_fixedname_name(&val->fname); 747 if ((val->attributes & VALATTR_INSECURITY) != 0 && 748 val->frdataset.covers == dns_rdatatype_ds && 749 NEGATIVE(&val->frdataset) && 750 isdelegation(name, &val->frdataset, DNS_R_NCACHENXRRSET)) 751 { 752 result = markanswer(val, "validator_callback_ds", 753 "no DS and this is a delegation"); 754 } else if ((val->attributes & VALATTR_INSECURITY) != 0) { 755 result = proveunsecure(val, have_dsset, true); 756 } else { 757 result = validate_dnskey(val); 758 } 759 if (result != DNS_R_WAIT) { 760 validator_done(val, result); 761 } 762 } else { 763 if (eresult != DNS_R_BROKENCHAIN) { 764 expire_rdatasets(val); 765 } 766 validator_log(val, ISC_LOG_DEBUG(3), 767 "validator_callback_ds: got %s", 768 isc_result_totext(eresult)); 769 validator_done(val, DNS_R_BROKENCHAIN); 770 } 771 772 want_destroy = exit_check(val); 773 UNLOCK(&val->lock); 774 if (want_destroy) { 775 destroy(val); 776 } 777 } 778 779 /*% 780 * Callback when the CNAME record has been validated. 781 * 782 * Resumes validation of the unsecure zone proof. 783 */ 784 static void 785 validator_callback_cname(isc_task_t *task, isc_event_t *event) { 786 dns_validatorevent_t *devent; 787 dns_validator_t *val; 788 bool want_destroy; 789 isc_result_t result; 790 isc_result_t eresult; 791 792 UNUSED(task); 793 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); 794 795 devent = (dns_validatorevent_t *)event; 796 val = devent->ev_arg; 797 eresult = devent->result; 798 799 isc_event_free(&event); 800 dns_validator_destroy(&val->subvalidator); 801 802 INSIST(val->event != NULL); 803 INSIST((val->attributes & VALATTR_INSECURITY) != 0); 804 805 validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_cname"); 806 LOCK(&val->lock); 807 if (CANCELED(val)) { 808 validator_done(val, ISC_R_CANCELED); 809 } else if (eresult == ISC_R_SUCCESS) { 810 validator_log(val, ISC_LOG_DEBUG(3), "cname with trust %s", 811 dns_trust_totext(val->frdataset.trust)); 812 result = proveunsecure(val, false, true); 813 if (result != DNS_R_WAIT) { 814 validator_done(val, result); 815 } 816 } else { 817 if (eresult != DNS_R_BROKENCHAIN) { 818 expire_rdatasets(val); 819 } 820 validator_log(val, ISC_LOG_DEBUG(3), 821 "validator_callback_cname: got %s", 822 isc_result_totext(eresult)); 823 validator_done(val, DNS_R_BROKENCHAIN); 824 } 825 826 want_destroy = exit_check(val); 827 UNLOCK(&val->lock); 828 if (want_destroy) { 829 destroy(val); 830 } 831 } 832 833 /*% 834 * Callback for when NSEC records have been validated. 835 * 836 * Looks for NOQNAME, NODATA and OPTOUT proofs. 837 * 838 * Resumes the negative response validation by calling validate_nx(). 839 */ 840 static void 841 validator_callback_nsec(isc_task_t *task, isc_event_t *event) { 842 dns_validatorevent_t *devent; 843 dns_validator_t *val; 844 dns_rdataset_t *rdataset; 845 bool want_destroy; 846 isc_result_t result; 847 bool exists, data; 848 849 UNUSED(task); 850 INSIST(event->ev_type == DNS_EVENT_VALIDATORDONE); 851 852 devent = (dns_validatorevent_t *)event; 853 rdataset = devent->rdataset; 854 val = devent->ev_arg; 855 result = devent->result; 856 dns_validator_destroy(&val->subvalidator); 857 858 INSIST(val->event != NULL); 859 860 validator_log(val, ISC_LOG_DEBUG(3), "in validator_callback_nsec"); 861 LOCK(&val->lock); 862 if (CANCELED(val)) { 863 validator_done(val, ISC_R_CANCELED); 864 } else if (result != ISC_R_SUCCESS) { 865 validator_log(val, ISC_LOG_DEBUG(3), 866 "validator_callback_nsec: got %s", 867 isc_result_totext(result)); 868 if (result == DNS_R_BROKENCHAIN) { 869 val->authfail++; 870 } 871 if (result == ISC_R_CANCELED) { 872 validator_done(val, result); 873 } else { 874 result = validate_nx(val, true); 875 if (result != DNS_R_WAIT) { 876 validator_done(val, result); 877 } 878 } 879 } else { 880 dns_name_t **proofs = val->event->proofs; 881 dns_name_t *wild = dns_fixedname_name(&val->wild); 882 883 if (rdataset->type == dns_rdatatype_nsec && 884 rdataset->trust == dns_trust_secure && 885 (NEEDNODATA(val) || NEEDNOQNAME(val)) && 886 !FOUNDNODATA(val) && !FOUNDNOQNAME(val) && 887 dns_nsec_noexistnodata(val->event->type, val->event->name, 888 devent->name, rdataset, &exists, 889 &data, wild, validator_log, 890 val) == ISC_R_SUCCESS) 891 { 892 if (exists && !data) { 893 val->attributes |= VALATTR_FOUNDNODATA; 894 if (NEEDNODATA(val)) { 895 proofs[DNS_VALIDATOR_NODATAPROOF] = 896 devent->name; 897 } 898 } 899 if (!exists) { 900 dns_name_t *closest; 901 unsigned int clabels; 902 903 val->attributes |= VALATTR_FOUNDNOQNAME; 904 905 closest = dns_fixedname_name(&val->closest); 906 clabels = dns_name_countlabels(closest); 907 /* 908 * If we are validating a wildcard response 909 * clabels will not be zero. We then need 910 * to check if the generated wildcard from 911 * dns_nsec_noexistnodata is consistent with 912 * the wildcard used to generate the response. 913 */ 914 if (clabels == 0 || 915 dns_name_countlabels(wild) == clabels + 1) 916 { 917 val->attributes |= VALATTR_FOUNDCLOSEST; 918 } 919 /* 920 * The NSEC noqname proof also contains 921 * the closest encloser. 922 */ 923 if (NEEDNOQNAME(val)) { 924 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = 925 devent->name; 926 } 927 } 928 } 929 930 result = validate_nx(val, true); 931 if (result != DNS_R_WAIT) { 932 validator_done(val, result); 933 } 934 } 935 936 want_destroy = exit_check(val); 937 UNLOCK(&val->lock); 938 if (want_destroy) { 939 destroy(val); 940 } 941 942 /* 943 * Free stuff from the event. 944 */ 945 isc_event_free(&event); 946 } 947 948 /*% 949 * Looks for the requested name and type in the view (zones and cache). 950 * 951 * Returns: 952 * \li ISC_R_SUCCESS 953 * \li ISC_R_NOTFOUND 954 * \li DNS_R_NCACHENXDOMAIN 955 * \li DNS_R_NCACHENXRRSET 956 * \li DNS_R_NXRRSET 957 * \li DNS_R_NXDOMAIN 958 * \li DNS_R_BROKENCHAIN 959 */ 960 static isc_result_t 961 view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) { 962 dns_fixedname_t fixedname; 963 dns_name_t *foundname; 964 isc_result_t result; 965 unsigned int options; 966 isc_time_t now; 967 char namebuf[DNS_NAME_FORMATSIZE]; 968 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 969 970 disassociate_rdatasets(val); 971 972 if (isc_time_now(&now) == ISC_R_SUCCESS && 973 dns_resolver_getbadcache(val->view->resolver, name, type, &now)) 974 { 975 dns_name_format(name, namebuf, sizeof(namebuf)); 976 dns_rdatatype_format(type, typebuf, sizeof(typebuf)); 977 validator_log(val, ISC_LOG_INFO, "bad cache hit (%s/%s)", 978 namebuf, typebuf); 979 return (DNS_R_BROKENCHAIN); 980 } 981 982 options = DNS_DBFIND_PENDINGOK; 983 foundname = dns_fixedname_initname(&fixedname); 984 result = dns_view_find(val->view, name, type, 0, options, false, false, 985 NULL, NULL, foundname, &val->frdataset, 986 &val->fsigrdataset); 987 988 if (result == DNS_R_NXDOMAIN) { 989 goto notfound; 990 } else if (result != ISC_R_SUCCESS && result != DNS_R_NCACHENXDOMAIN && 991 result != DNS_R_NCACHENXRRSET && result != DNS_R_EMPTYNAME && 992 result != DNS_R_NXRRSET && result != ISC_R_NOTFOUND) 993 { 994 result = ISC_R_NOTFOUND; 995 goto notfound; 996 } 997 998 return (result); 999 1000 notfound: 1001 disassociate_rdatasets(val); 1002 1003 return (result); 1004 } 1005 1006 /*% 1007 * Checks to make sure we are not going to loop. As we use a SHARED fetch 1008 * the validation process will stall if looping was to occur. 1009 */ 1010 static bool 1011 check_deadlock(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, 1012 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 1013 dns_validator_t *parent; 1014 1015 for (parent = val; parent != NULL; parent = parent->parent) { 1016 if (parent->event != NULL && parent->event->type == type && 1017 dns_name_equal(parent->event->name, name) && 1018 /* 1019 * As NSEC3 records are meta data you sometimes 1020 * need to prove a NSEC3 record which says that 1021 * itself doesn't exist. 1022 */ 1023 (parent->event->type != dns_rdatatype_nsec3 || 1024 rdataset == NULL || sigrdataset == NULL || 1025 parent->event->message == NULL || 1026 parent->event->rdataset != NULL || 1027 parent->event->sigrdataset != NULL)) 1028 { 1029 validator_log(val, ISC_LOG_DEBUG(3), 1030 "continuing validation would lead to " 1031 "deadlock: aborting validation"); 1032 return (true); 1033 } 1034 } 1035 return (false); 1036 } 1037 1038 /*% 1039 * Start a fetch for the requested name and type. 1040 */ 1041 static isc_result_t 1042 create_fetch(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, 1043 isc_taskaction_t callback, const char *caller) { 1044 unsigned int fopts = 0; 1045 1046 disassociate_rdatasets(val); 1047 1048 if (check_deadlock(val, name, type, NULL, NULL)) { 1049 validator_log(val, ISC_LOG_DEBUG(3), 1050 "deadlock found (create_fetch)"); 1051 return (DNS_R_NOVALIDSIG); 1052 } 1053 1054 if ((val->options & DNS_VALIDATOR_NOCDFLAG) != 0) { 1055 fopts |= DNS_FETCHOPT_NOCDFLAG; 1056 } 1057 1058 if ((val->options & DNS_VALIDATOR_NONTA) != 0) { 1059 fopts |= DNS_FETCHOPT_NONTA; 1060 } 1061 1062 validator_logcreate(val, name, type, caller, "fetch"); 1063 return (dns_resolver_createfetch( 1064 val->view->resolver, name, type, NULL, NULL, NULL, NULL, 0, 1065 fopts, 0, NULL, val->event->ev_sender, callback, val, 1066 &val->frdataset, &val->fsigrdataset, &val->fetch)); 1067 } 1068 1069 /*% 1070 * Start a subvalidation process. 1071 */ 1072 static isc_result_t 1073 create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type, 1074 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 1075 isc_taskaction_t action, const char *caller) { 1076 isc_result_t result; 1077 unsigned int vopts = 0; 1078 dns_rdataset_t *sig = NULL; 1079 1080 if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset)) { 1081 sig = sigrdataset; 1082 } 1083 1084 if (check_deadlock(val, name, type, rdataset, sig)) { 1085 validator_log(val, ISC_LOG_DEBUG(3), 1086 "deadlock found (create_validator)"); 1087 return (DNS_R_NOVALIDSIG); 1088 } 1089 1090 /* OK to clear other options, but preserve NOCDFLAG and NONTA. */ 1091 vopts |= (val->options & 1092 (DNS_VALIDATOR_NOCDFLAG | DNS_VALIDATOR_NONTA)); 1093 1094 validator_logcreate(val, name, type, caller, "validator"); 1095 result = dns_validator_create(val->view, name, type, rdataset, sig, 1096 NULL, vopts, val->task, action, val, 1097 val->qc, &val->subvalidator); 1098 if (result == ISC_R_SUCCESS) { 1099 val->subvalidator->parent = val; 1100 val->subvalidator->depth = val->depth + 1; 1101 } 1102 return (result); 1103 } 1104 1105 /*% 1106 * Try to find a key that could have signed val->siginfo among those in 1107 * 'rdataset'. If found, build a dst_key_t for it and point val->key at 1108 * it. 1109 * 1110 * If val->key is already non-NULL, start searching from the next position in 1111 * 'rdataset' to find the *next* key that could have signed 'siginfo', then 1112 * set val->key to that. 1113 * 1114 * Returns ISC_R_SUCCESS if a possible matching key has been found, 1115 * ISC_R_NOTFOUND if not. Any other value indicates error. 1116 */ 1117 static isc_result_t 1118 select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) { 1119 isc_result_t result; 1120 dns_rdata_rrsig_t *siginfo = val->siginfo; 1121 isc_buffer_t b; 1122 dns_rdata_t rdata = DNS_RDATA_INIT; 1123 dst_key_t *oldkey = val->key; 1124 bool no_rdata = false; 1125 1126 if (oldkey == NULL) { 1127 result = dns_rdataset_first(rdataset); 1128 } else { 1129 dst_key_free(&oldkey); 1130 val->key = NULL; 1131 result = dns_rdataset_next(rdataset); 1132 } 1133 if (result != ISC_R_SUCCESS) { 1134 goto done; 1135 } 1136 1137 do { 1138 dns_rdataset_current(rdataset, &rdata); 1139 1140 isc_buffer_init(&b, rdata.data, rdata.length); 1141 isc_buffer_add(&b, rdata.length); 1142 INSIST(val->key == NULL); 1143 result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b, 1144 val->view->mctx, no_rdata, 1145 &val->key); 1146 if (result == ISC_R_SUCCESS) { 1147 if (siginfo->algorithm == 1148 (dns_secalg_t)dst_key_alg(val->key) && 1149 siginfo->keyid == 1150 (dns_keytag_t)dst_key_id(val->key) && 1151 (dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) == 1152 0 && 1153 dst_key_iszonekey(val->key)) 1154 { 1155 if (no_rdata) { 1156 /* Retry with full key */ 1157 dns_rdata_reset(&rdata); 1158 dst_key_free(&val->key); 1159 no_rdata = false; 1160 continue; 1161 } 1162 /* This is the key we're looking for. */ 1163 goto done; 1164 } 1165 dst_key_free(&val->key); 1166 } 1167 dns_rdata_reset(&rdata); 1168 result = dns_rdataset_next(rdataset); 1169 no_rdata = true; 1170 } while (result == ISC_R_SUCCESS); 1171 1172 done: 1173 if (result == ISC_R_NOMORE) { 1174 result = ISC_R_NOTFOUND; 1175 } 1176 1177 return (result); 1178 } 1179 1180 /*% 1181 * Get the key that generated the signature in val->siginfo. 1182 */ 1183 static isc_result_t 1184 seek_dnskey(dns_validator_t *val) { 1185 isc_result_t result; 1186 dns_rdata_rrsig_t *siginfo = val->siginfo; 1187 unsigned int nlabels; 1188 int order; 1189 dns_namereln_t namereln; 1190 1191 /* 1192 * Is the signer name appropriate for this signature? 1193 * 1194 * The signer name must be at the same level as the owner name 1195 * or closer to the DNS root. 1196 */ 1197 namereln = dns_name_fullcompare(val->event->name, &siginfo->signer, 1198 &order, &nlabels); 1199 if (namereln != dns_namereln_subdomain && 1200 namereln != dns_namereln_equal) 1201 { 1202 return (DNS_R_CONTINUE); 1203 } 1204 1205 if (namereln == dns_namereln_equal) { 1206 /* 1207 * If this is a self-signed keyset, it must not be a zone key 1208 * (since seek_dnskey is not called from validate_dnskey). 1209 */ 1210 if (val->event->rdataset->type == dns_rdatatype_dnskey) { 1211 return (DNS_R_CONTINUE); 1212 } 1213 1214 /* 1215 * Records appearing in the parent zone at delegation 1216 * points cannot be self-signed. 1217 */ 1218 if (dns_rdatatype_atparent(val->event->rdataset->type)) { 1219 return (DNS_R_CONTINUE); 1220 } 1221 } else { 1222 /* 1223 * SOA and NS RRsets can only be signed by a key with 1224 * the same name. 1225 */ 1226 if (val->event->rdataset->type == dns_rdatatype_soa || 1227 val->event->rdataset->type == dns_rdatatype_ns) 1228 { 1229 const char *type; 1230 1231 if (val->event->rdataset->type == dns_rdatatype_soa) { 1232 type = "SOA"; 1233 } else { 1234 type = "NS"; 1235 } 1236 validator_log(val, ISC_LOG_DEBUG(3), 1237 "%s signer mismatch", type); 1238 return (DNS_R_CONTINUE); 1239 } 1240 } 1241 1242 /* 1243 * Do we know about this key? 1244 */ 1245 result = view_find(val, &siginfo->signer, dns_rdatatype_dnskey); 1246 switch (result) { 1247 case ISC_R_SUCCESS: 1248 /* 1249 * We have an rrset for the given keyname. 1250 */ 1251 val->keyset = &val->frdataset; 1252 if ((DNS_TRUST_PENDING(val->frdataset.trust) || 1253 DNS_TRUST_ANSWER(val->frdataset.trust)) && 1254 dns_rdataset_isassociated(&val->fsigrdataset)) 1255 { 1256 /* 1257 * We know the key but haven't validated it yet or 1258 * we have a key of trust answer but a DS 1259 * record for the zone may have been added. 1260 */ 1261 result = create_validator( 1262 val, &siginfo->signer, dns_rdatatype_dnskey, 1263 &val->frdataset, &val->fsigrdataset, 1264 validator_callback_dnskey, "seek_dnskey"); 1265 if (result != ISC_R_SUCCESS) { 1266 return (result); 1267 } 1268 return (DNS_R_WAIT); 1269 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) { 1270 /* 1271 * Having a pending key with no signature means that 1272 * something is broken. 1273 */ 1274 result = DNS_R_CONTINUE; 1275 } else if (val->frdataset.trust < dns_trust_secure) { 1276 /* 1277 * The key is legitimately insecure. There's no 1278 * point in even attempting verification. 1279 */ 1280 val->key = NULL; 1281 result = ISC_R_SUCCESS; 1282 } else { 1283 /* 1284 * See if we've got the key used in the signature. 1285 */ 1286 validator_log(val, ISC_LOG_DEBUG(3), 1287 "keyset with trust %s", 1288 dns_trust_totext(val->frdataset.trust)); 1289 result = select_signing_key(val, val->keyset); 1290 if (result != ISC_R_SUCCESS) { 1291 /* 1292 * Either the key we're looking for is not 1293 * in the rrset, or something bad happened. 1294 * Give up. 1295 */ 1296 result = DNS_R_CONTINUE; 1297 } 1298 } 1299 break; 1300 1301 case ISC_R_NOTFOUND: 1302 /* 1303 * We don't know anything about this key. 1304 */ 1305 result = create_fetch(val, &siginfo->signer, 1306 dns_rdatatype_dnskey, 1307 fetch_callback_dnskey, "seek_dnskey"); 1308 if (result != ISC_R_SUCCESS) { 1309 return (result); 1310 } 1311 return (DNS_R_WAIT); 1312 1313 case DNS_R_NCACHENXDOMAIN: 1314 case DNS_R_NCACHENXRRSET: 1315 case DNS_R_EMPTYNAME: 1316 case DNS_R_NXDOMAIN: 1317 case DNS_R_NXRRSET: 1318 /* 1319 * This key doesn't exist. 1320 */ 1321 result = DNS_R_CONTINUE; 1322 break; 1323 1324 case DNS_R_BROKENCHAIN: 1325 return (result); 1326 1327 default: 1328 break; 1329 } 1330 1331 if (dns_rdataset_isassociated(&val->frdataset) && 1332 val->keyset != &val->frdataset) 1333 { 1334 dns_rdataset_disassociate(&val->frdataset); 1335 } 1336 if (dns_rdataset_isassociated(&val->fsigrdataset)) { 1337 dns_rdataset_disassociate(&val->fsigrdataset); 1338 } 1339 1340 return (result); 1341 } 1342 1343 /* 1344 * Compute the tag for a key represented in a DNSKEY rdata. 1345 */ 1346 static dns_keytag_t 1347 compute_keytag(dns_rdata_t *rdata) { 1348 isc_region_t r; 1349 1350 dns_rdata_toregion(rdata, &r); 1351 return (dst_region_computeid(&r)); 1352 } 1353 1354 /*% 1355 * Is the DNSKEY rrset in val->event->rdataset self-signed? 1356 */ 1357 static bool 1358 selfsigned_dnskey(dns_validator_t *val) { 1359 dns_rdataset_t *rdataset = val->event->rdataset; 1360 dns_rdataset_t *sigrdataset = val->event->sigrdataset; 1361 dns_name_t *name = val->event->name; 1362 isc_result_t result; 1363 isc_mem_t *mctx = val->view->mctx; 1364 bool answer = false; 1365 1366 if (rdataset->type != dns_rdatatype_dnskey) { 1367 return (false); 1368 } 1369 1370 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 1371 result = dns_rdataset_next(rdataset)) 1372 { 1373 dns_rdata_t keyrdata = DNS_RDATA_INIT; 1374 dns_rdata_t sigrdata = DNS_RDATA_INIT; 1375 dns_rdata_dnskey_t key; 1376 dns_rdata_rrsig_t sig; 1377 dns_keytag_t keytag; 1378 1379 dns_rdata_reset(&keyrdata); 1380 dns_rdataset_current(rdataset, &keyrdata); 1381 result = dns_rdata_tostruct(&keyrdata, &key, NULL); 1382 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1383 keytag = compute_keytag(&keyrdata); 1384 1385 for (result = dns_rdataset_first(sigrdataset); 1386 result == ISC_R_SUCCESS; 1387 result = dns_rdataset_next(sigrdataset)) 1388 { 1389 dst_key_t *dstkey = NULL; 1390 1391 dns_rdata_reset(&sigrdata); 1392 dns_rdataset_current(sigrdataset, &sigrdata); 1393 result = dns_rdata_tostruct(&sigrdata, &sig, NULL); 1394 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1395 1396 if (sig.algorithm != key.algorithm || 1397 sig.keyid != keytag || 1398 !dns_name_equal(name, &sig.signer)) 1399 { 1400 continue; 1401 } 1402 1403 /* 1404 * If the REVOKE bit is not set we have a 1405 * theoretically self signed DNSKEY RRset. 1406 * This will be verified later. 1407 */ 1408 if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) { 1409 answer = true; 1410 continue; 1411 } 1412 1413 result = dns_dnssec_keyfromrdata(name, &keyrdata, mctx, 1414 &dstkey); 1415 if (result != ISC_R_SUCCESS) { 1416 continue; 1417 } 1418 1419 /* 1420 * If this RRset is pending and it is trusted, 1421 * see if it was self signed by this DNSKEY. 1422 */ 1423 if (DNS_TRUST_PENDING(rdataset->trust) && 1424 dns_view_istrusted(val->view, name, &key)) 1425 { 1426 result = dns_dnssec_verify( 1427 name, rdataset, dstkey, true, 1428 val->view->maxbits, mctx, &sigrdata, 1429 NULL); 1430 if (result == ISC_R_SUCCESS) { 1431 /* 1432 * The key with the REVOKE flag has 1433 * self signed the RRset so it is no 1434 * good. 1435 */ 1436 dns_view_untrust(val->view, name, &key); 1437 } 1438 } else if (rdataset->trust >= dns_trust_secure) { 1439 /* 1440 * We trust this RRset so if the key is 1441 * marked revoked remove it. 1442 */ 1443 dns_view_untrust(val->view, name, &key); 1444 } 1445 1446 dst_key_free(&dstkey); 1447 } 1448 } 1449 1450 return (answer); 1451 } 1452 1453 /*% 1454 * Attempt to verify the rdataset using the given key and rdata (RRSIG). 1455 * The signature was good and from a wildcard record and the QNAME does 1456 * not match the wildcard we need to look for a NOQNAME proof. 1457 * 1458 * Returns: 1459 * \li ISC_R_SUCCESS if the verification succeeds. 1460 * \li Others if the verification fails. 1461 */ 1462 static isc_result_t 1463 verify(dns_validator_t *val, dst_key_t *key, dns_rdata_t *rdata, 1464 uint16_t keyid) { 1465 isc_result_t result; 1466 dns_fixedname_t fixed; 1467 bool ignore = false; 1468 dns_name_t *wild; 1469 1470 val->attributes |= VALATTR_TRIEDVERIFY; 1471 wild = dns_fixedname_initname(&fixed); 1472 again: 1473 result = dns_dnssec_verify(val->event->name, val->event->rdataset, key, 1474 ignore, val->view->maxbits, val->view->mctx, 1475 rdata, wild); 1476 if ((result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) && 1477 val->view->acceptexpired) 1478 { 1479 ignore = true; 1480 goto again; 1481 } 1482 1483 if (ignore && (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD)) 1484 { 1485 validator_log(val, ISC_LOG_INFO, 1486 "accepted expired %sRRSIG (keyid=%u)", 1487 (result == DNS_R_FROMWILDCARD) ? "wildcard " : "", 1488 keyid); 1489 } else if (result == DNS_R_SIGEXPIRED || result == DNS_R_SIGFUTURE) { 1490 validator_log(val, ISC_LOG_INFO, 1491 "verify failed due to bad signature (keyid=%u): " 1492 "%s", 1493 keyid, isc_result_totext(result)); 1494 } else { 1495 validator_log(val, ISC_LOG_DEBUG(3), 1496 "verify rdataset (keyid=%u): %s", keyid, 1497 isc_result_totext(result)); 1498 } 1499 if (result == DNS_R_FROMWILDCARD) { 1500 if (!dns_name_equal(val->event->name, wild)) { 1501 dns_name_t *closest; 1502 unsigned int labels; 1503 1504 /* 1505 * Compute the closest encloser in case we need it 1506 * for the NSEC3 NOQNAME proof. 1507 */ 1508 closest = dns_fixedname_name(&val->closest); 1509 dns_name_copy(wild, closest); 1510 labels = dns_name_countlabels(closest) - 1; 1511 dns_name_getlabelsequence(closest, 1, labels, closest); 1512 val->attributes |= VALATTR_NEEDNOQNAME; 1513 } 1514 result = ISC_R_SUCCESS; 1515 } 1516 return (result); 1517 } 1518 1519 /*% 1520 * Attempts positive response validation of a normal RRset. 1521 * 1522 * Returns: 1523 * \li ISC_R_SUCCESS Validation completed successfully 1524 * \li DNS_R_WAIT Validation has started but is waiting 1525 * for an event. 1526 * \li Other return codes are possible and all indicate failure. 1527 */ 1528 static isc_result_t 1529 validate_answer(dns_validator_t *val, bool resume) { 1530 isc_result_t result, vresult = DNS_R_NOVALIDSIG; 1531 dns_validatorevent_t *event; 1532 dns_rdata_t rdata = DNS_RDATA_INIT; 1533 1534 /* 1535 * Caller must be holding the validator lock. 1536 */ 1537 1538 event = val->event; 1539 1540 if (resume) { 1541 /* 1542 * We already have a sigrdataset. 1543 */ 1544 result = ISC_R_SUCCESS; 1545 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate"); 1546 } else { 1547 result = dns_rdataset_first(event->sigrdataset); 1548 } 1549 1550 for (; result == ISC_R_SUCCESS; 1551 result = dns_rdataset_next(event->sigrdataset)) 1552 { 1553 dns_rdata_reset(&rdata); 1554 dns_rdataset_current(event->sigrdataset, &rdata); 1555 if (val->siginfo == NULL) { 1556 val->siginfo = isc_mem_get(val->view->mctx, 1557 sizeof(*val->siginfo)); 1558 } 1559 result = dns_rdata_tostruct(&rdata, val->siginfo, NULL); 1560 if (result != ISC_R_SUCCESS) { 1561 return (result); 1562 } 1563 1564 /* 1565 * At this point we could check that the signature algorithm 1566 * was known and "sufficiently good". 1567 */ 1568 if (!dns_resolver_algorithm_supported(val->view->resolver, 1569 event->name, 1570 val->siginfo->algorithm)) 1571 { 1572 resume = false; 1573 continue; 1574 } 1575 1576 if (!resume) { 1577 result = seek_dnskey(val); 1578 if (result == DNS_R_CONTINUE) { 1579 continue; /* Try the next SIG RR. */ 1580 } 1581 if (result != ISC_R_SUCCESS) { 1582 return (result); 1583 } 1584 } 1585 1586 /* 1587 * There isn't a secure DNSKEY for this signature so move 1588 * onto the next RRSIG. 1589 */ 1590 if (val->key == NULL) { 1591 resume = false; 1592 continue; 1593 } 1594 1595 vresult = verify(val, val->key, &rdata, val->siginfo->keyid); 1596 if (vresult == DNS_R_SIGEXPIRED || vresult == DNS_R_SIGFUTURE) { 1597 resume = false; 1598 continue; 1599 } 1600 if (vresult != ISC_R_SUCCESS) { 1601 val->failed = true; 1602 validator_log(val, ISC_LOG_DEBUG(3), 1603 "failed to verify rdataset"); 1604 } else { 1605 dns_rdataset_trimttl(event->rdataset, 1606 event->sigrdataset, val->siginfo, 1607 val->start, 1608 val->view->acceptexpired); 1609 } 1610 1611 if (val->key != NULL) { 1612 dst_key_free(&val->key); 1613 } 1614 if (val->keyset != NULL) { 1615 dns_rdataset_disassociate(val->keyset); 1616 val->keyset = NULL; 1617 } 1618 val->key = NULL; 1619 if (NEEDNOQNAME(val)) { 1620 if (val->event->message == NULL) { 1621 validator_log(val, ISC_LOG_DEBUG(3), 1622 "no message available " 1623 "for noqname proof"); 1624 return (DNS_R_NOVALIDSIG); 1625 } 1626 validator_log(val, ISC_LOG_DEBUG(3), 1627 "looking for noqname proof"); 1628 return (validate_nx(val, false)); 1629 } else if (vresult == ISC_R_SUCCESS) { 1630 marksecure(event); 1631 validator_log(val, ISC_LOG_DEBUG(3), 1632 "marking as secure, " 1633 "noqname proof not needed"); 1634 return (ISC_R_SUCCESS); 1635 } else { 1636 validator_log(val, ISC_LOG_DEBUG(3), 1637 "verify failure: %s", 1638 isc_result_totext(vresult)); 1639 resume = false; 1640 } 1641 if (val->failed) { 1642 result = ISC_R_NOMORE; 1643 break; 1644 } 1645 } 1646 if (result != ISC_R_NOMORE) { 1647 validator_log(val, ISC_LOG_DEBUG(3), 1648 "failed to iterate signatures: %s", 1649 isc_result_totext(result)); 1650 return (result); 1651 } 1652 1653 validator_log(val, ISC_LOG_INFO, "no valid signature found"); 1654 return (vresult); 1655 } 1656 1657 /*% 1658 * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset 1659 * (val->event->rdataset). 1660 */ 1661 static isc_result_t 1662 check_signer(dns_validator_t *val, dns_rdata_t *keyrdata, uint16_t keyid, 1663 dns_secalg_t algorithm) { 1664 dns_rdata_rrsig_t sig; 1665 dst_key_t *dstkey = NULL; 1666 isc_result_t result; 1667 1668 for (result = dns_rdataset_first(val->event->sigrdataset); 1669 result == ISC_R_SUCCESS; 1670 result = dns_rdataset_next(val->event->sigrdataset)) 1671 { 1672 dns_rdata_t rdata = DNS_RDATA_INIT; 1673 1674 dns_rdataset_current(val->event->sigrdataset, &rdata); 1675 result = dns_rdata_tostruct(&rdata, &sig, NULL); 1676 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1677 if (keyid != sig.keyid || algorithm != sig.algorithm) { 1678 continue; 1679 } 1680 if (dstkey == NULL) { 1681 result = dns_dnssec_keyfromrdata( 1682 val->event->name, keyrdata, val->view->mctx, 1683 &dstkey); 1684 if (result != ISC_R_SUCCESS) { 1685 /* 1686 * This really shouldn't happen, but... 1687 */ 1688 continue; 1689 } 1690 } 1691 result = verify(val, dstkey, &rdata, sig.keyid); 1692 if (result == ISC_R_SUCCESS) { 1693 break; 1694 } 1695 } 1696 1697 if (dstkey != NULL) { 1698 dst_key_free(&dstkey); 1699 } 1700 1701 return (result); 1702 } 1703 1704 /* 1705 * get_dsset() is called to look up a DS RRset corresponding to the name 1706 * of a DNSKEY record, either in the cache or, if necessary, by starting a 1707 * fetch. This is done in the context of validating a zone key to build a 1708 * trust chain. 1709 * 1710 * Returns: 1711 * \li ISC_R_COMPLETE a DS has not been found; the caller should 1712 * stop trying to validate the zone key and 1713 * return the result code in '*resp'. 1714 * \li DNS_R_CONTINUE a DS has been found and the caller may 1715 * continue the zone key validation. 1716 */ 1717 static isc_result_t 1718 get_dsset(dns_validator_t *val, dns_name_t *tname, isc_result_t *resp) { 1719 isc_result_t result; 1720 1721 result = view_find(val, tname, dns_rdatatype_ds); 1722 switch (result) { 1723 case ISC_R_SUCCESS: 1724 /* 1725 * We have a DS RRset. 1726 */ 1727 val->dsset = &val->frdataset; 1728 if ((DNS_TRUST_PENDING(val->frdataset.trust) || 1729 DNS_TRUST_ANSWER(val->frdataset.trust)) && 1730 dns_rdataset_isassociated(&val->fsigrdataset)) 1731 { 1732 /* 1733 * ... which is signed but not yet validated. 1734 */ 1735 result = create_validator( 1736 val, tname, dns_rdatatype_ds, &val->frdataset, 1737 &val->fsigrdataset, validator_callback_ds, 1738 "validate_dnskey"); 1739 *resp = DNS_R_WAIT; 1740 if (result != ISC_R_SUCCESS) { 1741 *resp = result; 1742 } 1743 return (ISC_R_COMPLETE); 1744 } else if (DNS_TRUST_PENDING(val->frdataset.trust)) { 1745 /* 1746 * There should never be an unsigned DS. 1747 */ 1748 disassociate_rdatasets(val); 1749 validator_log(val, ISC_LOG_DEBUG(2), 1750 "unsigned DS record"); 1751 *resp = DNS_R_NOVALIDSIG; 1752 return (ISC_R_COMPLETE); 1753 } 1754 break; 1755 1756 case ISC_R_NOTFOUND: 1757 /* 1758 * We don't have the DS. Find it. 1759 */ 1760 result = create_fetch(val, tname, dns_rdatatype_ds, 1761 fetch_callback_ds, "validate_dnskey"); 1762 *resp = DNS_R_WAIT; 1763 if (result != ISC_R_SUCCESS) { 1764 *resp = result; 1765 } 1766 return (ISC_R_COMPLETE); 1767 1768 case DNS_R_NCACHENXDOMAIN: 1769 case DNS_R_NCACHENXRRSET: 1770 case DNS_R_EMPTYNAME: 1771 case DNS_R_NXDOMAIN: 1772 case DNS_R_NXRRSET: 1773 case DNS_R_CNAME: 1774 /* 1775 * The DS does not exist. 1776 */ 1777 disassociate_rdatasets(val); 1778 validator_log(val, ISC_LOG_DEBUG(2), "no DS record"); 1779 *resp = DNS_R_NOVALIDSIG; 1780 return (ISC_R_COMPLETE); 1781 1782 case DNS_R_BROKENCHAIN: 1783 *resp = result; 1784 return (ISC_R_COMPLETE); 1785 1786 default: 1787 break; 1788 } 1789 1790 return (DNS_R_CONTINUE); 1791 } 1792 1793 /*% 1794 * Attempts positive response validation of an RRset containing zone keys 1795 * (i.e. a DNSKEY rrset). 1796 * 1797 * Caller must be holding the validator lock. 1798 * 1799 * Returns: 1800 * \li ISC_R_SUCCESS Validation completed successfully 1801 * \li DNS_R_WAIT Validation has started but is waiting 1802 * for an event. 1803 * \li Other return codes are possible and all indicate failure. 1804 */ 1805 static isc_result_t 1806 validate_dnskey(dns_validator_t *val) { 1807 isc_result_t result; 1808 dns_rdata_t dsrdata = DNS_RDATA_INIT; 1809 dns_rdata_t keyrdata = DNS_RDATA_INIT; 1810 dns_keynode_t *keynode = NULL; 1811 dns_rdata_ds_t ds; 1812 bool supported_algorithm; 1813 char digest_types[256]; 1814 1815 /* 1816 * If we don't already have a DS RRset, check to see if there's 1817 * a DS style trust anchor configured for this key. 1818 */ 1819 if (val->dsset == NULL) { 1820 result = dns_keytable_find(val->keytable, val->event->name, 1821 &keynode); 1822 if (result == ISC_R_SUCCESS) { 1823 if (dns_keynode_dsset(keynode, &val->fdsset)) { 1824 val->dsset = &val->fdsset; 1825 } 1826 dns_keytable_detachkeynode(val->keytable, &keynode); 1827 } 1828 } 1829 1830 /* 1831 * No trust anchor for this name, so we look up the DS at the parent. 1832 */ 1833 if (val->dsset == NULL) { 1834 isc_result_t tresult = ISC_R_SUCCESS; 1835 1836 /* 1837 * If this is the root name and there was no trust anchor, 1838 * we can give up now, since there's no DS at the root. 1839 */ 1840 if (dns_name_equal(val->event->name, dns_rootname)) { 1841 if ((val->attributes & VALATTR_TRIEDVERIFY) != 0) { 1842 validator_log(val, ISC_LOG_DEBUG(3), 1843 "root key failed to validate"); 1844 } else { 1845 validator_log(val, ISC_LOG_DEBUG(3), 1846 "no trusted root key"); 1847 } 1848 result = DNS_R_NOVALIDSIG; 1849 goto cleanup; 1850 } 1851 1852 /* 1853 * Look up the DS RRset for this name. 1854 */ 1855 result = get_dsset(val, val->event->name, &tresult); 1856 if (result == ISC_R_COMPLETE) { 1857 result = tresult; 1858 goto cleanup; 1859 } 1860 } 1861 1862 /* 1863 * We have a DS set. 1864 */ 1865 INSIST(val->dsset != NULL); 1866 1867 if (val->dsset->trust < dns_trust_secure) { 1868 result = markanswer(val, "validate_dnskey (2)", "insecure DS"); 1869 goto cleanup; 1870 } 1871 1872 /* 1873 * Look through the DS record and find the keys that can sign the 1874 * key set and the matching signature. For each such key, attempt 1875 * verification. 1876 */ 1877 1878 supported_algorithm = false; 1879 1880 /* 1881 * If DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present we 1882 * are required to prefer it over DNS_DSDIGEST_SHA1. This in 1883 * practice means that we need to ignore DNS_DSDIGEST_SHA1 if a 1884 * DNS_DSDIGEST_SHA256 or DNS_DSDIGEST_SHA384 is present. 1885 */ 1886 memset(digest_types, 1, sizeof(digest_types)); 1887 for (result = dns_rdataset_first(val->dsset); result == ISC_R_SUCCESS; 1888 result = dns_rdataset_next(val->dsset)) 1889 { 1890 dns_rdata_reset(&dsrdata); 1891 dns_rdataset_current(val->dsset, &dsrdata); 1892 result = dns_rdata_tostruct(&dsrdata, &ds, NULL); 1893 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1894 1895 if (!dns_resolver_ds_digest_supported(val->view->resolver, 1896 val->event->name, 1897 ds.digest_type)) 1898 { 1899 continue; 1900 } 1901 1902 if (!dns_resolver_algorithm_supported(val->view->resolver, 1903 val->event->name, 1904 ds.algorithm)) 1905 { 1906 continue; 1907 } 1908 1909 if ((ds.digest_type == DNS_DSDIGEST_SHA256 && 1910 ds.length == ISC_SHA256_DIGESTLENGTH) || 1911 (ds.digest_type == DNS_DSDIGEST_SHA384 && 1912 ds.length == ISC_SHA384_DIGESTLENGTH)) 1913 { 1914 digest_types[DNS_DSDIGEST_SHA1] = 0; 1915 break; 1916 } 1917 } 1918 1919 for (result = dns_rdataset_first(val->dsset); result == ISC_R_SUCCESS; 1920 result = dns_rdataset_next(val->dsset)) 1921 { 1922 dns_rdata_reset(&dsrdata); 1923 dns_rdataset_current(val->dsset, &dsrdata); 1924 result = dns_rdata_tostruct(&dsrdata, &ds, NULL); 1925 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1926 1927 if (digest_types[ds.digest_type] == 0) { 1928 continue; 1929 } 1930 1931 if (!dns_resolver_ds_digest_supported(val->view->resolver, 1932 val->event->name, 1933 ds.digest_type)) 1934 { 1935 continue; 1936 } 1937 1938 if (!dns_resolver_algorithm_supported(val->view->resolver, 1939 val->event->name, 1940 ds.algorithm)) 1941 { 1942 continue; 1943 } 1944 1945 supported_algorithm = true; 1946 1947 /* 1948 * Find the DNSKEY matching the DS... 1949 */ 1950 result = dns_dnssec_matchdskey(val->event->name, &dsrdata, 1951 val->event->rdataset, &keyrdata); 1952 if (result != ISC_R_SUCCESS) { 1953 validator_log(val, ISC_LOG_DEBUG(3), 1954 "no DNSKEY matching DS"); 1955 continue; 1956 } 1957 1958 /* 1959 * ... and check that it signed the DNSKEY RRset. 1960 */ 1961 result = check_signer(val, &keyrdata, ds.key_tag, ds.algorithm); 1962 if (result == ISC_R_SUCCESS) { 1963 break; 1964 } 1965 validator_log(val, ISC_LOG_DEBUG(3), 1966 "no RRSIG matching DS key"); 1967 } 1968 1969 if (result == ISC_R_SUCCESS) { 1970 marksecure(val->event); 1971 validator_log(val, ISC_LOG_DEBUG(3), "marking as secure (DS)"); 1972 } else if (result == ISC_R_NOMORE && !supported_algorithm) { 1973 validator_log(val, ISC_LOG_DEBUG(3), 1974 "no supported algorithm/digest (DS)"); 1975 result = markanswer(val, "validate_dnskey (3)", 1976 "no supported algorithm/digest (DS)"); 1977 } else { 1978 validator_log(val, ISC_LOG_INFO, 1979 "no valid signature found (DS)"); 1980 result = DNS_R_NOVALIDSIG; 1981 } 1982 1983 cleanup: 1984 if (val->dsset == &val->fdsset) { 1985 val->dsset = NULL; 1986 dns_rdataset_disassociate(&val->fdsset); 1987 } 1988 1989 return (result); 1990 } 1991 1992 /*% 1993 * val_rdataset_first and val_rdataset_next provide iteration methods 1994 * that hide whether we are iterating across the AUTHORITY section of 1995 * a message, or a negative cache rdataset. 1996 */ 1997 static isc_result_t 1998 val_rdataset_first(dns_validator_t *val, dns_name_t **namep, 1999 dns_rdataset_t **rdatasetp) { 2000 dns_message_t *message = val->event->message; 2001 isc_result_t result; 2002 2003 REQUIRE(rdatasetp != NULL); 2004 REQUIRE(namep != NULL); 2005 if (message == NULL) { 2006 REQUIRE(*rdatasetp != NULL); 2007 REQUIRE(*namep != NULL); 2008 } else { 2009 REQUIRE(*rdatasetp == NULL); 2010 REQUIRE(*namep == NULL); 2011 } 2012 2013 if (message != NULL) { 2014 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); 2015 if (result != ISC_R_SUCCESS) { 2016 return (result); 2017 } 2018 dns_message_currentname(message, DNS_SECTION_AUTHORITY, namep); 2019 *rdatasetp = ISC_LIST_HEAD((*namep)->list); 2020 INSIST(*rdatasetp != NULL); 2021 } else { 2022 result = dns_rdataset_first(val->event->rdataset); 2023 if (result == ISC_R_SUCCESS) { 2024 dns_ncache_current(val->event->rdataset, *namep, 2025 *rdatasetp); 2026 } 2027 } 2028 return (result); 2029 } 2030 2031 static isc_result_t 2032 val_rdataset_next(dns_validator_t *val, dns_name_t **namep, 2033 dns_rdataset_t **rdatasetp) { 2034 dns_message_t *message = val->event->message; 2035 isc_result_t result = ISC_R_SUCCESS; 2036 2037 REQUIRE(rdatasetp != NULL && *rdatasetp != NULL); 2038 REQUIRE(namep != NULL && *namep != NULL); 2039 2040 if (message != NULL) { 2041 dns_rdataset_t *rdataset = *rdatasetp; 2042 rdataset = ISC_LIST_NEXT(rdataset, link); 2043 if (rdataset == NULL) { 2044 *namep = NULL; 2045 result = dns_message_nextname(message, 2046 DNS_SECTION_AUTHORITY); 2047 if (result == ISC_R_SUCCESS) { 2048 dns_message_currentname( 2049 message, DNS_SECTION_AUTHORITY, namep); 2050 rdataset = ISC_LIST_HEAD((*namep)->list); 2051 INSIST(rdataset != NULL); 2052 } 2053 } 2054 *rdatasetp = rdataset; 2055 } else { 2056 dns_rdataset_disassociate(*rdatasetp); 2057 result = dns_rdataset_next(val->event->rdataset); 2058 if (result == ISC_R_SUCCESS) { 2059 dns_ncache_current(val->event->rdataset, *namep, 2060 *rdatasetp); 2061 } 2062 } 2063 return (result); 2064 } 2065 2066 /*% 2067 * Look for NODATA at the wildcard and NOWILDCARD proofs in the 2068 * previously validated NSEC records. As these proofs are mutually 2069 * exclusive we stop when one is found. 2070 * 2071 * Returns 2072 * \li ISC_R_SUCCESS 2073 */ 2074 static isc_result_t 2075 checkwildcard(dns_validator_t *val, dns_rdatatype_t type, 2076 dns_name_t *zonename) { 2077 dns_name_t *name, *wild, tname; 2078 isc_result_t result; 2079 bool exists, data; 2080 char namebuf[DNS_NAME_FORMATSIZE]; 2081 dns_rdataset_t *rdataset, trdataset; 2082 2083 dns_name_init(&tname, NULL); 2084 dns_rdataset_init(&trdataset); 2085 wild = dns_fixedname_name(&val->wild); 2086 2087 if (dns_name_countlabels(wild) == 0) { 2088 validator_log(val, ISC_LOG_DEBUG(3), 2089 "in checkwildcard: no wildcard to check"); 2090 return (ISC_R_SUCCESS); 2091 } 2092 2093 dns_name_format(wild, namebuf, sizeof(namebuf)); 2094 validator_log(val, ISC_LOG_DEBUG(3), "in checkwildcard: %s", namebuf); 2095 2096 if (val->event->message == NULL) { 2097 name = &tname; 2098 rdataset = &trdataset; 2099 } else { 2100 name = NULL; 2101 rdataset = NULL; 2102 } 2103 2104 for (result = val_rdataset_first(val, &name, &rdataset); 2105 result == ISC_R_SUCCESS; 2106 result = val_rdataset_next(val, &name, &rdataset)) 2107 { 2108 if (rdataset->type != type || 2109 rdataset->trust != dns_trust_secure) 2110 { 2111 continue; 2112 } 2113 2114 if (rdataset->type == dns_rdatatype_nsec && 2115 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) && 2116 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) && 2117 dns_nsec_noexistnodata(val->event->type, wild, name, 2118 rdataset, &exists, &data, NULL, 2119 validator_log, val) == ISC_R_SUCCESS) 2120 { 2121 dns_name_t **proofs = val->event->proofs; 2122 if (exists && !data) { 2123 val->attributes |= VALATTR_FOUNDNODATA; 2124 } 2125 if (exists && !data && NEEDNODATA(val)) { 2126 proofs[DNS_VALIDATOR_NODATAPROOF] = name; 2127 } 2128 if (!exists) { 2129 val->attributes |= VALATTR_FOUNDNOWILDCARD; 2130 } 2131 if (!exists && NEEDNOQNAME(val)) { 2132 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name; 2133 } 2134 if (dns_rdataset_isassociated(&trdataset)) { 2135 dns_rdataset_disassociate(&trdataset); 2136 } 2137 return (ISC_R_SUCCESS); 2138 } 2139 2140 if (rdataset->type == dns_rdatatype_nsec3 && 2141 (NEEDNODATA(val) || NEEDNOWILDCARD(val)) && 2142 !FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) && 2143 dns_nsec3_noexistnodata( 2144 val->event->type, wild, name, rdataset, zonename, 2145 &exists, &data, NULL, NULL, NULL, NULL, NULL, NULL, 2146 validator_log, val) == ISC_R_SUCCESS) 2147 { 2148 dns_name_t **proofs = val->event->proofs; 2149 if (exists && !data) { 2150 val->attributes |= VALATTR_FOUNDNODATA; 2151 } 2152 if (exists && !data && NEEDNODATA(val)) { 2153 proofs[DNS_VALIDATOR_NODATAPROOF] = name; 2154 } 2155 if (!exists) { 2156 val->attributes |= VALATTR_FOUNDNOWILDCARD; 2157 } 2158 if (!exists && NEEDNOQNAME(val)) { 2159 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name; 2160 } 2161 if (dns_rdataset_isassociated(&trdataset)) { 2162 dns_rdataset_disassociate(&trdataset); 2163 } 2164 return (ISC_R_SUCCESS); 2165 } 2166 } 2167 if (result == ISC_R_NOMORE) { 2168 result = ISC_R_SUCCESS; 2169 } 2170 if (dns_rdataset_isassociated(&trdataset)) { 2171 dns_rdataset_disassociate(&trdataset); 2172 } 2173 return (result); 2174 } 2175 2176 /* 2177 * Look for the needed proofs for a negative or wildcard response 2178 * from a zone using NSEC3, and set flags in the validator as they 2179 * are found. 2180 */ 2181 static isc_result_t 2182 findnsec3proofs(dns_validator_t *val) { 2183 dns_name_t *name, tname; 2184 isc_result_t result; 2185 bool exists, data, optout, unknown; 2186 bool setclosest, setnearest, *setclosestp; 2187 dns_fixedname_t fclosest, fnearest, fzonename; 2188 dns_name_t *closest, *nearest, *zonename, *closestp; 2189 dns_name_t **proofs = val->event->proofs; 2190 dns_rdataset_t *rdataset, trdataset; 2191 2192 dns_name_init(&tname, NULL); 2193 dns_rdataset_init(&trdataset); 2194 closest = dns_fixedname_initname(&fclosest); 2195 nearest = dns_fixedname_initname(&fnearest); 2196 zonename = dns_fixedname_initname(&fzonename); 2197 2198 if (val->event->message == NULL) { 2199 name = &tname; 2200 rdataset = &trdataset; 2201 } else { 2202 name = NULL; 2203 rdataset = NULL; 2204 } 2205 2206 for (result = val_rdataset_first(val, &name, &rdataset); 2207 result == ISC_R_SUCCESS; 2208 result = val_rdataset_next(val, &name, &rdataset)) 2209 { 2210 if (rdataset->type != dns_rdatatype_nsec3 || 2211 rdataset->trust != dns_trust_secure) 2212 { 2213 continue; 2214 } 2215 2216 result = dns_nsec3_noexistnodata( 2217 val->event->type, val->event->name, name, rdataset, 2218 zonename, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2219 NULL, validator_log, val); 2220 if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) { 2221 if (dns_rdataset_isassociated(&trdataset)) { 2222 dns_rdataset_disassociate(&trdataset); 2223 } 2224 return (result); 2225 } 2226 } 2227 if (result != ISC_R_NOMORE) { 2228 result = ISC_R_SUCCESS; 2229 } 2230 POST(result); 2231 2232 if (dns_name_countlabels(zonename) == 0) { 2233 if (dns_rdataset_isassociated(&trdataset)) { 2234 dns_rdataset_disassociate(&trdataset); 2235 } 2236 return (ISC_R_SUCCESS); 2237 } 2238 2239 /* 2240 * If the val->closest is set then we want to use it otherwise 2241 * we need to discover it. 2242 */ 2243 if (dns_name_countlabels(dns_fixedname_name(&val->closest)) != 0) { 2244 char namebuf[DNS_NAME_FORMATSIZE]; 2245 2246 dns_name_format(dns_fixedname_name(&val->closest), namebuf, 2247 sizeof(namebuf)); 2248 validator_log(val, ISC_LOG_DEBUG(3), 2249 "closest encloser from wildcard signature '%s'", 2250 namebuf); 2251 dns_name_copy(dns_fixedname_name(&val->closest), closest); 2252 closestp = NULL; 2253 setclosestp = NULL; 2254 } else { 2255 closestp = closest; 2256 setclosestp = &setclosest; 2257 } 2258 2259 for (result = val_rdataset_first(val, &name, &rdataset); 2260 result == ISC_R_SUCCESS; 2261 result = val_rdataset_next(val, &name, &rdataset)) 2262 { 2263 if (rdataset->type != dns_rdatatype_nsec3 || 2264 rdataset->trust != dns_trust_secure) 2265 { 2266 continue; 2267 } 2268 2269 /* 2270 * We process all NSEC3 records to find the closest 2271 * encloser and nearest name to the closest encloser. 2272 */ 2273 setclosest = setnearest = false; 2274 optout = false; 2275 unknown = false; 2276 result = dns_nsec3_noexistnodata( 2277 val->event->type, val->event->name, name, rdataset, 2278 zonename, &exists, &data, &optout, &unknown, 2279 setclosestp, &setnearest, closestp, nearest, 2280 validator_log, val); 2281 if (unknown) { 2282 val->attributes |= VALATTR_FOUNDUNKNOWN; 2283 } 2284 if (result == DNS_R_NSEC3ITERRANGE) { 2285 /* 2286 * We don't really know which NSEC3 record provides 2287 * which proof. Just populate them. 2288 */ 2289 if (NEEDNOQNAME(val) && 2290 proofs[DNS_VALIDATOR_NOQNAMEPROOF] == NULL) 2291 { 2292 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name; 2293 } else if (setclosest) { 2294 proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name; 2295 } else if (NEEDNODATA(val) && 2296 proofs[DNS_VALIDATOR_NODATAPROOF] == NULL) 2297 { 2298 proofs[DNS_VALIDATOR_NODATAPROOF] = name; 2299 } else if (NEEDNOWILDCARD(val) && 2300 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] == 2301 NULL) 2302 { 2303 proofs[DNS_VALIDATOR_NOWILDCARDPROOF] = name; 2304 } 2305 if (dns_rdataset_isassociated(&trdataset)) { 2306 dns_rdataset_disassociate(&trdataset); 2307 } 2308 return (result); 2309 } 2310 if (result != ISC_R_SUCCESS) { 2311 continue; 2312 } 2313 if (setclosest) { 2314 proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name; 2315 } 2316 if (exists && !data && NEEDNODATA(val)) { 2317 val->attributes |= VALATTR_FOUNDNODATA; 2318 proofs[DNS_VALIDATOR_NODATAPROOF] = name; 2319 } 2320 if (!exists && setnearest) { 2321 val->attributes |= VALATTR_FOUNDNOQNAME; 2322 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name; 2323 if (optout) { 2324 val->attributes |= VALATTR_FOUNDOPTOUT; 2325 } 2326 } 2327 } 2328 if (result == ISC_R_NOMORE) { 2329 result = ISC_R_SUCCESS; 2330 } 2331 2332 /* 2333 * To know we have a valid noqname and optout proofs we need to also 2334 * have a valid closest encloser. Otherwise we could still be looking 2335 * at proofs from the parent zone. 2336 */ 2337 if (dns_name_countlabels(closest) > 0 && 2338 dns_name_countlabels(nearest) == 2339 dns_name_countlabels(closest) + 1 && 2340 dns_name_issubdomain(nearest, closest)) 2341 { 2342 val->attributes |= VALATTR_FOUNDCLOSEST; 2343 result = dns_name_concatenate(dns_wildcardname, closest, 2344 dns_fixedname_name(&val->wild), 2345 NULL); 2346 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2347 } else { 2348 val->attributes &= ~VALATTR_FOUNDNOQNAME; 2349 val->attributes &= ~VALATTR_FOUNDOPTOUT; 2350 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL; 2351 } 2352 2353 /* 2354 * Do we need to check for the wildcard? 2355 */ 2356 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && 2357 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) 2358 { 2359 result = checkwildcard(val, dns_rdatatype_nsec3, zonename); 2360 if (result != ISC_R_SUCCESS) { 2361 if (dns_rdataset_isassociated(&trdataset)) { 2362 dns_rdataset_disassociate(&trdataset); 2363 } 2364 return (result); 2365 } 2366 } 2367 if (dns_rdataset_isassociated(&trdataset)) { 2368 dns_rdataset_disassociate(&trdataset); 2369 } 2370 return (result); 2371 } 2372 2373 /* 2374 * Start a validator for negative response data. 2375 * 2376 * Returns: 2377 * \li DNS_R_CONTINUE Validation skipped, continue 2378 * \li DNS_R_WAIT Validation is in progress 2379 * 2380 * \li Other return codes indicate failure. 2381 */ 2382 static isc_result_t 2383 validate_neg_rrset(dns_validator_t *val, dns_name_t *name, 2384 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 2385 isc_result_t result; 2386 2387 /* 2388 * If a signed zone is missing the zone key, bad 2389 * things could happen. A query for data in the zone 2390 * would lead to a query for the zone key, which 2391 * would return a negative answer, which would contain 2392 * an SOA and an NSEC signed by the missing key, which 2393 * would trigger another query for the DNSKEY (since 2394 * the first one is still in progress), and go into an 2395 * infinite loop. Avoid that. 2396 */ 2397 if (val->event->type == dns_rdatatype_dnskey && 2398 rdataset->type == dns_rdatatype_nsec && 2399 dns_name_equal(name, val->event->name)) 2400 { 2401 dns_rdata_t nsec = DNS_RDATA_INIT; 2402 2403 result = dns_rdataset_first(rdataset); 2404 if (result != ISC_R_SUCCESS) { 2405 return (result); 2406 } 2407 dns_rdataset_current(rdataset, &nsec); 2408 if (dns_nsec_typepresent(&nsec, dns_rdatatype_soa)) { 2409 return (DNS_R_CONTINUE); 2410 } 2411 } 2412 2413 val->currentset = rdataset; 2414 result = create_validator(val, name, rdataset->type, rdataset, 2415 sigrdataset, validator_callback_nsec, 2416 "validate_neg_rrset"); 2417 if (result != ISC_R_SUCCESS) { 2418 return (result); 2419 } 2420 2421 val->authcount++; 2422 return (DNS_R_WAIT); 2423 } 2424 2425 /*% 2426 * Validate the authority section records. 2427 */ 2428 static isc_result_t 2429 validate_authority(dns_validator_t *val, bool resume) { 2430 dns_name_t *name; 2431 dns_message_t *message = val->event->message; 2432 isc_result_t result; 2433 2434 if (!resume) { 2435 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); 2436 } else { 2437 result = ISC_R_SUCCESS; 2438 } 2439 2440 for (; result == ISC_R_SUCCESS; 2441 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) 2442 { 2443 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 2444 2445 name = NULL; 2446 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); 2447 if (resume) { 2448 rdataset = ISC_LIST_NEXT(val->currentset, link); 2449 val->currentset = NULL; 2450 resume = false; 2451 } else { 2452 rdataset = ISC_LIST_HEAD(name->list); 2453 } 2454 2455 for (; rdataset != NULL; 2456 rdataset = ISC_LIST_NEXT(rdataset, link)) 2457 { 2458 if (rdataset->type == dns_rdatatype_rrsig) { 2459 continue; 2460 } 2461 2462 for (sigrdataset = ISC_LIST_HEAD(name->list); 2463 sigrdataset != NULL; 2464 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) 2465 { 2466 if (sigrdataset->type == dns_rdatatype_rrsig && 2467 sigrdataset->covers == rdataset->type) 2468 { 2469 break; 2470 } 2471 } 2472 2473 result = validate_neg_rrset(val, name, rdataset, 2474 sigrdataset); 2475 if (result != DNS_R_CONTINUE) { 2476 return (result); 2477 } 2478 } 2479 } 2480 if (result == ISC_R_NOMORE) { 2481 result = ISC_R_SUCCESS; 2482 } 2483 return (result); 2484 } 2485 2486 /*% 2487 * Validate negative cache elements. 2488 */ 2489 static isc_result_t 2490 validate_ncache(dns_validator_t *val, bool resume) { 2491 dns_name_t *name; 2492 isc_result_t result; 2493 2494 if (!resume) { 2495 result = dns_rdataset_first(val->event->rdataset); 2496 } else { 2497 result = dns_rdataset_next(val->event->rdataset); 2498 } 2499 2500 for (; result == ISC_R_SUCCESS; 2501 result = dns_rdataset_next(val->event->rdataset)) 2502 { 2503 dns_rdataset_t *rdataset, *sigrdataset = NULL; 2504 2505 disassociate_rdatasets(val); 2506 2507 name = dns_fixedname_initname(&val->fname); 2508 rdataset = &val->frdataset; 2509 dns_ncache_current(val->event->rdataset, name, rdataset); 2510 2511 if (val->frdataset.type == dns_rdatatype_rrsig) { 2512 continue; 2513 } 2514 2515 result = dns_ncache_getsigrdataset(val->event->rdataset, name, 2516 rdataset->type, 2517 &val->fsigrdataset); 2518 if (result == ISC_R_SUCCESS) { 2519 sigrdataset = &val->fsigrdataset; 2520 } 2521 2522 result = validate_neg_rrset(val, name, rdataset, sigrdataset); 2523 if (result == DNS_R_CONTINUE) { 2524 continue; 2525 } 2526 2527 return (result); 2528 } 2529 if (result == ISC_R_NOMORE) { 2530 result = ISC_R_SUCCESS; 2531 } 2532 2533 return (result); 2534 } 2535 2536 /*% 2537 * Prove a negative answer is good or that there is a NOQNAME when the 2538 * answer is from a wildcard. 2539 * 2540 * Loop through the authority section looking for NODATA, NOWILDCARD 2541 * and NOQNAME proofs in the NSEC records by calling 2542 * validator_callback_nsec(). 2543 * 2544 * If the required proofs are found we are done. 2545 * 2546 * If the proofs are not found attempt to prove this is an unsecure 2547 * response. 2548 */ 2549 static isc_result_t 2550 validate_nx(dns_validator_t *val, bool resume) { 2551 isc_result_t result; 2552 2553 if (resume) { 2554 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate_nx"); 2555 } 2556 2557 if (val->event->message == NULL) { 2558 result = validate_ncache(val, resume); 2559 } else { 2560 result = validate_authority(val, resume); 2561 } 2562 2563 if (result != ISC_R_SUCCESS) { 2564 return (result); 2565 } 2566 2567 /* 2568 * Do we only need to check for NOQNAME? To get here we must have 2569 * had a secure wildcard answer. 2570 */ 2571 if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) { 2572 if (!FOUNDNOQNAME(val)) { 2573 result = findnsec3proofs(val); 2574 if (result == DNS_R_NSEC3ITERRANGE) { 2575 validator_log(val, ISC_LOG_DEBUG(3), 2576 "too many iterations"); 2577 markanswer(val, "validate_nx (3)", NULL); 2578 return (ISC_R_SUCCESS); 2579 } 2580 } 2581 2582 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && !FOUNDOPTOUT(val)) 2583 { 2584 validator_log(val, ISC_LOG_DEBUG(3), 2585 "marking as secure, noqname proof found"); 2586 marksecure(val->event); 2587 return (ISC_R_SUCCESS); 2588 } else if (FOUNDOPTOUT(val) && 2589 dns_name_countlabels( 2590 dns_fixedname_name(&val->wild)) != 0) 2591 { 2592 validator_log(val, ISC_LOG_DEBUG(3), 2593 "optout proof found"); 2594 val->event->optout = true; 2595 markanswer(val, "validate_nx (1)", NULL); 2596 return (ISC_R_SUCCESS); 2597 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) { 2598 validator_log(val, ISC_LOG_DEBUG(3), 2599 "unknown NSEC3 hash algorithm found"); 2600 markanswer(val, "validate_nx (2)", NULL); 2601 return (ISC_R_SUCCESS); 2602 } 2603 2604 validator_log(val, ISC_LOG_DEBUG(3), "noqname proof not found"); 2605 return (DNS_R_NOVALIDNSEC); 2606 } 2607 2608 if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val)) { 2609 result = findnsec3proofs(val); 2610 if (result == DNS_R_NSEC3ITERRANGE) { 2611 validator_log(val, ISC_LOG_DEBUG(3), 2612 "too many iterations"); 2613 markanswer(val, "validate_nx (4)", NULL); 2614 return (ISC_R_SUCCESS); 2615 } 2616 } 2617 2618 /* 2619 * Do we need to check for the wildcard? 2620 */ 2621 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && 2622 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) 2623 { 2624 result = checkwildcard(val, dns_rdatatype_nsec, NULL); 2625 if (result != ISC_R_SUCCESS) { 2626 return (result); 2627 } 2628 } 2629 2630 if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) || 2631 (NEEDNOQNAME(val) && FOUNDNOQNAME(val) && NEEDNOWILDCARD(val) && 2632 FOUNDNOWILDCARD(val) && FOUNDCLOSEST(val))) 2633 { 2634 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0) { 2635 val->event->optout = true; 2636 } 2637 validator_log(val, ISC_LOG_DEBUG(3), 2638 "nonexistence proof(s) found"); 2639 if (val->event->message == NULL) { 2640 marksecure(val->event); 2641 } else { 2642 val->event->secure = true; 2643 } 2644 return (ISC_R_SUCCESS); 2645 } 2646 2647 if (val->authfail != 0 && val->authcount == val->authfail) { 2648 return (DNS_R_BROKENCHAIN); 2649 } 2650 2651 validator_log(val, ISC_LOG_DEBUG(3), "nonexistence proof(s) not found"); 2652 return (proveunsecure(val, false, false)); 2653 } 2654 2655 /*% 2656 * Check that DS rdataset has at least one record with 2657 * a supported algorithm and digest. 2658 */ 2659 static bool 2660 check_ds_algs(dns_validator_t *val, dns_name_t *name, 2661 dns_rdataset_t *rdataset) { 2662 dns_rdata_t dsrdata = DNS_RDATA_INIT; 2663 dns_rdata_ds_t ds; 2664 isc_result_t result; 2665 2666 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 2667 result = dns_rdataset_next(rdataset)) 2668 { 2669 dns_rdataset_current(rdataset, &dsrdata); 2670 result = dns_rdata_tostruct(&dsrdata, &ds, NULL); 2671 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2672 2673 if (dns_resolver_ds_digest_supported(val->view->resolver, name, 2674 ds.digest_type) && 2675 dns_resolver_algorithm_supported(val->view->resolver, name, 2676 ds.algorithm)) 2677 { 2678 dns_rdata_reset(&dsrdata); 2679 return (true); 2680 } 2681 dns_rdata_reset(&dsrdata); 2682 } 2683 return (false); 2684 } 2685 2686 /*% 2687 * seek_ds is called to look up DS rrsets at the label of val->event->name 2688 * indicated by val->labels. This is done while building an insecurity 2689 * proof, and so it will attempt validation of NXDOMAIN, NXRRSET or CNAME 2690 * responses. 2691 * 2692 * Returns: 2693 * \li ISC_R_COMPLETE a result has been determined and copied 2694 * into `*resp`; ISC_R_SUCCESS indicates that 2695 * the name has been proven insecure and any 2696 * other result indicates failure. 2697 * \li DNS_R_CONTINUE result is indeterminate; caller should 2698 * continue walking down labels. 2699 */ 2700 static isc_result_t 2701 seek_ds(dns_validator_t *val, isc_result_t *resp) { 2702 isc_result_t result; 2703 char namebuf[DNS_NAME_FORMATSIZE]; 2704 dns_fixedname_t fixedfound; 2705 dns_name_t *found = dns_fixedname_initname(&fixedfound); 2706 dns_name_t *tname = dns_fixedname_initname(&val->fname); 2707 2708 if (val->labels == dns_name_countlabels(val->event->name)) { 2709 dns_name_copy(val->event->name, tname); 2710 } else { 2711 dns_name_split(val->event->name, val->labels, NULL, tname); 2712 } 2713 2714 dns_name_format(tname, namebuf, sizeof(namebuf)); 2715 validator_log(val, ISC_LOG_DEBUG(3), "checking existence of DS at '%s'", 2716 namebuf); 2717 2718 result = view_find(val, tname, dns_rdatatype_ds); 2719 switch (result) { 2720 case ISC_R_SUCCESS: 2721 /* 2722 * There is a DS here. If it's already been 2723 * validated, continue walking down labels. 2724 */ 2725 if (val->frdataset.trust >= dns_trust_secure) { 2726 if (!check_ds_algs(val, tname, &val->frdataset)) { 2727 validator_log(val, ISC_LOG_DEBUG(3), 2728 "no supported algorithm/" 2729 "digest (%s/DS)", 2730 namebuf); 2731 *resp = markanswer(val, "proveunsecure (5)", 2732 "no supported " 2733 "algorithm/digest (DS)"); 2734 return (ISC_R_COMPLETE); 2735 } 2736 2737 break; 2738 } 2739 2740 /* 2741 * Otherwise, try to validate it now. 2742 */ 2743 if (dns_rdataset_isassociated(&val->fsigrdataset)) { 2744 result = create_validator( 2745 val, tname, dns_rdatatype_ds, &val->frdataset, 2746 &val->fsigrdataset, validator_callback_ds, 2747 "proveunsecure"); 2748 *resp = DNS_R_WAIT; 2749 if (result != ISC_R_SUCCESS) { 2750 *resp = result; 2751 } 2752 } else { 2753 /* 2754 * There should never be an unsigned DS. 2755 */ 2756 validator_log(val, ISC_LOG_DEBUG(3), 2757 "unsigned DS record"); 2758 *resp = DNS_R_NOVALIDSIG; 2759 } 2760 2761 return (ISC_R_COMPLETE); 2762 2763 case ISC_R_NOTFOUND: 2764 /* 2765 * We don't know anything about the DS. Find it. 2766 */ 2767 *resp = DNS_R_WAIT; 2768 result = create_fetch(val, tname, dns_rdatatype_ds, 2769 fetch_callback_ds, "proveunsecure"); 2770 if (result != ISC_R_SUCCESS) { 2771 *resp = result; 2772 } 2773 return (ISC_R_COMPLETE); 2774 2775 case DNS_R_NXRRSET: 2776 case DNS_R_NCACHENXRRSET: 2777 /* 2778 * There is no DS. If this is a delegation, 2779 * we may be done. 2780 * 2781 * If we have "trust == answer" then this namespace 2782 * has switched from insecure to should be secure. 2783 */ 2784 if (DNS_TRUST_PENDING(val->frdataset.trust) || 2785 DNS_TRUST_ANSWER(val->frdataset.trust)) 2786 { 2787 result = create_validator( 2788 val, tname, dns_rdatatype_ds, &val->frdataset, 2789 &val->fsigrdataset, validator_callback_ds, 2790 "proveunsecure"); 2791 *resp = DNS_R_WAIT; 2792 if (result != ISC_R_SUCCESS) { 2793 *resp = result; 2794 } 2795 return (ISC_R_COMPLETE); 2796 } 2797 2798 /* 2799 * Zones using NSEC3 don't return a NSEC RRset so 2800 * we need to use dns_view_findzonecut2 to find 2801 * the zone cut. 2802 */ 2803 if (result == DNS_R_NXRRSET && 2804 !dns_rdataset_isassociated(&val->frdataset) && 2805 dns_view_findzonecut(val->view, tname, found, NULL, 0, 0, 2806 false, false, NULL, 2807 NULL) == ISC_R_SUCCESS && 2808 dns_name_equal(tname, found)) 2809 { 2810 *resp = markanswer(val, "proveunsecure (3)", 2811 "no DS at zone cut"); 2812 return (ISC_R_COMPLETE); 2813 } 2814 2815 if (val->frdataset.trust < dns_trust_secure) { 2816 /* 2817 * This shouldn't happen, since the negative 2818 * response should have been validated. Since 2819 * there's no way of validating existing 2820 * negative response blobs, give up. 2821 */ 2822 validator_log(val, ISC_LOG_WARNING, 2823 "can't validate existing " 2824 "negative responses (no DS)"); 2825 *resp = DNS_R_MUSTBESECURE; 2826 return (ISC_R_COMPLETE); 2827 } 2828 2829 if (isdelegation(tname, &val->frdataset, result)) { 2830 *resp = markanswer(val, "proveunsecure (4)", 2831 "this is a delegation"); 2832 return (ISC_R_COMPLETE); 2833 } 2834 2835 break; 2836 2837 case DNS_R_NXDOMAIN: 2838 case DNS_R_NCACHENXDOMAIN: 2839 /* 2840 * This is not a zone cut. Assuming things are 2841 * as expected, continue. 2842 */ 2843 if (!dns_rdataset_isassociated(&val->frdataset)) { 2844 /* 2845 * There should be an NSEC here, since we 2846 * are still in a secure zone. 2847 */ 2848 *resp = DNS_R_NOVALIDNSEC; 2849 return (ISC_R_COMPLETE); 2850 } else if (DNS_TRUST_PENDING(val->frdataset.trust) || 2851 DNS_TRUST_ANSWER(val->frdataset.trust)) 2852 { 2853 /* 2854 * If we have "trust == answer" then this 2855 * namespace has switched from insecure to 2856 * should be secure. 2857 */ 2858 *resp = DNS_R_WAIT; 2859 result = create_validator( 2860 val, tname, dns_rdatatype_ds, &val->frdataset, 2861 &val->fsigrdataset, validator_callback_ds, 2862 "proveunsecure"); 2863 if (result != ISC_R_SUCCESS) { 2864 *resp = result; 2865 } 2866 return (ISC_R_COMPLETE); 2867 } else if (val->frdataset.trust < dns_trust_secure) { 2868 /* 2869 * This shouldn't happen, since the negative 2870 * response should have been validated. Since 2871 * there's no way of validating existing 2872 * negative response blobs, give up. 2873 */ 2874 validator_log(val, ISC_LOG_WARNING, 2875 "can't validate existing " 2876 "negative responses " 2877 "(not a zone cut)"); 2878 *resp = DNS_R_NOVALIDSIG; 2879 return (ISC_R_COMPLETE); 2880 } 2881 2882 break; 2883 2884 case DNS_R_CNAME: 2885 if (DNS_TRUST_PENDING(val->frdataset.trust) || 2886 DNS_TRUST_ANSWER(val->frdataset.trust)) 2887 { 2888 result = create_validator( 2889 val, tname, dns_rdatatype_cname, 2890 &val->frdataset, &val->fsigrdataset, 2891 validator_callback_cname, 2892 "proveunsecure " 2893 "(cname)"); 2894 *resp = DNS_R_WAIT; 2895 if (result != ISC_R_SUCCESS) { 2896 *resp = result; 2897 } 2898 return (ISC_R_COMPLETE); 2899 } 2900 2901 break; 2902 2903 default: 2904 *resp = result; 2905 return (ISC_R_COMPLETE); 2906 } 2907 2908 /* 2909 * No definite answer yet; continue walking down labels. 2910 */ 2911 return (DNS_R_CONTINUE); 2912 } 2913 2914 /*% 2915 * proveunsecure walks down, label by label, from the closest enclosing 2916 * trust anchor to the name that is being validated, looking for an 2917 * endpoint in the chain of trust. That occurs when we can prove that 2918 * a DS record does not exist at a delegation point, or that a DS exists 2919 * at a delegation point but we don't support its algorithm/digest. If 2920 * no such endpoint is found, then the response should have been secure. 2921 * 2922 * Returns: 2923 * \li ISC_R_SUCCESS val->event->name is in an unsecure zone 2924 * \li DNS_R_WAIT validation is in progress. 2925 * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure 2926 * (policy) but we proved that it is unsecure. 2927 * \li DNS_R_NOVALIDSIG 2928 * \li DNS_R_NOVALIDNSEC 2929 * \li DNS_R_NOTINSECURE 2930 * \li DNS_R_BROKENCHAIN 2931 */ 2932 static isc_result_t 2933 proveunsecure(dns_validator_t *val, bool have_ds, bool resume) { 2934 isc_result_t result; 2935 char namebuf[DNS_NAME_FORMATSIZE]; 2936 dns_fixedname_t fixedsecroot; 2937 dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot); 2938 unsigned int labels; 2939 2940 /* 2941 * We're attempting to prove insecurity. 2942 */ 2943 val->attributes |= VALATTR_INSECURITY; 2944 2945 dns_name_copy(val->event->name, secroot); 2946 2947 /* 2948 * If this is a response to a DS query, we need to look in 2949 * the parent zone for the trust anchor. 2950 */ 2951 labels = dns_name_countlabels(secroot); 2952 if (val->event->type == dns_rdatatype_ds && labels > 1U) { 2953 dns_name_getlabelsequence(secroot, 1, labels - 1, secroot); 2954 } 2955 2956 result = dns_keytable_finddeepestmatch(val->keytable, secroot, secroot); 2957 if (result == ISC_R_NOTFOUND) { 2958 validator_log(val, ISC_LOG_DEBUG(3), "not beneath secure root"); 2959 return (markanswer(val, "proveunsecure (1)", 2960 "not beneath secure root")); 2961 } else if (result != ISC_R_SUCCESS) { 2962 return (result); 2963 } 2964 2965 if (!resume) { 2966 /* 2967 * We are looking for interruptions in the chain of trust. 2968 * That can only happen *below* the trust anchor, so we 2969 * start looking at the next label down. 2970 */ 2971 val->labels = dns_name_countlabels(secroot) + 1; 2972 } else { 2973 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure"); 2974 2975 /* 2976 * If we have a DS rdataset and it is secure, check whether 2977 * it has a supported algorithm combination. If not, this is 2978 * an insecure delegation as far as this resolver is concerned. 2979 */ 2980 if (have_ds && val->frdataset.trust >= dns_trust_secure && 2981 !check_ds_algs(val, dns_fixedname_name(&val->fname), 2982 &val->frdataset)) 2983 { 2984 dns_name_format(dns_fixedname_name(&val->fname), 2985 namebuf, sizeof(namebuf)); 2986 validator_log(val, ISC_LOG_DEBUG(3), 2987 "no supported algorithm/digest (%s/DS)", 2988 namebuf); 2989 result = markanswer(val, "proveunsecure (2)", namebuf); 2990 goto out; 2991 } 2992 val->labels++; 2993 } 2994 2995 /* 2996 * Walk down through each of the remaining labels in the name, 2997 * looking for DS records. 2998 */ 2999 while (val->labels <= dns_name_countlabels(val->event->name)) { 3000 isc_result_t tresult; 3001 3002 result = seek_ds(val, &tresult); 3003 if (result == ISC_R_COMPLETE) { 3004 result = tresult; 3005 goto out; 3006 } 3007 3008 INSIST(result == DNS_R_CONTINUE); 3009 val->labels++; 3010 } 3011 3012 /* Couldn't complete insecurity proof. */ 3013 validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed: %s", 3014 isc_result_totext(result)); 3015 return (DNS_R_NOTINSECURE); 3016 3017 out: 3018 if (result != DNS_R_WAIT) { 3019 disassociate_rdatasets(val); 3020 } 3021 return (result); 3022 } 3023 3024 /*% 3025 * Start the validation process. 3026 * 3027 * Attempt to validate the answer based on the category it appears to 3028 * fall in. 3029 * \li 1. secure positive answer. 3030 * \li 2. unsecure positive answer. 3031 * \li 3. a negative answer (secure or unsecure). 3032 * 3033 * Note an answer that appears to be a secure positive answer may actually 3034 * be an unsecure positive answer. 3035 */ 3036 static void 3037 validator_start(isc_task_t *task, isc_event_t *event) { 3038 dns_validator_t *val; 3039 dns_validatorevent_t *vevent; 3040 bool want_destroy = false; 3041 isc_result_t result = ISC_R_FAILURE; 3042 3043 UNUSED(task); 3044 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART); 3045 vevent = (dns_validatorevent_t *)event; 3046 val = vevent->validator; 3047 3048 /* If the validator has been canceled, val->event == NULL */ 3049 if (val->event == NULL) { 3050 return; 3051 } 3052 3053 validator_log(val, ISC_LOG_DEBUG(3), "starting"); 3054 3055 LOCK(&val->lock); 3056 3057 if (val->event->rdataset != NULL && val->event->sigrdataset != NULL) { 3058 isc_result_t saved_result; 3059 3060 /* 3061 * This looks like a simple validation. We say "looks like" 3062 * because it might end up requiring an insecurity proof. 3063 */ 3064 validator_log(val, ISC_LOG_DEBUG(3), 3065 "attempting positive response validation"); 3066 3067 INSIST(dns_rdataset_isassociated(val->event->rdataset)); 3068 INSIST(dns_rdataset_isassociated(val->event->sigrdataset)); 3069 if (selfsigned_dnskey(val)) { 3070 result = validate_dnskey(val); 3071 } else { 3072 result = validate_answer(val, false); 3073 } 3074 if (result == DNS_R_NOVALIDSIG && 3075 (val->attributes & VALATTR_TRIEDVERIFY) == 0) 3076 { 3077 saved_result = result; 3078 validator_log(val, ISC_LOG_DEBUG(3), 3079 "falling back to insecurity proof"); 3080 result = proveunsecure(val, false, false); 3081 if (result == DNS_R_NOTINSECURE) { 3082 result = saved_result; 3083 } 3084 } 3085 } else if (val->event->rdataset != NULL && 3086 val->event->rdataset->type != 0) 3087 { 3088 /* 3089 * This is either an unsecure subdomain or a response 3090 * from a broken server. 3091 */ 3092 INSIST(dns_rdataset_isassociated(val->event->rdataset)); 3093 validator_log(val, ISC_LOG_DEBUG(3), 3094 "attempting insecurity proof"); 3095 3096 result = proveunsecure(val, false, false); 3097 if (result == DNS_R_NOTINSECURE) { 3098 validator_log(val, ISC_LOG_INFO, 3099 "got insecure response; " 3100 "parent indicates it should be secure"); 3101 } 3102 } else if ((val->event->rdataset == NULL && 3103 val->event->sigrdataset == NULL)) 3104 { 3105 /* 3106 * This is a validation of a negative response. 3107 */ 3108 validator_log(val, ISC_LOG_DEBUG(3), 3109 "attempting negative response validation " 3110 "from message"); 3111 3112 if (val->event->message->rcode == dns_rcode_nxdomain) { 3113 val->attributes |= VALATTR_NEEDNOQNAME; 3114 val->attributes |= VALATTR_NEEDNOWILDCARD; 3115 } else { 3116 val->attributes |= VALATTR_NEEDNODATA; 3117 } 3118 3119 result = validate_nx(val, false); 3120 } else if ((val->event->rdataset != NULL && 3121 NEGATIVE(val->event->rdataset))) 3122 { 3123 /* 3124 * This is a delayed validation of a negative cache entry. 3125 */ 3126 validator_log(val, ISC_LOG_DEBUG(3), 3127 "attempting negative response validation " 3128 "from cache"); 3129 3130 if (NXDOMAIN(val->event->rdataset)) { 3131 val->attributes |= VALATTR_NEEDNOQNAME; 3132 val->attributes |= VALATTR_NEEDNOWILDCARD; 3133 } else { 3134 val->attributes |= VALATTR_NEEDNODATA; 3135 } 3136 3137 result = validate_nx(val, false); 3138 } else { 3139 UNREACHABLE(); 3140 } 3141 3142 if (result != DNS_R_WAIT) { 3143 want_destroy = exit_check(val); 3144 validator_done(val, result); 3145 } 3146 3147 UNLOCK(&val->lock); 3148 if (want_destroy) { 3149 destroy(val); 3150 } 3151 } 3152 3153 isc_result_t 3154 dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 3155 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 3156 dns_message_t *message, unsigned int options, 3157 isc_task_t *task, isc_taskaction_t action, void *arg, 3158 isc_counter_t *qc, dns_validator_t **validatorp) { 3159 isc_result_t result = ISC_R_FAILURE; 3160 dns_validator_t *val; 3161 isc_task_t *tclone = NULL; 3162 dns_validatorevent_t *event; 3163 3164 REQUIRE(name != NULL); 3165 REQUIRE(rdataset != NULL || 3166 (rdataset == NULL && sigrdataset == NULL && message != NULL)); 3167 REQUIRE(validatorp != NULL && *validatorp == NULL); 3168 3169 event = (dns_validatorevent_t *)isc_event_allocate( 3170 view->mctx, task, DNS_EVENT_VALIDATORSTART, validator_start, 3171 NULL, sizeof(dns_validatorevent_t)); 3172 3173 isc_task_attach(task, &tclone); 3174 event->result = ISC_R_FAILURE; 3175 event->name = name; 3176 event->type = type; 3177 event->rdataset = rdataset; 3178 event->sigrdataset = sigrdataset; 3179 event->message = message; 3180 memset(event->proofs, 0, sizeof(event->proofs)); 3181 event->optout = false; 3182 event->secure = false; 3183 3184 val = isc_mem_get(view->mctx, sizeof(*val)); 3185 *val = (dns_validator_t){ .event = event, 3186 .options = options, 3187 .task = task, 3188 .action = action, 3189 .arg = arg }; 3190 3191 dns_view_weakattach(view, &val->view); 3192 isc_mutex_init(&val->lock); 3193 3194 result = dns_view_getsecroots(val->view, &val->keytable); 3195 if (result != ISC_R_SUCCESS) { 3196 goto cleanup; 3197 } 3198 3199 if (qc != NULL) { 3200 isc_counter_attach(qc, &val->qc); 3201 } 3202 3203 val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name); 3204 dns_rdataset_init(&val->fdsset); 3205 dns_rdataset_init(&val->frdataset); 3206 dns_rdataset_init(&val->fsigrdataset); 3207 dns_fixedname_init(&val->wild); 3208 dns_fixedname_init(&val->closest); 3209 isc_stdtime_get(&val->start); 3210 ISC_LINK_INIT(val, link); 3211 val->magic = VALIDATOR_MAGIC; 3212 3213 event->validator = val; 3214 3215 if ((options & DNS_VALIDATOR_DEFER) == 0) { 3216 isc_task_send(task, ISC_EVENT_PTR(&event)); 3217 } 3218 3219 *validatorp = val; 3220 3221 return (ISC_R_SUCCESS); 3222 3223 cleanup: 3224 isc_mutex_destroy(&val->lock); 3225 3226 isc_task_detach(&tclone); 3227 isc_event_free(ISC_EVENT_PTR(&event)); 3228 3229 dns_view_weakdetach(&val->view); 3230 isc_mem_put(view->mctx, val, sizeof(*val)); 3231 3232 return (result); 3233 } 3234 3235 void 3236 dns_validator_send(dns_validator_t *validator) { 3237 isc_event_t *event; 3238 REQUIRE(VALID_VALIDATOR(validator)); 3239 3240 LOCK(&validator->lock); 3241 3242 INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0); 3243 event = (isc_event_t *)validator->event; 3244 validator->options &= ~DNS_VALIDATOR_DEFER; 3245 UNLOCK(&validator->lock); 3246 3247 isc_task_send(validator->task, ISC_EVENT_PTR(&event)); 3248 } 3249 3250 void 3251 dns_validator_cancel(dns_validator_t *validator) { 3252 dns_fetch_t *fetch = NULL; 3253 3254 REQUIRE(VALID_VALIDATOR(validator)); 3255 3256 LOCK(&validator->lock); 3257 3258 validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel"); 3259 3260 if ((validator->attributes & VALATTR_CANCELED) == 0) { 3261 validator->attributes |= VALATTR_CANCELED; 3262 if (validator->event != NULL) { 3263 fetch = validator->fetch; 3264 validator->fetch = NULL; 3265 3266 if (validator->subvalidator != NULL) { 3267 dns_validator_cancel(validator->subvalidator); 3268 } 3269 if ((validator->options & DNS_VALIDATOR_DEFER) != 0) { 3270 validator->options &= ~DNS_VALIDATOR_DEFER; 3271 validator_done(validator, ISC_R_CANCELED); 3272 } 3273 } 3274 } 3275 UNLOCK(&validator->lock); 3276 3277 /* Need to cancel and destroy the fetch outside validator lock */ 3278 if (fetch != NULL) { 3279 dns_resolver_cancelfetch(fetch); 3280 dns_resolver_destroyfetch(&fetch); 3281 } 3282 } 3283 3284 static void 3285 destroy(dns_validator_t *val) { 3286 isc_mem_t *mctx; 3287 3288 REQUIRE(SHUTDOWN(val)); 3289 REQUIRE(val->event == NULL); 3290 REQUIRE(val->fetch == NULL); 3291 3292 val->magic = 0; 3293 if (val->key != NULL) { 3294 dst_key_free(&val->key); 3295 } 3296 if (val->keytable != NULL) { 3297 dns_keytable_detach(&val->keytable); 3298 } 3299 if (val->subvalidator != NULL) { 3300 dns_validator_destroy(&val->subvalidator); 3301 } 3302 disassociate_rdatasets(val); 3303 mctx = val->view->mctx; 3304 if (val->siginfo != NULL) { 3305 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo)); 3306 } 3307 if (val->qc != NULL) { 3308 isc_counter_detach(&val->qc); 3309 } 3310 isc_mutex_destroy(&val->lock); 3311 dns_view_weakdetach(&val->view); 3312 isc_mem_put(mctx, val, sizeof(*val)); 3313 } 3314 3315 void 3316 dns_validator_destroy(dns_validator_t **validatorp) { 3317 dns_validator_t *val; 3318 bool want_destroy = false; 3319 3320 REQUIRE(validatorp != NULL); 3321 val = *validatorp; 3322 *validatorp = NULL; 3323 REQUIRE(VALID_VALIDATOR(val)); 3324 3325 LOCK(&val->lock); 3326 3327 val->attributes |= VALATTR_SHUTDOWN; 3328 validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_destroy"); 3329 3330 want_destroy = exit_check(val); 3331 UNLOCK(&val->lock); 3332 if (want_destroy) { 3333 destroy(val); 3334 } 3335 } 3336 3337 static void 3338 validator_logv(dns_validator_t *val, isc_logcategory_t *category, 3339 isc_logmodule_t *module, int level, const char *fmt, 3340 va_list ap) { 3341 char msgbuf[2048]; 3342 static const char spaces[] = " *"; 3343 int depth = val->depth * 2; 3344 const char *viewname, *sep1, *sep2; 3345 3346 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 3347 3348 if ((unsigned int)depth >= sizeof spaces) { 3349 depth = sizeof spaces - 1; 3350 } 3351 3352 /* 3353 * Log the view name unless it's: 3354 * * "_default/IN" (which means there's only one view 3355 * configured in the server), or 3356 * * "_dnsclient/IN" (which means this is being called 3357 * from an application using dns/client.c). 3358 */ 3359 if (val->view->rdclass == dns_rdataclass_in && 3360 (strcmp(val->view->name, "_default") == 0 || 3361 strcmp(val->view->name, DNS_CLIENTVIEW_NAME) == 0)) 3362 { 3363 sep1 = viewname = sep2 = ""; 3364 } else { 3365 sep1 = "view "; 3366 viewname = val->view->name; 3367 sep2 = ": "; 3368 } 3369 3370 if (val->event != NULL && val->event->name != NULL) { 3371 char namebuf[DNS_NAME_FORMATSIZE]; 3372 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3373 3374 dns_name_format(val->event->name, namebuf, sizeof(namebuf)); 3375 dns_rdatatype_format(val->event->type, typebuf, 3376 sizeof(typebuf)); 3377 isc_log_write(dns_lctx, category, module, level, 3378 "%s%s%s%.*svalidating %s/%s: %s", sep1, viewname, 3379 sep2, depth, spaces, namebuf, typebuf, msgbuf); 3380 } else { 3381 isc_log_write(dns_lctx, category, module, level, 3382 "%s%s%s%.*svalidator @%p: %s", sep1, viewname, 3383 sep2, depth, spaces, val, msgbuf); 3384 } 3385 } 3386 3387 static void 3388 validator_log(void *val, int level, const char *fmt, ...) { 3389 va_list ap; 3390 3391 if (!isc_log_wouldlog(dns_lctx, level)) { 3392 return; 3393 } 3394 3395 va_start(ap, fmt); 3396 3397 validator_logv(val, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_VALIDATOR, 3398 level, fmt, ap); 3399 va_end(ap); 3400 } 3401 3402 static void 3403 validator_logcreate(dns_validator_t *val, dns_name_t *name, 3404 dns_rdatatype_t type, const char *caller, 3405 const char *operation) { 3406 char namestr[DNS_NAME_FORMATSIZE]; 3407 char typestr[DNS_RDATATYPE_FORMATSIZE]; 3408 3409 dns_name_format(name, namestr, sizeof(namestr)); 3410 dns_rdatatype_format(type, typestr, sizeof(typestr)); 3411 validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s", 3412 caller, operation, namestr, typestr); 3413 } 3414