/contrib/bind9/lib/dns/validator.c
C | 4369 lines | 3257 code | 378 blank | 734 comment | 1178 complexity | a9e623957e291c360bd8b11e4018b46b MD5 | raw file
Large files files are truncated, but you can click here to view the full file
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…
Large files files are truncated, but you can click here to view the full file