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