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