PageRenderTime 293ms CodeModel.GetById 193ms app.highlight 83ms RepoModel.GetById 2ms app.codeStats 1ms

/contrib/bind9/lib/dns/validator.c

https://bitbucket.org/freebsd/freebsd-head/
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