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