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