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