validator.c revision 1.9
1/* $NetBSD: validator.c,v 1.9 2021/02/19 16:42:16 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 != ISC_R_SUCCESS) { 2251 continue; 2252 } 2253 if (setclosest) { 2254 proofs[DNS_VALIDATOR_CLOSESTENCLOSER] = name; 2255 } 2256 if (exists && !data && NEEDNODATA(val)) { 2257 val->attributes |= VALATTR_FOUNDNODATA; 2258 proofs[DNS_VALIDATOR_NODATAPROOF] = name; 2259 } 2260 if (!exists && setnearest) { 2261 val->attributes |= VALATTR_FOUNDNOQNAME; 2262 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = name; 2263 if (optout) { 2264 val->attributes |= VALATTR_FOUNDOPTOUT; 2265 } 2266 } 2267 } 2268 if (result == ISC_R_NOMORE) { 2269 result = ISC_R_SUCCESS; 2270 } 2271 2272 /* 2273 * To know we have a valid noqname and optout proofs we need to also 2274 * have a valid closest encloser. Otherwise we could still be looking 2275 * at proofs from the parent zone. 2276 */ 2277 if (dns_name_countlabels(closest) > 0 && 2278 dns_name_countlabels(nearest) == 2279 dns_name_countlabels(closest) + 1 && 2280 dns_name_issubdomain(nearest, closest)) 2281 { 2282 val->attributes |= VALATTR_FOUNDCLOSEST; 2283 result = dns_name_concatenate(dns_wildcardname, closest, 2284 dns_fixedname_name(&val->wild), 2285 NULL); 2286 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2287 } else { 2288 val->attributes &= ~VALATTR_FOUNDNOQNAME; 2289 val->attributes &= ~VALATTR_FOUNDOPTOUT; 2290 proofs[DNS_VALIDATOR_NOQNAMEPROOF] = NULL; 2291 } 2292 2293 /* 2294 * Do we need to check for the wildcard? 2295 */ 2296 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && 2297 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) 2298 { 2299 result = checkwildcard(val, dns_rdatatype_nsec3, zonename); 2300 if (result != ISC_R_SUCCESS) { 2301 return (result); 2302 } 2303 } 2304 return (result); 2305} 2306 2307/* 2308 * Start a validator for negative response data. 2309 * 2310 * Returns: 2311 * \li DNS_R_CONTINUE Validation skipped, continue 2312 * \li DNS_R_WAIT Validation is in progress 2313 * 2314 * \li Other return codes indicate failure. 2315 */ 2316static isc_result_t 2317validate_neg_rrset(dns_validator_t *val, dns_name_t *name, 2318 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) { 2319 isc_result_t result; 2320 2321 /* 2322 * If a signed zone is missing the zone key, bad 2323 * things could happen. A query for data in the zone 2324 * would lead to a query for the zone key, which 2325 * would return a negative answer, which would contain 2326 * an SOA and an NSEC signed by the missing key, which 2327 * would trigger another query for the DNSKEY (since 2328 * the first one is still in progress), and go into an 2329 * infinite loop. Avoid that. 2330 */ 2331 if (val->event->type == dns_rdatatype_dnskey && 2332 rdataset->type == dns_rdatatype_nsec && 2333 dns_name_equal(name, val->event->name)) 2334 { 2335 dns_rdata_t nsec = DNS_RDATA_INIT; 2336 2337 result = dns_rdataset_first(rdataset); 2338 if (result != ISC_R_SUCCESS) { 2339 return (result); 2340 } 2341 dns_rdataset_current(rdataset, &nsec); 2342 if (dns_nsec_typepresent(&nsec, dns_rdatatype_soa)) { 2343 return (DNS_R_CONTINUE); 2344 } 2345 } 2346 2347 val->currentset = rdataset; 2348 result = create_validator(val, name, rdataset->type, rdataset, 2349 sigrdataset, validator_callback_nsec, 2350 "validate_neg_rrset"); 2351 if (result != ISC_R_SUCCESS) { 2352 return (result); 2353 } 2354 2355 val->authcount++; 2356 return (DNS_R_WAIT); 2357} 2358 2359/*% 2360 * Validate the authority section records. 2361 */ 2362static isc_result_t 2363validate_authority(dns_validator_t *val, bool resume) { 2364 dns_name_t *name; 2365 dns_message_t *message = val->event->message; 2366 isc_result_t result; 2367 2368 if (!resume) { 2369 result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); 2370 } else { 2371 result = ISC_R_SUCCESS; 2372 } 2373 2374 for (; result == ISC_R_SUCCESS; 2375 result = dns_message_nextname(message, DNS_SECTION_AUTHORITY)) 2376 { 2377 dns_rdataset_t *rdataset = NULL, *sigrdataset = NULL; 2378 2379 name = NULL; 2380 dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name); 2381 if (resume) { 2382 rdataset = ISC_LIST_NEXT(val->currentset, link); 2383 val->currentset = NULL; 2384 resume = false; 2385 } else { 2386 rdataset = ISC_LIST_HEAD(name->list); 2387 } 2388 2389 for (; rdataset != NULL; 2390 rdataset = ISC_LIST_NEXT(rdataset, link)) { 2391 if (rdataset->type == dns_rdatatype_rrsig) { 2392 continue; 2393 } 2394 2395 for (sigrdataset = ISC_LIST_HEAD(name->list); 2396 sigrdataset != NULL; 2397 sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) 2398 { 2399 if (sigrdataset->type == dns_rdatatype_rrsig && 2400 sigrdataset->covers == rdataset->type) 2401 { 2402 break; 2403 } 2404 } 2405 2406 result = validate_neg_rrset(val, name, rdataset, 2407 sigrdataset); 2408 if (result != DNS_R_CONTINUE) { 2409 return (result); 2410 } 2411 } 2412 } 2413 if (result == ISC_R_NOMORE) { 2414 result = ISC_R_SUCCESS; 2415 } 2416 return (result); 2417} 2418 2419/*% 2420 * Validate negative cache elements. 2421 */ 2422static isc_result_t 2423validate_ncache(dns_validator_t *val, bool resume) { 2424 dns_name_t *name; 2425 isc_result_t result; 2426 2427 if (!resume) { 2428 result = dns_rdataset_first(val->event->rdataset); 2429 } else { 2430 result = dns_rdataset_next(val->event->rdataset); 2431 } 2432 2433 for (; result == ISC_R_SUCCESS; 2434 result = dns_rdataset_next(val->event->rdataset)) 2435 { 2436 dns_rdataset_t *rdataset, *sigrdataset = NULL; 2437 2438 disassociate_rdatasets(val); 2439 2440 name = dns_fixedname_initname(&val->fname); 2441 rdataset = &val->frdataset; 2442 dns_ncache_current(val->event->rdataset, name, rdataset); 2443 2444 if (val->frdataset.type == dns_rdatatype_rrsig) { 2445 continue; 2446 } 2447 2448 result = dns_ncache_getsigrdataset(val->event->rdataset, name, 2449 rdataset->type, 2450 &val->fsigrdataset); 2451 if (result == ISC_R_SUCCESS) { 2452 sigrdataset = &val->fsigrdataset; 2453 } 2454 2455 result = validate_neg_rrset(val, name, rdataset, sigrdataset); 2456 if (result == DNS_R_CONTINUE) { 2457 continue; 2458 } 2459 2460 return (result); 2461 } 2462 if (result == ISC_R_NOMORE) { 2463 result = ISC_R_SUCCESS; 2464 } 2465 2466 return (result); 2467} 2468 2469/*% 2470 * Prove a negative answer is good or that there is a NOQNAME when the 2471 * answer is from a wildcard. 2472 * 2473 * Loop through the authority section looking for NODATA, NOWILDCARD 2474 * and NOQNAME proofs in the NSEC records by calling 2475 * validator_callback_nsec(). 2476 * 2477 * If the required proofs are found we are done. 2478 * 2479 * If the proofs are not found attempt to prove this is an unsecure 2480 * response. 2481 */ 2482static isc_result_t 2483validate_nx(dns_validator_t *val, bool resume) { 2484 isc_result_t result; 2485 2486 if (resume) { 2487 validator_log(val, ISC_LOG_DEBUG(3), "resuming validate_nx"); 2488 } 2489 2490 if (val->event->message == NULL) { 2491 result = validate_ncache(val, resume); 2492 } else { 2493 result = validate_authority(val, resume); 2494 } 2495 2496 if (result != ISC_R_SUCCESS) { 2497 return (result); 2498 } 2499 2500 /* 2501 * Do we only need to check for NOQNAME? To get here we must have 2502 * had a secure wildcard answer. 2503 */ 2504 if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) { 2505 if (!FOUNDNOQNAME(val)) { 2506 findnsec3proofs(val); 2507 } 2508 2509 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && !FOUNDOPTOUT(val)) 2510 { 2511 validator_log(val, ISC_LOG_DEBUG(3), 2512 "marking as secure, noqname proof found"); 2513 marksecure(val->event); 2514 return (ISC_R_SUCCESS); 2515 } else if (FOUNDOPTOUT(val) && 2516 dns_name_countlabels( 2517 dns_fixedname_name(&val->wild)) != 0) 2518 { 2519 validator_log(val, ISC_LOG_DEBUG(3), 2520 "optout proof found"); 2521 val->event->optout = true; 2522 markanswer(val, "validate_nx (1)", NULL); 2523 return (ISC_R_SUCCESS); 2524 } else if ((val->attributes & VALATTR_FOUNDUNKNOWN) != 0) { 2525 validator_log(val, ISC_LOG_DEBUG(3), 2526 "unknown NSEC3 hash algorithm found"); 2527 markanswer(val, "validate_nx (2)", NULL); 2528 return (ISC_R_SUCCESS); 2529 } 2530 2531 validator_log(val, ISC_LOG_DEBUG(3), "noqname proof not found"); 2532 return (DNS_R_NOVALIDNSEC); 2533 } 2534 2535 if (!FOUNDNOQNAME(val) && !FOUNDNODATA(val)) { 2536 findnsec3proofs(val); 2537 } 2538 2539 /* 2540 * Do we need to check for the wildcard? 2541 */ 2542 if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && 2543 ((NEEDNODATA(val) && !FOUNDNODATA(val)) || NEEDNOWILDCARD(val))) 2544 { 2545 result = checkwildcard(val, dns_rdatatype_nsec, NULL); 2546 if (result != ISC_R_SUCCESS) { 2547 return (result); 2548 } 2549 } 2550 2551 if ((NEEDNODATA(val) && (FOUNDNODATA(val) || FOUNDOPTOUT(val))) || 2552 (NEEDNOQNAME(val) && FOUNDNOQNAME(val) && NEEDNOWILDCARD(val) && 2553 FOUNDNOWILDCARD(val) && FOUNDCLOSEST(val))) 2554 { 2555 if ((val->attributes & VALATTR_FOUNDOPTOUT) != 0) { 2556 val->event->optout = true; 2557 } 2558 validator_log(val, ISC_LOG_DEBUG(3), 2559 "nonexistence proof(s) found"); 2560 if (val->event->message == NULL) { 2561 marksecure(val->event); 2562 } else { 2563 val->event->secure = true; 2564 } 2565 return (ISC_R_SUCCESS); 2566 } 2567 2568 if (val->authfail != 0 && val->authcount == val->authfail) { 2569 return (DNS_R_BROKENCHAIN); 2570 } 2571 2572 validator_log(val, ISC_LOG_DEBUG(3), "nonexistence proof(s) not found"); 2573 return (proveunsecure(val, false, false)); 2574} 2575 2576/*% 2577 * Check that DS rdataset has at least one record with 2578 * a supported algorithm and digest. 2579 */ 2580static bool 2581check_ds_algs(dns_validator_t *val, dns_name_t *name, 2582 dns_rdataset_t *rdataset) { 2583 dns_rdata_t dsrdata = DNS_RDATA_INIT; 2584 dns_rdata_ds_t ds; 2585 isc_result_t result; 2586 2587 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; 2588 result = dns_rdataset_next(rdataset)) 2589 { 2590 dns_rdataset_current(rdataset, &dsrdata); 2591 result = dns_rdata_tostruct(&dsrdata, &ds, NULL); 2592 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2593 2594 if (dns_resolver_ds_digest_supported(val->view->resolver, name, 2595 ds.digest_type) && 2596 dns_resolver_algorithm_supported(val->view->resolver, name, 2597 ds.algorithm)) 2598 { 2599 dns_rdata_reset(&dsrdata); 2600 return (true); 2601 } 2602 dns_rdata_reset(&dsrdata); 2603 } 2604 return (false); 2605} 2606 2607/*% 2608 * seek_ds is called to look up DS rrsets at the label of val->event->name 2609 * indicated by val->labels. This is done while building an insecurity 2610 * proof, and so it will attempt validation of NXDOMAIN, NXRRSET or CNAME 2611 * responses. 2612 * 2613 * Returns: 2614 * \li ISC_R_COMPLETE a result has been determined and copied 2615 * into `*resp`; ISC_R_SUCCESS indicates that 2616 * the name has been proven insecure and any 2617 * other result indicates failure. 2618 * \li DNS_R_CONTINUE result is indeterminate; caller should 2619 * continue walking down labels. 2620 */ 2621static isc_result_t 2622seek_ds(dns_validator_t *val, isc_result_t *resp) { 2623 isc_result_t result; 2624 char namebuf[DNS_NAME_FORMATSIZE]; 2625 dns_fixedname_t fixedfound; 2626 dns_name_t *found = dns_fixedname_initname(&fixedfound); 2627 dns_name_t *tname = dns_fixedname_initname(&val->fname); 2628 2629 if (val->labels == dns_name_countlabels(val->event->name)) { 2630 dns_name_copynf(val->event->name, tname); 2631 } else { 2632 dns_name_split(val->event->name, val->labels, NULL, tname); 2633 } 2634 2635 dns_name_format(tname, namebuf, sizeof(namebuf)); 2636 validator_log(val, ISC_LOG_DEBUG(3), "checking existence of DS at '%s'", 2637 namebuf); 2638 2639 result = view_find(val, tname, dns_rdatatype_ds); 2640 switch (result) { 2641 case ISC_R_SUCCESS: 2642 /* 2643 * There is a DS here. If it's already been 2644 * validated, continue walking down labels. 2645 */ 2646 if (val->frdataset.trust >= dns_trust_secure) { 2647 if (!check_ds_algs(val, tname, &val->frdataset)) { 2648 validator_log(val, ISC_LOG_DEBUG(3), 2649 "no supported algorithm/" 2650 "digest (%s/DS)", 2651 namebuf); 2652 *resp = markanswer(val, "proveunsecure (5)", 2653 "no supported " 2654 "algorithm/digest (DS)"); 2655 return (ISC_R_COMPLETE); 2656 } 2657 2658 break; 2659 } 2660 2661 /* 2662 * Otherwise, try to validate it now. 2663 */ 2664 if (dns_rdataset_isassociated(&val->fsigrdataset)) { 2665 result = create_validator( 2666 val, tname, dns_rdatatype_ds, &val->frdataset, 2667 &val->fsigrdataset, validator_callback_ds, 2668 "proveunsecure"); 2669 *resp = DNS_R_WAIT; 2670 if (result != ISC_R_SUCCESS) { 2671 *resp = result; 2672 } 2673 } else { 2674 /* 2675 * There should never be an unsigned DS. 2676 */ 2677 validator_log(val, ISC_LOG_DEBUG(3), 2678 "unsigned DS record"); 2679 *resp = DNS_R_NOVALIDSIG; 2680 } 2681 2682 return (ISC_R_COMPLETE); 2683 2684 case ISC_R_NOTFOUND: 2685 /* 2686 * We don't know anything about the DS. Find it. 2687 */ 2688 *resp = DNS_R_WAIT; 2689 result = create_fetch(val, tname, dns_rdatatype_ds, 2690 fetch_callback_ds, "proveunsecure"); 2691 if (result != ISC_R_SUCCESS) { 2692 *resp = result; 2693 } 2694 return (ISC_R_COMPLETE); 2695 2696 case DNS_R_NXRRSET: 2697 case DNS_R_NCACHENXRRSET: 2698 /* 2699 * There is no DS. If this is a delegation, 2700 * we may be done. 2701 * 2702 * If we have "trust == answer" then this namespace 2703 * has switched from insecure to should be secure. 2704 */ 2705 if (DNS_TRUST_PENDING(val->frdataset.trust) || 2706 DNS_TRUST_ANSWER(val->frdataset.trust)) 2707 { 2708 result = create_validator( 2709 val, tname, dns_rdatatype_ds, &val->frdataset, 2710 &val->fsigrdataset, validator_callback_ds, 2711 "proveunsecure"); 2712 *resp = DNS_R_WAIT; 2713 if (result != ISC_R_SUCCESS) { 2714 *resp = result; 2715 } 2716 return (ISC_R_COMPLETE); 2717 } 2718 2719 /* 2720 * Zones using NSEC3 don't return a NSEC RRset so 2721 * we need to use dns_view_findzonecut2 to find 2722 * the zone cut. 2723 */ 2724 if (result == DNS_R_NXRRSET && 2725 !dns_rdataset_isassociated(&val->frdataset) && 2726 dns_view_findzonecut(val->view, tname, found, NULL, 0, 0, 2727 false, false, NULL, 2728 NULL) == ISC_R_SUCCESS && 2729 dns_name_equal(tname, found)) 2730 { 2731 *resp = markanswer(val, "proveunsecure (3)", 2732 "no DS at zone cut"); 2733 return (ISC_R_COMPLETE); 2734 } 2735 2736 if (val->frdataset.trust < dns_trust_secure) { 2737 /* 2738 * This shouldn't happen, since the negative 2739 * response should have been validated. Since 2740 * there's no way of validating existing 2741 * negative response blobs, give up. 2742 */ 2743 validator_log(val, ISC_LOG_WARNING, 2744 "can't validate existing " 2745 "negative responses (no DS)"); 2746 *resp = DNS_R_MUSTBESECURE; 2747 return (ISC_R_COMPLETE); 2748 } 2749 2750 if (isdelegation(tname, &val->frdataset, result)) { 2751 *resp = markanswer(val, "proveunsecure (4)", 2752 "this is a delegation"); 2753 return (ISC_R_COMPLETE); 2754 } 2755 2756 break; 2757 2758 case DNS_R_NXDOMAIN: 2759 case DNS_R_NCACHENXDOMAIN: 2760 /* 2761 * This is not a zone cut. Assuming things are 2762 * as expected, continue. 2763 */ 2764 if (!dns_rdataset_isassociated(&val->frdataset)) { 2765 /* 2766 * There should be an NSEC here, since we 2767 * are still in a secure zone. 2768 */ 2769 *resp = DNS_R_NOVALIDNSEC; 2770 return (ISC_R_COMPLETE); 2771 } else if (DNS_TRUST_PENDING(val->frdataset.trust) || 2772 DNS_TRUST_ANSWER(val->frdataset.trust)) 2773 { 2774 /* 2775 * If we have "trust == answer" then this 2776 * namespace has switched from insecure to 2777 * should be secure. 2778 */ 2779 *resp = DNS_R_WAIT; 2780 result = create_validator( 2781 val, tname, dns_rdatatype_ds, &val->frdataset, 2782 &val->fsigrdataset, validator_callback_ds, 2783 "proveunsecure"); 2784 if (result != ISC_R_SUCCESS) { 2785 *resp = result; 2786 } 2787 return (ISC_R_COMPLETE); 2788 } else if (val->frdataset.trust < dns_trust_secure) { 2789 /* 2790 * This shouldn't happen, since the negative 2791 * response should have been validated. Since 2792 * there's no way of validating existing 2793 * negative response blobs, give up. 2794 */ 2795 validator_log(val, ISC_LOG_WARNING, 2796 "can't validate existing " 2797 "negative responses " 2798 "(not a zone cut)"); 2799 *resp = DNS_R_NOVALIDSIG; 2800 return (ISC_R_COMPLETE); 2801 } 2802 2803 break; 2804 2805 case DNS_R_CNAME: 2806 if (DNS_TRUST_PENDING(val->frdataset.trust) || 2807 DNS_TRUST_ANSWER(val->frdataset.trust)) 2808 { 2809 result = create_validator( 2810 val, tname, dns_rdatatype_cname, 2811 &val->frdataset, &val->fsigrdataset, 2812 validator_callback_cname, 2813 "proveunsecure " 2814 "(cname)"); 2815 *resp = DNS_R_WAIT; 2816 if (result != ISC_R_SUCCESS) { 2817 *resp = result; 2818 } 2819 return (ISC_R_COMPLETE); 2820 } 2821 2822 break; 2823 2824 default: 2825 *resp = result; 2826 return (ISC_R_COMPLETE); 2827 } 2828 2829 /* 2830 * No definite answer yet; continue walking down labels. 2831 */ 2832 return (DNS_R_CONTINUE); 2833} 2834 2835/*% 2836 * proveunsecure walks down, label by label, from the closest enclosing 2837 * trust anchor to the name that is being validated, looking for an 2838 * endpoint in the chain of trust. That occurs when we can prove that 2839 * a DS record does not exist at a delegation point, or that a DS exists 2840 * at a delegation point but we don't support its algorithm/digest. If 2841 * no such endpoint is found, then the response should have been secure. 2842 * 2843 * Returns: 2844 * \li ISC_R_SUCCESS val->event->name is in an unsecure zone 2845 * \li DNS_R_WAIT validation is in progress. 2846 * \li DNS_R_MUSTBESECURE val->event->name is supposed to be secure 2847 * (policy) but we proved that it is unsecure. 2848 * \li DNS_R_NOVALIDSIG 2849 * \li DNS_R_NOVALIDNSEC 2850 * \li DNS_R_NOTINSECURE 2851 * \li DNS_R_BROKENCHAIN 2852 */ 2853static isc_result_t 2854proveunsecure(dns_validator_t *val, bool have_ds, bool resume) { 2855 isc_result_t result; 2856 char namebuf[DNS_NAME_FORMATSIZE]; 2857 dns_fixedname_t fixedsecroot; 2858 dns_name_t *secroot = dns_fixedname_initname(&fixedsecroot); 2859 unsigned int labels; 2860 2861 /* 2862 * We're attempting to prove insecurity. 2863 */ 2864 val->attributes |= VALATTR_INSECURITY; 2865 2866 dns_name_copynf(val->event->name, secroot); 2867 2868 /* 2869 * If this is a response to a DS query, we need to look in 2870 * the parent zone for the trust anchor. 2871 */ 2872 labels = dns_name_countlabels(secroot); 2873 if (val->event->type == dns_rdatatype_ds && labels > 1U) { 2874 dns_name_getlabelsequence(secroot, 1, labels - 1, secroot); 2875 } 2876 2877 result = dns_keytable_finddeepestmatch(val->keytable, secroot, secroot); 2878 if (result == ISC_R_NOTFOUND) { 2879 validator_log(val, ISC_LOG_DEBUG(3), "not beneath secure root"); 2880 return (markanswer(val, "proveunsecure (1)", 2881 "not beneath secure root")); 2882 } else if (result != ISC_R_SUCCESS) { 2883 return (result); 2884 } 2885 2886 if (!resume) { 2887 /* 2888 * We are looking for interruptions in the chain of trust. 2889 * That can only happen *below* the trust anchor, so we 2890 * start looking at the next label down. 2891 */ 2892 val->labels = dns_name_countlabels(secroot) + 1; 2893 } else { 2894 validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure"); 2895 2896 /* 2897 * If we have a DS rdataset and it is secure, check whether 2898 * it has a supported algorithm combination. If not, this is 2899 * an insecure delegation as far as this resolver is concerned. 2900 */ 2901 if (have_ds && val->frdataset.trust >= dns_trust_secure && 2902 !check_ds_algs(val, dns_fixedname_name(&val->fname), 2903 &val->frdataset)) 2904 { 2905 dns_name_format(dns_fixedname_name(&val->fname), 2906 namebuf, sizeof(namebuf)); 2907 validator_log(val, ISC_LOG_DEBUG(3), 2908 "no supported algorithm/digest (%s/DS)", 2909 namebuf); 2910 result = markanswer(val, "proveunsecure (2)", namebuf); 2911 goto out; 2912 } 2913 val->labels++; 2914 } 2915 2916 /* 2917 * Walk down through each of the remaining labels in the name, 2918 * looking for DS records. 2919 */ 2920 while (val->labels <= dns_name_countlabels(val->event->name)) { 2921 isc_result_t tresult; 2922 2923 result = seek_ds(val, &tresult); 2924 if (result == ISC_R_COMPLETE) { 2925 result = tresult; 2926 goto out; 2927 } 2928 2929 INSIST(result == DNS_R_CONTINUE); 2930 val->labels++; 2931 } 2932 2933 /* Couldn't complete insecurity proof. */ 2934 validator_log(val, ISC_LOG_DEBUG(3), "insecurity proof failed: %s", 2935 isc_result_totext(result)); 2936 return (DNS_R_NOTINSECURE); 2937 2938out: 2939 if (result != DNS_R_WAIT) { 2940 disassociate_rdatasets(val); 2941 } 2942 return (result); 2943} 2944 2945/*% 2946 * Start the validation process. 2947 * 2948 * Attempt to validate the answer based on the category it appears to 2949 * fall in. 2950 * \li 1. secure positive answer. 2951 * \li 2. unsecure positive answer. 2952 * \li 3. a negative answer (secure or unsecure). 2953 * 2954 * Note an answer that appears to be a secure positive answer may actually 2955 * be an unsecure positive answer. 2956 */ 2957static void 2958validator_start(isc_task_t *task, isc_event_t *event) { 2959 dns_validator_t *val; 2960 dns_validatorevent_t *vevent; 2961 bool want_destroy = false; 2962 isc_result_t result = ISC_R_FAILURE; 2963 2964 UNUSED(task); 2965 REQUIRE(event->ev_type == DNS_EVENT_VALIDATORSTART); 2966 vevent = (dns_validatorevent_t *)event; 2967 val = vevent->validator; 2968 2969 /* If the validator has been canceled, val->event == NULL */ 2970 if (val->event == NULL) { 2971 return; 2972 } 2973 2974 validator_log(val, ISC_LOG_DEBUG(3), "starting"); 2975 2976 LOCK(&val->lock); 2977 2978 if (val->event->rdataset != NULL && val->event->sigrdataset != NULL) { 2979 isc_result_t saved_result; 2980 2981 /* 2982 * This looks like a simple validation. We say "looks like" 2983 * because it might end up requiring an insecurity proof. 2984 */ 2985 validator_log(val, ISC_LOG_DEBUG(3), 2986 "attempting positive response validation"); 2987 2988 INSIST(dns_rdataset_isassociated(val->event->rdataset)); 2989 INSIST(dns_rdataset_isassociated(val->event->sigrdataset)); 2990 if (selfsigned_dnskey(val)) { 2991 result = validate_dnskey(val); 2992 } else { 2993 result = validate_answer(val, false); 2994 } 2995 if (result == DNS_R_NOVALIDSIG && 2996 (val->attributes & VALATTR_TRIEDVERIFY) == 0) { 2997 saved_result = result; 2998 validator_log(val, ISC_LOG_DEBUG(3), 2999 "falling back to insecurity proof"); 3000 result = proveunsecure(val, false, false); 3001 if (result == DNS_R_NOTINSECURE) { 3002 result = saved_result; 3003 } 3004 } 3005 } else if (val->event->rdataset != NULL && 3006 val->event->rdataset->type != 0) { 3007 /* 3008 * This is either an unsecure subdomain or a response 3009 * from a broken server. 3010 */ 3011 INSIST(dns_rdataset_isassociated(val->event->rdataset)); 3012 validator_log(val, ISC_LOG_DEBUG(3), 3013 "attempting insecurity proof"); 3014 3015 result = proveunsecure(val, false, false); 3016 if (result == DNS_R_NOTINSECURE) { 3017 validator_log(val, ISC_LOG_INFO, 3018 "got insecure response; " 3019 "parent indicates it should be secure"); 3020 } 3021 } else if ((val->event->rdataset == NULL && 3022 val->event->sigrdataset == NULL)) { 3023 /* 3024 * This is a validation of a negative response. 3025 */ 3026 validator_log(val, ISC_LOG_DEBUG(3), 3027 "attempting negative response validation " 3028 "from message"); 3029 3030 if (val->event->message->rcode == dns_rcode_nxdomain) { 3031 val->attributes |= VALATTR_NEEDNOQNAME; 3032 val->attributes |= VALATTR_NEEDNOWILDCARD; 3033 } else { 3034 val->attributes |= VALATTR_NEEDNODATA; 3035 } 3036 3037 result = validate_nx(val, false); 3038 } else if ((val->event->rdataset != NULL && 3039 NEGATIVE(val->event->rdataset))) { 3040 /* 3041 * This is a delayed validation of a negative cache entry. 3042 */ 3043 validator_log(val, ISC_LOG_DEBUG(3), 3044 "attempting negative response validation " 3045 "from cache"); 3046 3047 if (NXDOMAIN(val->event->rdataset)) { 3048 val->attributes |= VALATTR_NEEDNOQNAME; 3049 val->attributes |= VALATTR_NEEDNOWILDCARD; 3050 } else { 3051 val->attributes |= VALATTR_NEEDNODATA; 3052 } 3053 3054 result = validate_nx(val, false); 3055 } else { 3056 INSIST(0); 3057 ISC_UNREACHABLE(); 3058 } 3059 3060 if (result != DNS_R_WAIT) { 3061 want_destroy = exit_check(val); 3062 validator_done(val, result); 3063 } 3064 3065 UNLOCK(&val->lock); 3066 if (want_destroy) { 3067 destroy(val); 3068 } 3069} 3070 3071isc_result_t 3072dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type, 3073 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, 3074 dns_message_t *message, unsigned int options, 3075 isc_task_t *task, isc_taskaction_t action, void *arg, 3076 dns_validator_t **validatorp) { 3077 isc_result_t result = ISC_R_FAILURE; 3078 dns_validator_t *val; 3079 isc_task_t *tclone = NULL; 3080 dns_validatorevent_t *event; 3081 3082 REQUIRE(name != NULL); 3083 REQUIRE(rdataset != NULL || 3084 (rdataset == NULL && sigrdataset == NULL && message != NULL)); 3085 REQUIRE(validatorp != NULL && *validatorp == NULL); 3086 3087 event = (dns_validatorevent_t *)isc_event_allocate( 3088 view->mctx, task, DNS_EVENT_VALIDATORSTART, validator_start, 3089 NULL, sizeof(dns_validatorevent_t)); 3090 3091 isc_task_attach(task, &tclone); 3092 event->result = ISC_R_FAILURE; 3093 event->name = name; 3094 event->type = type; 3095 event->rdataset = rdataset; 3096 event->sigrdataset = sigrdataset; 3097 event->message = message; 3098 memset(event->proofs, 0, sizeof(event->proofs)); 3099 event->optout = false; 3100 event->secure = false; 3101 3102 val = isc_mem_get(view->mctx, sizeof(*val)); 3103 *val = (dns_validator_t){ .event = event, 3104 .options = options, 3105 .task = task, 3106 .action = action, 3107 .arg = arg }; 3108 3109 dns_view_weakattach(view, &val->view); 3110 isc_mutex_init(&val->lock); 3111 3112 result = dns_view_getsecroots(val->view, &val->keytable); 3113 if (result != ISC_R_SUCCESS) { 3114 goto cleanup; 3115 } 3116 3117 val->mustbesecure = dns_resolver_getmustbesecure(view->resolver, name); 3118 dns_rdataset_init(&val->fdsset); 3119 dns_rdataset_init(&val->frdataset); 3120 dns_rdataset_init(&val->fsigrdataset); 3121 dns_fixedname_init(&val->wild); 3122 dns_fixedname_init(&val->closest); 3123 isc_stdtime_get(&val->start); 3124 ISC_LINK_INIT(val, link); 3125 val->magic = VALIDATOR_MAGIC; 3126 3127 event->validator = val; 3128 3129 if ((options & DNS_VALIDATOR_DEFER) == 0) { 3130 isc_task_send(task, ISC_EVENT_PTR(&event)); 3131 } 3132 3133 *validatorp = val; 3134 3135 return (ISC_R_SUCCESS); 3136 3137cleanup: 3138 isc_mutex_destroy(&val->lock); 3139 3140 isc_task_detach(&tclone); 3141 isc_event_free(ISC_EVENT_PTR(&event)); 3142 3143 dns_view_weakdetach(&val->view); 3144 isc_mem_put(view->mctx, val, sizeof(*val)); 3145 3146 return (result); 3147} 3148 3149void 3150dns_validator_send(dns_validator_t *validator) { 3151 isc_event_t *event; 3152 REQUIRE(VALID_VALIDATOR(validator)); 3153 3154 LOCK(&validator->lock); 3155 3156 INSIST((validator->options & DNS_VALIDATOR_DEFER) != 0); 3157 event = (isc_event_t *)validator->event; 3158 validator->options &= ~DNS_VALIDATOR_DEFER; 3159 UNLOCK(&validator->lock); 3160 3161 isc_task_send(validator->task, ISC_EVENT_PTR(&event)); 3162} 3163 3164void 3165dns_validator_cancel(dns_validator_t *validator) { 3166 dns_fetch_t *fetch = NULL; 3167 3168 REQUIRE(VALID_VALIDATOR(validator)); 3169 3170 LOCK(&validator->lock); 3171 3172 validator_log(validator, ISC_LOG_DEBUG(3), "dns_validator_cancel"); 3173 3174 if ((validator->attributes & VALATTR_CANCELED) == 0) { 3175 validator->attributes |= VALATTR_CANCELED; 3176 if (validator->event != NULL) { 3177 fetch = validator->fetch; 3178 validator->fetch = NULL; 3179 3180 if (validator->subvalidator != NULL) { 3181 dns_validator_cancel(validator->subvalidator); 3182 } 3183 if ((validator->options & DNS_VALIDATOR_DEFER) != 0) { 3184 validator->options &= ~DNS_VALIDATOR_DEFER; 3185 validator_done(validator, ISC_R_CANCELED); 3186 } 3187 } 3188 } 3189 UNLOCK(&validator->lock); 3190 3191 /* Need to cancel and destroy the fetch outside validator lock */ 3192 if (fetch != NULL) { 3193 dns_resolver_cancelfetch(fetch); 3194 dns_resolver_destroyfetch(&fetch); 3195 } 3196} 3197 3198static void 3199destroy(dns_validator_t *val) { 3200 isc_mem_t *mctx; 3201 3202 REQUIRE(SHUTDOWN(val)); 3203 REQUIRE(val->event == NULL); 3204 REQUIRE(val->fetch == NULL); 3205 3206 val->magic = 0; 3207 if (val->key != NULL) { 3208 dst_key_free(&val->key); 3209 } 3210 if (val->keytable != NULL) { 3211 dns_keytable_detach(&val->keytable); 3212 } 3213 if (val->subvalidator != NULL) { 3214 dns_validator_destroy(&val->subvalidator); 3215 } 3216 disassociate_rdatasets(val); 3217 mctx = val->view->mctx; 3218 if (val->siginfo != NULL) { 3219 isc_mem_put(mctx, val->siginfo, sizeof(*val->siginfo)); 3220 } 3221 isc_mutex_destroy(&val->lock); 3222 dns_view_weakdetach(&val->view); 3223 isc_mem_put(mctx, val, sizeof(*val)); 3224} 3225 3226void 3227dns_validator_destroy(dns_validator_t **validatorp) { 3228 dns_validator_t *val; 3229 bool want_destroy = false; 3230 3231 REQUIRE(validatorp != NULL); 3232 val = *validatorp; 3233 *validatorp = NULL; 3234 REQUIRE(VALID_VALIDATOR(val)); 3235 3236 LOCK(&val->lock); 3237 3238 val->attributes |= VALATTR_SHUTDOWN; 3239 validator_log(val, ISC_LOG_DEBUG(4), "dns_validator_destroy"); 3240 3241 want_destroy = exit_check(val); 3242 UNLOCK(&val->lock); 3243 if (want_destroy) { 3244 destroy(val); 3245 } 3246} 3247 3248static void 3249validator_logv(dns_validator_t *val, isc_logcategory_t *category, 3250 isc_logmodule_t *module, int level, const char *fmt, 3251 va_list ap) { 3252 char msgbuf[2048]; 3253 static const char spaces[] = " *"; 3254 int depth = val->depth * 2; 3255 const char *viewname, *sep1, *sep2; 3256 3257 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 3258 3259 if ((unsigned int)depth >= sizeof spaces) { 3260 depth = sizeof spaces - 1; 3261 } 3262 3263 /* 3264 * Log the view name unless it's: 3265 * * "_default/IN" (which means there's only one view 3266 * configured in the server), or 3267 * * "_dnsclient/IN" (which means this is being called 3268 * from an application using dns/client.c). 3269 */ 3270 if (val->view->rdclass == dns_rdataclass_in && 3271 (strcmp(val->view->name, "_default") == 0 || 3272 strcmp(val->view->name, DNS_CLIENTVIEW_NAME) == 0)) 3273 { 3274 sep1 = viewname = sep2 = ""; 3275 } else { 3276 sep1 = "view "; 3277 viewname = val->view->name; 3278 sep2 = ": "; 3279 } 3280 3281 if (val->event != NULL && val->event->name != NULL) { 3282 char namebuf[DNS_NAME_FORMATSIZE]; 3283 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3284 3285 dns_name_format(val->event->name, namebuf, sizeof(namebuf)); 3286 dns_rdatatype_format(val->event->type, typebuf, 3287 sizeof(typebuf)); 3288 isc_log_write(dns_lctx, category, module, level, 3289 "%s%s%s%.*svalidating %s/%s: %s", sep1, viewname, 3290 sep2, depth, spaces, namebuf, typebuf, msgbuf); 3291 } else { 3292 isc_log_write(dns_lctx, category, module, level, 3293 "%s%s%s%.*svalidator @%p: %s", sep1, viewname, 3294 sep2, depth, spaces, val, msgbuf); 3295 } 3296} 3297 3298static void 3299validator_log(void *val, int level, const char *fmt, ...) { 3300 va_list ap; 3301 3302 if (!isc_log_wouldlog(dns_lctx, level)) { 3303 return; 3304 } 3305 3306 va_start(ap, fmt); 3307 3308 validator_logv(val, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_VALIDATOR, 3309 level, fmt, ap); 3310 va_end(ap); 3311} 3312 3313static void 3314validator_logcreate(dns_validator_t *val, dns_name_t *name, 3315 dns_rdatatype_t type, const char *caller, 3316 const char *operation) { 3317 char namestr[DNS_NAME_FORMATSIZE]; 3318 char typestr[DNS_RDATATYPE_FORMATSIZE]; 3319 3320 dns_name_format(name, namestr, sizeof(namestr)); 3321 dns_rdatatype_format(type, typestr, sizeof(typestr)); 3322 validator_log(val, ISC_LOG_DEBUG(9), "%s: creating %s for %s %s", 3323 caller, operation, namestr, typestr); 3324} 3325