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