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