PageRenderTime 120ms CodeModel.GetById 19ms app.highlight 90ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/lib/dns/nsec3.c

https://bitbucket.org/freebsd/freebsd-head/
C | 1834 lines | 1375 code | 218 blank | 241 comment | 402 complexity | 85a8d6405af33523624c3a37ffe8279b MD5 | raw file
   1/*
   2 * Copyright (C) 2006, 2008-2012  Internet Systems Consortium, Inc. ("ISC")
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
   9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14 * PERFORMANCE OF THIS SOFTWARE.
  15 */
  16
  17/* $Id$ */
  18
  19#include <config.h>
  20
  21#include <isc/base32.h>
  22#include <isc/buffer.h>
  23#include <isc/hex.h>
  24#include <isc/iterated_hash.h>
  25#include <isc/string.h>
  26#include <isc/util.h>
  27
  28#include <dst/dst.h>
  29
  30#include <dns/db.h>
  31#include <dns/zone.h>
  32#include <dns/compress.h>
  33#include <dns/dbiterator.h>
  34#include <dns/diff.h>
  35#include <dns/fixedname.h>
  36#include <dns/nsec3.h>
  37#include <dns/rdata.h>
  38#include <dns/rdatalist.h>
  39#include <dns/rdataset.h>
  40#include <dns/rdatasetiter.h>
  41#include <dns/rdatastruct.h>
  42#include <dns/result.h>
  43
  44#define CHECK(x) do { \
  45	result = (x); \
  46	if (result != ISC_R_SUCCESS) \
  47		goto failure; \
  48	} while (0)
  49
  50#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
  51#define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
  52#define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
  53
  54static void
  55set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
  56	unsigned int shift, mask;
  57
  58	shift = 7 - (index % 8);
  59	mask = 1 << shift;
  60
  61	if (bit != 0)
  62		array[index / 8] |= mask;
  63	else
  64		array[index / 8] &= (~mask & 0xFF);
  65}
  66
  67static unsigned int
  68bit_isset(unsigned char *array, unsigned int index) {
  69	unsigned int byte, shift, mask;
  70
  71	byte = array[index / 8];
  72	shift = 7 - (index % 8);
  73	mask = 1 << shift;
  74
  75	return ((byte & mask) != 0);
  76}
  77
  78isc_result_t
  79dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
  80		     dns_dbnode_t *node, unsigned int hashalg,
  81		     unsigned int flags, unsigned int iterations,
  82		     const unsigned char *salt, size_t salt_length,
  83		     const unsigned char *nexthash, size_t hash_length,
  84		     unsigned char *buffer, dns_rdata_t *rdata)
  85{
  86	isc_result_t result;
  87	dns_rdataset_t rdataset;
  88	isc_region_t r;
  89	unsigned int i, window;
  90	int octet;
  91	isc_boolean_t found;
  92	isc_boolean_t found_ns;
  93	isc_boolean_t need_rrsig;
  94
  95	unsigned char *nsec_bits, *bm;
  96	unsigned int max_type;
  97	dns_rdatasetiter_t *rdsiter;
  98	unsigned char *p;
  99
 100	REQUIRE(salt_length < 256U);
 101	REQUIRE(hash_length < 256U);
 102	REQUIRE(flags <= 0xffU);
 103	REQUIRE(hashalg <= 0xffU);
 104	REQUIRE(iterations <= 0xffffU);
 105
 106	switch (hashalg) {
 107	case dns_hash_sha1:
 108		REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
 109		break;
 110	}
 111
 112	memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
 113
 114	p = buffer;
 115
 116	*p++ = hashalg;
 117	*p++ = flags;
 118
 119	*p++ = iterations >> 8;
 120	*p++ = iterations;
 121
 122	*p++ = salt_length;
 123	memcpy(p, salt, salt_length);
 124	p += salt_length;
 125
 126	*p++ = hash_length;
 127	memcpy(p, nexthash, hash_length);
 128	p += hash_length;
 129
 130	r.length = p - buffer;
 131	r.base = buffer;
 132
 133	/*
 134	 * Use the end of the space for a raw bitmap leaving enough
 135	 * space for the window identifiers and length octets.
 136	 */
 137	bm = r.base + r.length + 512;
 138	nsec_bits = r.base + r.length;
 139	max_type = 0;
 140	if (node == NULL)
 141		goto collapse_bitmap;
 142	dns_rdataset_init(&rdataset);
 143	rdsiter = NULL;
 144	result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
 145	if (result != ISC_R_SUCCESS)
 146		return (result);
 147	found = found_ns = need_rrsig = ISC_FALSE;
 148	for (result = dns_rdatasetiter_first(rdsiter);
 149	     result == ISC_R_SUCCESS;
 150	     result = dns_rdatasetiter_next(rdsiter))
 151	{
 152		dns_rdatasetiter_current(rdsiter, &rdataset);
 153		if (rdataset.type != dns_rdatatype_nsec &&
 154		    rdataset.type != dns_rdatatype_nsec3 &&
 155		    rdataset.type != dns_rdatatype_rrsig) {
 156			if (rdataset.type > max_type)
 157				max_type = rdataset.type;
 158			set_bit(bm, rdataset.type, 1);
 159			/*
 160			 * Work out if we need to set the RRSIG bit for
 161			 * this node.  We set the RRSIG bit if either of
 162			 * the following conditions are met:
 163			 * 1) We have a SOA or DS then we need to set
 164			 *    the RRSIG bit as both always will be signed.
 165			 * 2) We set the RRSIG bit if we don't have
 166			 *    a NS record but do have other data.
 167			 */
 168			if (rdataset.type == dns_rdatatype_soa ||
 169			    rdataset.type == dns_rdatatype_ds)
 170				need_rrsig = ISC_TRUE;
 171			else if (rdataset.type == dns_rdatatype_ns)
 172				found_ns = ISC_TRUE;
 173			else
 174				found = ISC_TRUE;
 175		}
 176		dns_rdataset_disassociate(&rdataset);
 177	}
 178	if ((found && !found_ns) || need_rrsig) {
 179		if (dns_rdatatype_rrsig > max_type)
 180			max_type = dns_rdatatype_rrsig;
 181		set_bit(bm, dns_rdatatype_rrsig, 1);
 182	}
 183
 184	/*
 185	 * At zone cuts, deny the existence of glue in the parent zone.
 186	 */
 187	if (bit_isset(bm, dns_rdatatype_ns) &&
 188	    ! bit_isset(bm, dns_rdatatype_soa)) {
 189		for (i = 0; i <= max_type; i++) {
 190			if (bit_isset(bm, i) &&
 191			    ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
 192				set_bit(bm, i, 0);
 193		}
 194	}
 195
 196	dns_rdatasetiter_destroy(&rdsiter);
 197	if (result != ISC_R_NOMORE)
 198		return (result);
 199
 200 collapse_bitmap:
 201	for (window = 0; window < 256; window++) {
 202		if (window * 256 > max_type)
 203			break;
 204		for (octet = 31; octet >= 0; octet--)
 205			if (bm[window * 32 + octet] != 0)
 206				break;
 207		if (octet < 0)
 208			continue;
 209		nsec_bits[0] = window;
 210		nsec_bits[1] = octet + 1;
 211		/*
 212		 * Note: potentially overlapping move.
 213		 */
 214		memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
 215		nsec_bits += 3 + octet;
 216	}
 217	r.length = nsec_bits - r.base;
 218	INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
 219	dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
 220
 221	return (ISC_R_SUCCESS);
 222}
 223
 224isc_boolean_t
 225dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
 226	dns_rdata_nsec3_t nsec3;
 227	isc_result_t result;
 228	isc_boolean_t present;
 229	unsigned int i, len, window;
 230
 231	REQUIRE(rdata != NULL);
 232	REQUIRE(rdata->type == dns_rdatatype_nsec3);
 233
 234	/* This should never fail */
 235	result = dns_rdata_tostruct(rdata, &nsec3, NULL);
 236	INSIST(result == ISC_R_SUCCESS);
 237
 238	present = ISC_FALSE;
 239	for (i = 0; i < nsec3.len; i += len) {
 240		INSIST(i + 2 <= nsec3.len);
 241		window = nsec3.typebits[i];
 242		len = nsec3.typebits[i + 1];
 243		INSIST(len > 0 && len <= 32);
 244		i += 2;
 245		INSIST(i + len <= nsec3.len);
 246		if (window * 256 > type)
 247			break;
 248		if ((window + 1) * 256 <= type)
 249			continue;
 250		if (type < (window * 256) + len * 8)
 251			present = ISC_TF(bit_isset(&nsec3.typebits[i],
 252						   type % 256));
 253		break;
 254	}
 255	dns_rdata_freestruct(&nsec3);
 256	return (present);
 257}
 258
 259isc_result_t
 260dns_nsec3_hashname(dns_fixedname_t *result,
 261		   unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
 262		   size_t *hash_length, dns_name_t *name, dns_name_t *origin,
 263		   dns_hash_t hashalg, unsigned int iterations,
 264		   const unsigned char *salt, size_t saltlength)
 265{
 266	unsigned char hash[NSEC3_MAX_HASH_LENGTH];
 267	unsigned char nametext[DNS_NAME_FORMATSIZE];
 268	dns_fixedname_t fixed;
 269	dns_name_t *downcased;
 270	isc_buffer_t namebuffer;
 271	isc_region_t region;
 272	size_t len;
 273
 274	if (rethash == NULL)
 275		rethash = hash;
 276
 277	memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
 278
 279	dns_fixedname_init(&fixed);
 280	downcased = dns_fixedname_name(&fixed);
 281	dns_name_downcase(name, downcased, NULL);
 282
 283	/* hash the node name */
 284	len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
 285				downcased->ndata, downcased->length);
 286	if (len == 0U)
 287		return (DNS_R_BADALG);
 288
 289	if (hash_length != NULL)
 290		*hash_length = len;
 291
 292	/* convert the hash to base32hex */
 293	region.base = rethash;
 294	region.length = len;
 295	isc_buffer_init(&namebuffer, nametext, sizeof nametext);
 296	isc_base32hex_totext(&region, 1, "", &namebuffer);
 297
 298	/* convert the hex to a domain name */
 299	dns_fixedname_init(result);
 300	return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
 301				  origin, 0, NULL));
 302}
 303
 304unsigned int
 305dns_nsec3_hashlength(dns_hash_t hash) {
 306
 307	switch (hash) {
 308	case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
 309	}
 310	return (0);
 311}
 312
 313isc_boolean_t
 314dns_nsec3_supportedhash(dns_hash_t hash) {
 315	switch (hash) {
 316	case dns_hash_sha1: return (ISC_TRUE);
 317	}
 318	return (ISC_FALSE);
 319}
 320
 321/*%
 322 * Update a single RR in version 'ver' of 'db' and log the
 323 * update in 'diff'.
 324 *
 325 * Ensures:
 326 * \li  '*tuple' == NULL.  Either the tuple is freed, or its
 327 *      ownership has been transferred to the diff.
 328 */
 329static isc_result_t
 330do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
 331	     dns_diff_t *diff)
 332{
 333	dns_diff_t temp_diff;
 334	isc_result_t result;
 335
 336	/*
 337	 * Create a singleton diff.
 338	 */
 339	dns_diff_init(diff->mctx, &temp_diff);
 340	temp_diff.resign = diff->resign;
 341	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
 342
 343	/*
 344	 * Apply it to the database.
 345	 */
 346	result = dns_diff_apply(&temp_diff, db, ver);
 347	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
 348	if (result != ISC_R_SUCCESS) {
 349		dns_difftuple_free(tuple);
 350		return (result);
 351	}
 352
 353	/*
 354	 * Merge it into the current pending journal entry.
 355	 */
 356	dns_diff_appendminimal(diff, tuple);
 357
 358	/*
 359	 * Do not clear temp_diff.
 360	 */
 361	return (ISC_R_SUCCESS);
 362}
 363
 364/*%
 365 * Set '*exists' to true iff the given name exists, to false otherwise.
 366 */
 367static isc_result_t
 368name_exists(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
 369	    isc_boolean_t *exists)
 370{
 371	isc_result_t result;
 372	dns_dbnode_t *node = NULL;
 373	dns_rdatasetiter_t *iter = NULL;
 374
 375	result = dns_db_findnode(db, name, ISC_FALSE, &node);
 376	if (result == ISC_R_NOTFOUND) {
 377		*exists = ISC_FALSE;
 378		return (ISC_R_SUCCESS);
 379	}
 380	if (result != ISC_R_SUCCESS)
 381		return (result);
 382
 383	result = dns_db_allrdatasets(db, node, version,
 384				     (isc_stdtime_t) 0, &iter);
 385	if (result != ISC_R_SUCCESS)
 386		goto cleanup_node;
 387
 388	result = dns_rdatasetiter_first(iter);
 389	if (result == ISC_R_SUCCESS) {
 390		*exists = ISC_TRUE;
 391	} else if (result == ISC_R_NOMORE) {
 392		*exists = ISC_FALSE;
 393		result = ISC_R_SUCCESS;
 394	} else
 395		*exists = ISC_FALSE;
 396	dns_rdatasetiter_destroy(&iter);
 397
 398 cleanup_node:
 399	dns_db_detachnode(db, &node);
 400	return (result);
 401}
 402
 403static isc_boolean_t
 404match_nsec3param(const dns_rdata_nsec3_t *nsec3,
 405		 const dns_rdata_nsec3param_t *nsec3param)
 406{
 407	if (nsec3->hash == nsec3param->hash &&
 408	    nsec3->iterations == nsec3param->iterations &&
 409	    nsec3->salt_length == nsec3param->salt_length &&
 410	    !memcmp(nsec3->salt, nsec3param->salt, nsec3->salt_length))
 411		return (ISC_TRUE);
 412	return (ISC_FALSE);
 413}
 414
 415/*%
 416 * Delete NSEC3 records at "name" which match "param", recording the
 417 * change in "diff".
 418 */
 419static isc_result_t
 420delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
 421       const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
 422{
 423	dns_dbnode_t *node = NULL ;
 424	dns_difftuple_t *tuple = NULL;
 425	dns_rdata_nsec3_t nsec3;
 426	dns_rdataset_t rdataset;
 427	isc_result_t result;
 428
 429	result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
 430	if (result == ISC_R_NOTFOUND)
 431		return (ISC_R_SUCCESS);
 432	if (result != ISC_R_SUCCESS)
 433		return (result);
 434
 435	dns_rdataset_init(&rdataset);
 436	result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
 437				     (isc_stdtime_t) 0, &rdataset, NULL);
 438
 439	if (result == ISC_R_NOTFOUND) {
 440		result = ISC_R_SUCCESS;
 441		goto cleanup_node;
 442	}
 443	if (result != ISC_R_SUCCESS)
 444		goto cleanup_node;
 445
 446	for (result = dns_rdataset_first(&rdataset);
 447	     result == ISC_R_SUCCESS;
 448	     result = dns_rdataset_next(&rdataset))
 449	{
 450		dns_rdata_t rdata = DNS_RDATA_INIT;
 451		dns_rdataset_current(&rdataset, &rdata);
 452		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
 453
 454		if (!match_nsec3param(&nsec3, nsec3param))
 455			continue;
 456
 457		result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
 458					      rdataset.ttl, &rdata, &tuple);
 459		if (result != ISC_R_SUCCESS)
 460			goto failure;
 461		result = do_one_tuple(&tuple, db, version, diff);
 462		if (result != ISC_R_SUCCESS)
 463			goto failure;
 464	}
 465	if (result != ISC_R_NOMORE)
 466		goto failure;
 467	result = ISC_R_SUCCESS;
 468
 469 failure:
 470	dns_rdataset_disassociate(&rdataset);
 471 cleanup_node:
 472	dns_db_detachnode(db, &node);
 473
 474	return (result);
 475}
 476
 477static isc_boolean_t
 478better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
 479	dns_rdataset_t rdataset;
 480	isc_result_t result;
 481
 482	if (REMOVE(param->data[1]))
 483		return (ISC_TRUE);
 484
 485	dns_rdataset_init(&rdataset);
 486	dns_rdataset_clone(nsec3paramset, &rdataset);
 487	for (result = dns_rdataset_first(&rdataset);
 488	     result == ISC_R_SUCCESS;
 489	     result = dns_rdataset_next(&rdataset)) {
 490		dns_rdata_t rdata =  DNS_RDATA_INIT;
 491		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
 492
 493		if (rdataset.type != dns_rdatatype_nsec3param) {
 494			dns_rdata_t tmprdata =  DNS_RDATA_INIT;
 495			dns_rdataset_current(&rdataset, &tmprdata);
 496			if (!dns_nsec3param_fromprivate(&tmprdata, &rdata,
 497							buf, sizeof(buf)))
 498				continue;
 499		} else
 500			dns_rdataset_current(&rdataset, &rdata);
 501
 502		if (rdata.length != param->length)
 503			continue;
 504		if (rdata.data[0] != param->data[0] ||
 505		    REMOVE(rdata.data[1]) ||
 506		    rdata.data[2] != param->data[2] ||
 507		    rdata.data[3] != param->data[3] ||
 508		    rdata.data[4] != param->data[4] ||
 509		    memcmp(&rdata.data[5], &param->data[5], param->data[4]))
 510			continue;
 511		if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
 512			dns_rdataset_disassociate(&rdataset);
 513			return (ISC_TRUE);
 514		}
 515	}
 516	dns_rdataset_disassociate(&rdataset);
 517	return (ISC_FALSE);
 518}
 519
 520static isc_result_t
 521find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
 522	   const dns_rdata_nsec3param_t *nsec3param)
 523{
 524	isc_result_t result;
 525	for (result = dns_rdataset_first(rdataset);
 526	     result == ISC_R_SUCCESS;
 527	     result = dns_rdataset_next(rdataset)) {
 528		dns_rdata_t rdata = DNS_RDATA_INIT;
 529
 530		dns_rdataset_current(rdataset, &rdata);
 531		CHECK(dns_rdata_tostruct(&rdata, nsec3, NULL));
 532		dns_rdata_reset(&rdata);
 533		if (match_nsec3param(nsec3, nsec3param))
 534			break;
 535	}
 536 failure:
 537	return (result);
 538}
 539
 540isc_result_t
 541dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
 542		   dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
 543		   dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff)
 544{
 545	dns_dbiterator_t *dbit = NULL;
 546	dns_dbnode_t *node = NULL;
 547	dns_dbnode_t *newnode = NULL;
 548	dns_difftuple_t *tuple = NULL;
 549	dns_fixedname_t fixed;
 550	dns_fixedname_t fprev;
 551	dns_hash_t hash;
 552	dns_name_t *hashname;
 553	dns_name_t *origin;
 554	dns_name_t *prev;
 555	dns_name_t empty;
 556	dns_rdata_nsec3_t nsec3;
 557	dns_rdata_t rdata = DNS_RDATA_INIT;
 558	dns_rdataset_t rdataset;
 559	int pass;
 560	isc_boolean_t exists = ISC_FALSE;
 561	isc_boolean_t maybe_remove_unsecure = ISC_FALSE;
 562	isc_uint8_t flags;
 563	isc_buffer_t buffer;
 564	isc_result_t result;
 565	unsigned char *old_next;
 566	unsigned char *salt;
 567	unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
 568	unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
 569	unsigned int iterations;
 570	unsigned int labels;
 571	size_t next_length;
 572	unsigned int old_length;
 573	unsigned int salt_length;
 574
 575	dns_fixedname_init(&fixed);
 576	hashname = dns_fixedname_name(&fixed);
 577	dns_fixedname_init(&fprev);
 578	prev = dns_fixedname_name(&fprev);
 579
 580	dns_rdataset_init(&rdataset);
 581
 582	origin = dns_db_origin(db);
 583
 584	/*
 585	 * Chain parameters.
 586	 */
 587	hash = nsec3param->hash;
 588	iterations = nsec3param->iterations;
 589	salt_length = nsec3param->salt_length;
 590	salt = nsec3param->salt;
 591
 592	/*
 593	 * Default flags for a new chain.
 594	 */
 595	flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
 596
 597	/*
 598	 * If this is the first NSEC3 in the chain nexthash will
 599	 * remain pointing to itself.
 600	 */
 601	next_length = sizeof(nexthash);
 602	CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
 603				 name, origin, hash, iterations,
 604				 salt, salt_length));
 605
 606	/*
 607	 * Create the node if it doesn't exist and hold
 608	 * a reference to it until we have added the NSEC3.
 609	 */
 610	CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
 611
 612	/*
 613	 * Seek the iterator to the 'newnode'.
 614	 */
 615	CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
 616	CHECK(dns_dbiterator_seek(dbit, hashname));
 617	CHECK(dns_dbiterator_pause(dbit));
 618	result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
 619				     0, (isc_stdtime_t) 0, &rdataset, NULL);
 620	/*
 621	 * If we updating a existing NSEC3 then find its
 622	 * next field.
 623	 */
 624	if (result == ISC_R_SUCCESS) {
 625		result = find_nsec3(&nsec3, &rdataset, nsec3param);
 626		if (result == ISC_R_SUCCESS) {
 627			if (!CREATE(nsec3param->flags))
 628				flags = nsec3.flags;
 629			next_length = nsec3.next_length;
 630			INSIST(next_length <= sizeof(nexthash));
 631			memcpy(nexthash, nsec3.next, next_length);
 632			dns_rdataset_disassociate(&rdataset);
 633			/*
 634			 * If the NSEC3 is not for a unsecure delegation then
 635			 * we are just updating it.  If it is for a unsecure
 636			 * delegation then we need find out if we need to
 637			 * remove the NSEC3 record or not by examining the
 638			 * previous NSEC3 record.
 639			 */
 640			if (!unsecure)
 641				goto addnsec3;
 642			else if (CREATE(nsec3param->flags) && OPTOUT(flags)) {
 643				result = dns_nsec3_delnsec3(db, version, name,
 644							    nsec3param, diff);
 645				goto failure;
 646			} else
 647				maybe_remove_unsecure = ISC_TRUE;
 648		} else {
 649			dns_rdataset_disassociate(&rdataset);
 650			if (result != ISC_R_NOMORE)
 651				goto failure;
 652		}
 653	}
 654
 655	/*
 656	 * Find the previous NSEC3 (if any) and update it if required.
 657	 */
 658	pass = 0;
 659	do {
 660		result = dns_dbiterator_prev(dbit);
 661		if (result == ISC_R_NOMORE) {
 662			pass++;
 663			CHECK(dns_dbiterator_last(dbit));
 664		}
 665		CHECK(dns_dbiterator_current(dbit, &node, prev));
 666		CHECK(dns_dbiterator_pause(dbit));
 667		result = dns_db_findrdataset(db, node, version,
 668					     dns_rdatatype_nsec3, 0,
 669					     (isc_stdtime_t) 0, &rdataset,
 670					     NULL);
 671		dns_db_detachnode(db, &node);
 672		if (result != ISC_R_SUCCESS)
 673			continue;
 674
 675		result = find_nsec3(&nsec3, &rdataset, nsec3param);
 676		if (result == ISC_R_NOMORE) {
 677			dns_rdataset_disassociate(&rdataset);
 678			continue;
 679		}
 680		if (result != ISC_R_SUCCESS)
 681			goto failure;
 682
 683		if (maybe_remove_unsecure) {
 684			dns_rdataset_disassociate(&rdataset);
 685			/*
 686			 * If we have OPTOUT set in the previous NSEC3 record
 687			 * we actually need to delete the NSEC3 record.
 688			 * Otherwise we just need to replace the NSEC3 record.
 689			 */
 690			if (OPTOUT(nsec3.flags)) {
 691				result = dns_nsec3_delnsec3(db, version, name,
 692							    nsec3param, diff);
 693				goto failure;
 694			}
 695			goto addnsec3;
 696		} else {
 697			/*
 698			 * Is this is a unsecure delegation we are adding?
 699			 * If so no change is required.
 700			 */
 701			if (OPTOUT(nsec3.flags) && unsecure) {
 702				dns_rdataset_disassociate(&rdataset);
 703				goto failure;
 704			}
 705		}
 706
 707		old_next = nsec3.next;
 708		old_length = nsec3.next_length;
 709
 710		/*
 711		 * Delete the old previous NSEC3.
 712		 */
 713		CHECK(delete(db, version, prev, nsec3param, diff));
 714
 715		/*
 716		 * Fixup the previous NSEC3.
 717		 */
 718		nsec3.next = nexthash;
 719		nsec3.next_length = next_length;
 720		isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
 721		CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
 722					   dns_rdatatype_nsec3, &nsec3,
 723					   &buffer));
 724		CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
 725					   rdataset.ttl, &rdata, &tuple));
 726		CHECK(do_one_tuple(&tuple, db, version, diff));
 727		INSIST(old_length <= sizeof(nexthash));
 728		memcpy(nexthash, old_next, old_length);
 729		if (!CREATE(nsec3param->flags))
 730			flags = nsec3.flags;
 731		dns_rdata_reset(&rdata);
 732		dns_rdataset_disassociate(&rdataset);
 733		break;
 734	} while (pass < 2);
 735
 736 addnsec3:
 737	/*
 738	 * Create the NSEC3 RDATA.
 739	 */
 740	CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
 741	CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
 742				   salt, salt_length, nexthash, next_length,
 743				   nsec3buf, &rdata));
 744	dns_db_detachnode(db, &node);
 745
 746	/*
 747	 * Delete the old NSEC3 and record the change.
 748	 */
 749	CHECK(delete(db, version, hashname, nsec3param, diff));
 750	/*
 751	 * Add the new NSEC3 and record the change.
 752	 */
 753	CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
 754				   hashname, nsecttl, &rdata, &tuple));
 755	CHECK(do_one_tuple(&tuple, db, version, diff));
 756	INSIST(tuple == NULL);
 757	dns_rdata_reset(&rdata);
 758	dns_db_detachnode(db, &newnode);
 759
 760	/*
 761	 * Add missing NSEC3 records for empty nodes
 762	 */
 763	dns_name_init(&empty, NULL);
 764	dns_name_clone(name, &empty);
 765	do {
 766		labels = dns_name_countlabels(&empty) - 1;
 767		if (labels <= dns_name_countlabels(origin))
 768			break;
 769		dns_name_getlabelsequence(&empty, 1, labels, &empty);
 770		CHECK(name_exists(db, version, &empty, &exists));
 771		if (exists)
 772			break;
 773		CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
 774					 &empty, origin, hash, iterations,
 775					 salt, salt_length));
 776
 777		/*
 778		 * Create the node if it doesn't exist and hold
 779		 * a reference to it until we have added the NSEC3
 780		 * or we discover we don't need to add make a change.
 781		 */
 782		CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
 783		result = dns_db_findrdataset(db, newnode, version,
 784					     dns_rdatatype_nsec3, 0,
 785					     (isc_stdtime_t) 0, &rdataset,
 786					     NULL);
 787		if (result == ISC_R_SUCCESS) {
 788			result = find_nsec3(&nsec3, &rdataset, nsec3param);
 789			dns_rdataset_disassociate(&rdataset);
 790			if (result == ISC_R_SUCCESS) {
 791				dns_db_detachnode(db, &newnode);
 792				break;
 793			}
 794			if (result != ISC_R_NOMORE)
 795				goto failure;
 796		}
 797
 798		/*
 799		 * Find the previous NSEC3 and update it.
 800		 */
 801		CHECK(dns_dbiterator_seek(dbit, hashname));
 802		pass = 0;
 803		do {
 804			result = dns_dbiterator_prev(dbit);
 805			if (result == ISC_R_NOMORE) {
 806				pass++;
 807				CHECK(dns_dbiterator_last(dbit));
 808			}
 809			CHECK(dns_dbiterator_current(dbit, &node, prev));
 810			CHECK(dns_dbiterator_pause(dbit));
 811			result = dns_db_findrdataset(db, node, version,
 812						     dns_rdatatype_nsec3, 0,
 813						     (isc_stdtime_t) 0,
 814						     &rdataset, NULL);
 815			dns_db_detachnode(db, &node);
 816			if (result != ISC_R_SUCCESS)
 817				continue;
 818			result = find_nsec3(&nsec3, &rdataset, nsec3param);
 819			if (result == ISC_R_NOMORE) {
 820				dns_rdataset_disassociate(&rdataset);
 821				continue;
 822			}
 823			if (result != ISC_R_SUCCESS)
 824				goto failure;
 825
 826			old_next = nsec3.next;
 827			old_length = nsec3.next_length;
 828
 829			/*
 830			 * Delete the old previous NSEC3.
 831			 */
 832			CHECK(delete(db, version, prev, nsec3param, diff));
 833
 834			/*
 835			 * Fixup the previous NSEC3.
 836			 */
 837			nsec3.next = nexthash;
 838			nsec3.next_length = next_length;
 839			isc_buffer_init(&buffer, nsec3buf,
 840					sizeof(nsec3buf));
 841			CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
 842						   dns_rdatatype_nsec3, &nsec3,
 843						   &buffer));
 844			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
 845						   prev, rdataset.ttl, &rdata,
 846						   &tuple));
 847			CHECK(do_one_tuple(&tuple, db, version, diff));
 848			INSIST(old_length <= sizeof(nexthash));
 849			memcpy(nexthash, old_next, old_length);
 850			if (!CREATE(nsec3param->flags))
 851				flags = nsec3.flags;
 852			dns_rdata_reset(&rdata);
 853			dns_rdataset_disassociate(&rdataset);
 854			break;
 855		} while (pass < 2);
 856
 857		INSIST(pass < 2);
 858
 859		/*
 860		 * Create the NSEC3 RDATA for the empty node.
 861		 */
 862		CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
 863					   iterations, salt, salt_length,
 864					   nexthash, next_length, nsec3buf,
 865					   &rdata));
 866		/*
 867		 * Delete the old NSEC3 and record the change.
 868		 */
 869		CHECK(delete(db, version, hashname, nsec3param, diff));
 870
 871		/*
 872		 * Add the new NSEC3 and record the change.
 873		 */
 874		CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
 875					   hashname, nsecttl, &rdata, &tuple));
 876		CHECK(do_one_tuple(&tuple, db, version, diff));
 877		INSIST(tuple == NULL);
 878		dns_rdata_reset(&rdata);
 879		dns_db_detachnode(db, &newnode);
 880	} while (1);
 881
 882	if (result == ISC_R_NOMORE)
 883		result = ISC_R_SUCCESS;
 884
 885 failure:
 886	if (dbit != NULL)
 887		dns_dbiterator_destroy(&dbit);
 888	if (dns_rdataset_isassociated(&rdataset))
 889		dns_rdataset_disassociate(&rdataset);
 890	if (node != NULL)
 891		dns_db_detachnode(db, &node);
 892	if (newnode != NULL)
 893		dns_db_detachnode(db, &newnode);
 894	return (result);
 895}
 896
 897/*%
 898 * Add NSEC3 records for "name", recording the change in "diff".
 899 * The existing NSEC3 records are removed.
 900 */
 901isc_result_t
 902dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
 903		    dns_name_t *name, dns_ttl_t nsecttl,
 904		    isc_boolean_t unsecure, dns_diff_t *diff)
 905{
 906	dns_dbnode_t *node = NULL;
 907	dns_rdata_nsec3param_t nsec3param;
 908	dns_rdataset_t rdataset;
 909	isc_result_t result;
 910
 911	dns_rdataset_init(&rdataset);
 912
 913	/*
 914	 * Find the NSEC3 parameters for this zone.
 915	 */
 916	result = dns_db_getoriginnode(db, &node);
 917	if (result != ISC_R_SUCCESS)
 918		return (result);
 919
 920	result = dns_db_findrdataset(db, node, version,
 921				     dns_rdatatype_nsec3param, 0, 0,
 922				     &rdataset, NULL);
 923	dns_db_detachnode(db, &node);
 924	if (result == ISC_R_NOTFOUND)
 925		return (ISC_R_SUCCESS);
 926	if (result != ISC_R_SUCCESS)
 927		return (result);
 928
 929	/*
 930	 * Update each active NSEC3 chain.
 931	 */
 932	for (result = dns_rdataset_first(&rdataset);
 933	     result == ISC_R_SUCCESS;
 934	     result = dns_rdataset_next(&rdataset)) {
 935		dns_rdata_t rdata = DNS_RDATA_INIT;
 936
 937		dns_rdataset_current(&rdataset, &rdata);
 938		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
 939
 940		if (nsec3param.flags != 0)
 941			continue;
 942		/*
 943		 * We have a active chain.  Update it.
 944		 */
 945		CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
 946					 nsecttl, unsecure, diff));
 947	}
 948	if (result == ISC_R_NOMORE)
 949		result = ISC_R_SUCCESS;
 950
 951 failure:
 952	if (dns_rdataset_isassociated(&rdataset))
 953		dns_rdataset_disassociate(&rdataset);
 954	if (node != NULL)
 955		dns_db_detachnode(db, &node);
 956
 957	return (result);
 958}
 959
 960isc_boolean_t
 961dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
 962			   unsigned char *buf, size_t buflen)
 963{
 964	dns_decompress_t dctx;
 965	isc_result_t result;
 966	isc_buffer_t buf1;
 967	isc_buffer_t buf2;
 968
 969	/*
 970	 * Algorithm 0 (reserved by RFC 4034) is used to identify
 971	 * NSEC3PARAM records from DNSKEY pointers.
 972	 */
 973	if (src->length < 1 || src->data[0] != 0)
 974		return (ISC_FALSE);
 975
 976	isc_buffer_init(&buf1, src->data + 1, src->length - 1);
 977	isc_buffer_add(&buf1, src->length - 1);
 978	isc_buffer_setactive(&buf1, src->length - 1);
 979	isc_buffer_init(&buf2, buf, buflen);
 980	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
 981	result = dns_rdata_fromwire(target, src->rdclass,
 982				    dns_rdatatype_nsec3param,
 983				    &buf1, &dctx, 0, &buf2);
 984	dns_decompress_invalidate(&dctx);
 985
 986	return (ISC_TF(result == ISC_R_SUCCESS));
 987}
 988
 989void
 990dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
 991			 dns_rdatatype_t privatetype,
 992			 unsigned char *buf, size_t buflen)
 993{
 994	REQUIRE(buflen >= src->length + 1);
 995
 996	REQUIRE(DNS_RDATA_INITIALIZED(target));
 997
 998	memcpy(buf + 1, src->data, src->length);
 999	buf[0] = 0;
1000	target->data = buf;
1001	target->length = src->length + 1;
1002	target->type = privatetype;
1003	target->rdclass = src->rdclass;
1004	target->flags = 0;
1005	ISC_LINK_INIT(target, link);
1006}
1007
1008#ifdef BIND9
1009static isc_result_t
1010rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1011	  const dns_rdata_t *rdata, isc_boolean_t *flag)
1012{
1013	dns_rdataset_t rdataset;
1014	dns_dbnode_t *node = NULL;
1015	isc_result_t result;
1016
1017	dns_rdataset_init(&rdataset);
1018	if (rdata->type == dns_rdatatype_nsec3)
1019		CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
1020	else
1021		CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
1022	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
1023				     (isc_stdtime_t) 0, &rdataset, NULL);
1024	if (result == ISC_R_NOTFOUND) {
1025		*flag = ISC_FALSE;
1026		result = ISC_R_SUCCESS;
1027		goto failure;
1028	}
1029
1030	for (result = dns_rdataset_first(&rdataset);
1031	     result == ISC_R_SUCCESS;
1032	     result = dns_rdataset_next(&rdataset)) {
1033		dns_rdata_t myrdata = DNS_RDATA_INIT;
1034		dns_rdataset_current(&rdataset, &myrdata);
1035		if (!dns_rdata_casecompare(&myrdata, rdata))
1036			break;
1037	}
1038	dns_rdataset_disassociate(&rdataset);
1039	if (result == ISC_R_SUCCESS) {
1040		*flag = ISC_TRUE;
1041	} else if (result == ISC_R_NOMORE) {
1042		*flag = ISC_FALSE;
1043		result = ISC_R_SUCCESS;
1044	}
1045
1046 failure:
1047	if (node != NULL)
1048		dns_db_detachnode(db, &node);
1049	return (result);
1050}
1051#endif
1052
1053#ifdef BIND9
1054isc_result_t
1055dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
1056			    dns_zone_t *zone, dns_diff_t *diff)
1057{
1058	dns_dbnode_t *node = NULL;
1059	dns_difftuple_t *tuple = NULL;
1060	dns_name_t next;
1061	dns_rdata_t rdata = DNS_RDATA_INIT;
1062	dns_rdataset_t rdataset;
1063	isc_boolean_t flag;
1064	isc_result_t result = ISC_R_SUCCESS;
1065	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1066	dns_name_t *origin = dns_zone_getorigin(zone);
1067	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
1068
1069	dns_name_init(&next, NULL);
1070	dns_rdataset_init(&rdataset);
1071
1072	result = dns_db_getoriginnode(db, &node);
1073	if (result != ISC_R_SUCCESS)
1074		return (result);
1075
1076	/*
1077	 * Cause all NSEC3 chains to be deleted.
1078	 */
1079	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
1080				     0, (isc_stdtime_t) 0, &rdataset, NULL);
1081	if (result == ISC_R_NOTFOUND)
1082		goto try_private;
1083	if (result != ISC_R_SUCCESS)
1084		goto failure;
1085
1086	for (result = dns_rdataset_first(&rdataset);
1087	     result == ISC_R_SUCCESS;
1088	     result = dns_rdataset_next(&rdataset)) {
1089		dns_rdata_t private = DNS_RDATA_INIT;
1090
1091		dns_rdataset_current(&rdataset, &rdata);
1092
1093		CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
1094					   rdataset.ttl, &rdata, &tuple));
1095		CHECK(do_one_tuple(&tuple, db, ver, diff));
1096		INSIST(tuple == NULL);
1097
1098		dns_nsec3param_toprivate(&rdata, &private, privatetype,
1099					 buf, sizeof(buf));
1100		buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
1101
1102		CHECK(rr_exists(db, ver, origin, &private, &flag));
1103
1104		if (!flag) {
1105			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
1106						   origin, 0, &private,
1107						   &tuple));
1108			CHECK(do_one_tuple(&tuple, db, ver, diff));
1109			INSIST(tuple == NULL);
1110		}
1111		dns_rdata_reset(&rdata);
1112	}
1113	if (result != ISC_R_NOMORE)
1114		goto failure;
1115
1116	dns_rdataset_disassociate(&rdataset);
1117
1118 try_private:
1119	if (privatetype == 0)
1120		goto success;
1121	result = dns_db_findrdataset(db, node, ver, privatetype, 0,
1122				     (isc_stdtime_t) 0, &rdataset, NULL);
1123	if (result == ISC_R_NOTFOUND)
1124		goto success;
1125	if (result != ISC_R_SUCCESS)
1126		goto failure;
1127
1128	for (result = dns_rdataset_first(&rdataset);
1129	     result == ISC_R_SUCCESS;
1130	     result = dns_rdataset_next(&rdataset)) {
1131		dns_rdataset_current(&rdataset, &rdata);
1132		INSIST(rdata.length <= sizeof(buf));
1133		memcpy(buf, rdata.data, rdata.length);
1134
1135		if (buf[0] != 0 ||
1136		    buf[2] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) {
1137			dns_rdata_reset(&rdata);
1138			continue;
1139		}
1140
1141		CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
1142					   0, &rdata, &tuple));
1143		CHECK(do_one_tuple(&tuple, db, ver, diff));
1144		INSIST(tuple == NULL);
1145
1146		rdata.data = buf;
1147		buf[2] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC;
1148
1149		CHECK(rr_exists(db, ver, origin, &rdata, &flag));
1150
1151		if (!flag) {
1152			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
1153						   origin, 0, &rdata, &tuple));
1154			CHECK(do_one_tuple(&tuple, db, ver, diff));
1155			INSIST(tuple == NULL);
1156		}
1157		dns_rdata_reset(&rdata);
1158	}
1159	if (result != ISC_R_NOMORE)
1160		goto failure;
1161 success:
1162	result = ISC_R_SUCCESS;
1163
1164 failure:
1165	if (dns_rdataset_isassociated(&rdataset))
1166		dns_rdataset_disassociate(&rdataset);
1167	dns_db_detachnode(db, &node);
1168	return (result);
1169}
1170#endif
1171
1172isc_result_t
1173dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version,
1174		     dns_name_t *name, dns_ttl_t nsecttl,
1175		     isc_boolean_t unsecure, dns_rdatatype_t type,
1176		     dns_diff_t *diff)
1177{
1178	dns_dbnode_t *node = NULL;
1179	dns_rdata_nsec3param_t nsec3param;
1180	dns_rdataset_t rdataset;
1181	dns_rdataset_t prdataset;
1182	isc_result_t result;
1183
1184	dns_rdataset_init(&rdataset);
1185	dns_rdataset_init(&prdataset);
1186
1187	/*
1188	 * Find the NSEC3 parameters for this zone.
1189	 */
1190	result = dns_db_getoriginnode(db, &node);
1191	if (result != ISC_R_SUCCESS)
1192		return (result);
1193
1194	result = dns_db_findrdataset(db, node, version, type, 0, 0,
1195				     &prdataset, NULL);
1196	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1197		goto failure;
1198
1199	result = dns_db_findrdataset(db, node, version,
1200				     dns_rdatatype_nsec3param, 0, 0,
1201				     &rdataset, NULL);
1202	if (result == ISC_R_NOTFOUND)
1203		goto try_private;
1204	if (result != ISC_R_SUCCESS)
1205		goto failure;
1206
1207	/*
1208	 * Update each active NSEC3 chain.
1209	 */
1210	for (result = dns_rdataset_first(&rdataset);
1211	     result == ISC_R_SUCCESS;
1212	     result = dns_rdataset_next(&rdataset)) {
1213		dns_rdata_t rdata = DNS_RDATA_INIT;
1214
1215		dns_rdataset_current(&rdataset, &rdata);
1216		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
1217
1218		if (nsec3param.flags != 0)
1219			continue;
1220
1221		/*
1222		 * We have a active chain.  Update it.
1223		 */
1224		CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
1225					 nsecttl, unsecure, diff));
1226	}
1227	if (result != ISC_R_NOMORE)
1228		goto failure;
1229
1230	dns_rdataset_disassociate(&rdataset);
1231
1232 try_private:
1233	if (!dns_rdataset_isassociated(&prdataset))
1234		goto success;
1235	/*
1236	 * Update each active NSEC3 chain.
1237	 */
1238	for (result = dns_rdataset_first(&prdataset);
1239	     result == ISC_R_SUCCESS;
1240	     result = dns_rdataset_next(&prdataset)) {
1241		dns_rdata_t rdata1 = DNS_RDATA_INIT;
1242		dns_rdata_t rdata2 = DNS_RDATA_INIT;
1243		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1244
1245		dns_rdataset_current(&prdataset, &rdata1);
1246		if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
1247						buf, sizeof(buf)))
1248			continue;
1249		CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
1250
1251		if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
1252			continue;
1253		if (better_param(&prdataset, &rdata2))
1254			continue;
1255
1256		/*
1257		 * We have a active chain.  Update it.
1258		 */
1259		CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
1260					 nsecttl, unsecure, diff));
1261	}
1262	if (result == ISC_R_NOMORE)
1263 success:
1264		result = ISC_R_SUCCESS;
1265 failure:
1266	if (dns_rdataset_isassociated(&rdataset))
1267		dns_rdataset_disassociate(&rdataset);
1268	if (dns_rdataset_isassociated(&prdataset))
1269		dns_rdataset_disassociate(&prdataset);
1270	if (node != NULL)
1271		dns_db_detachnode(db, &node);
1272
1273	return (result);
1274}
1275
1276/*%
1277 * Determine whether any NSEC3 records that were associated with
1278 * 'name' should be deleted or if they should continue to exist.
1279 * ISC_TRUE indicates they should be deleted.
1280 * ISC_FALSE indicates they should be retained.
1281 */
1282static isc_result_t
1283deleteit(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1284	 isc_boolean_t *yesno)
1285{
1286	isc_result_t result;
1287	dns_fixedname_t foundname;
1288	dns_fixedname_init(&foundname);
1289
1290	result = dns_db_find(db, name, ver, dns_rdatatype_any,
1291			     DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
1292			     (isc_stdtime_t) 0, NULL,
1293			     dns_fixedname_name(&foundname),
1294			     NULL, NULL);
1295	if (result == DNS_R_EMPTYNAME || result == ISC_R_SUCCESS ||
1296	    result ==  DNS_R_ZONECUT) {
1297		*yesno = ISC_FALSE;
1298		return (ISC_R_SUCCESS);
1299	}
1300	if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
1301	    result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
1302		*yesno = ISC_TRUE;
1303		return (ISC_R_SUCCESS);
1304	}
1305	/*
1306	 * Silence compiler.
1307	 */
1308	*yesno = ISC_TRUE;
1309	return (result);
1310}
1311
1312isc_result_t
1313dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1314		   const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
1315{
1316	dns_dbiterator_t *dbit = NULL;
1317	dns_dbnode_t *node = NULL;
1318	dns_difftuple_t *tuple = NULL;
1319	dns_fixedname_t fixed;
1320	dns_fixedname_t fprev;
1321	dns_hash_t hash;
1322	dns_name_t *hashname;
1323	dns_name_t *origin;
1324	dns_name_t *prev;
1325	dns_name_t empty;
1326	dns_rdata_nsec3_t nsec3;
1327	dns_rdata_t rdata = DNS_RDATA_INIT;
1328	dns_rdataset_t rdataset;
1329	int pass;
1330	isc_boolean_t yesno;
1331	isc_buffer_t buffer;
1332	isc_result_t result;
1333	unsigned char *salt;
1334	unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
1335	unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
1336	unsigned int iterations;
1337	unsigned int labels;
1338	size_t next_length;
1339	unsigned int salt_length;
1340
1341	dns_fixedname_init(&fixed);
1342	hashname = dns_fixedname_name(&fixed);
1343	dns_fixedname_init(&fprev);
1344	prev = dns_fixedname_name(&fprev);
1345
1346	dns_rdataset_init(&rdataset);
1347
1348	origin = dns_db_origin(db);
1349
1350	/*
1351	 * Chain parameters.
1352	 */
1353	hash = nsec3param->hash;
1354	iterations = nsec3param->iterations;
1355	salt_length = nsec3param->salt_length;
1356	salt = nsec3param->salt;
1357
1358	/*
1359	 * If this is the first NSEC3 in the chain nexthash will
1360	 * remain pointing to itself.
1361	 */
1362	next_length = sizeof(nexthash);
1363	CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1364				 name, origin, hash, iterations,
1365				 salt, salt_length));
1366
1367	CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
1368
1369	result = dns_dbiterator_seek(dbit, hashname);
1370	if (result == ISC_R_NOTFOUND)
1371		goto success;
1372	if (result != ISC_R_SUCCESS)
1373		goto failure;
1374
1375	CHECK(dns_dbiterator_current(dbit, &node, NULL));
1376	CHECK(dns_dbiterator_pause(dbit));
1377	result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
1378				     0, (isc_stdtime_t) 0, &rdataset, NULL);
1379	dns_db_detachnode(db, &node);
1380	if (result == ISC_R_NOTFOUND)
1381		goto success;
1382	if (result != ISC_R_SUCCESS)
1383		goto failure;
1384
1385	/*
1386	 * If we find a existing NSEC3 for this chain then save the
1387	 * next field.
1388	 */
1389	result = find_nsec3(&nsec3, &rdataset, nsec3param);
1390	if (result == ISC_R_SUCCESS) {
1391		next_length = nsec3.next_length;
1392		INSIST(next_length <= sizeof(nexthash));
1393		memcpy(nexthash, nsec3.next, next_length);
1394	}
1395	dns_rdataset_disassociate(&rdataset);
1396	if (result == ISC_R_NOMORE)
1397		goto success;
1398	if (result != ISC_R_SUCCESS)
1399		goto failure;
1400
1401	/*
1402	 * Find the previous NSEC3 and update it.
1403	 */
1404	pass = 0;
1405	do {
1406		result = dns_dbiterator_prev(dbit);
1407		if (result == ISC_R_NOMORE) {
1408			pass++;
1409			CHECK(dns_dbiterator_last(dbit));
1410		}
1411		CHECK(dns_dbiterator_current(dbit, &node, prev));
1412		CHECK(dns_dbiterator_pause(dbit));
1413		result = dns_db_findrdataset(db, node, version,
1414					     dns_rdatatype_nsec3, 0,
1415					     (isc_stdtime_t) 0, &rdataset,
1416					     NULL);
1417		dns_db_detachnode(db, &node);
1418		if (result != ISC_R_SUCCESS)
1419			continue;
1420		result = find_nsec3(&nsec3, &rdataset, nsec3param);
1421		if (result == ISC_R_NOMORE) {
1422			dns_rdataset_disassociate(&rdataset);
1423			continue;
1424		}
1425		if (result != ISC_R_SUCCESS)
1426			goto failure;
1427
1428		/*
1429		 * Delete the old previous NSEC3.
1430		 */
1431		CHECK(delete(db, version, prev, nsec3param, diff));
1432
1433		/*
1434		 * Fixup the previous NSEC3.
1435		 */
1436		nsec3.next = nexthash;
1437		nsec3.next_length = next_length;
1438		if (CREATE(nsec3param->flags))
1439			nsec3.flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
1440		isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
1441		CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1442					   dns_rdatatype_nsec3, &nsec3,
1443					   &buffer));
1444		CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
1445					   rdataset.ttl, &rdata, &tuple));
1446		CHECK(do_one_tuple(&tuple, db, version, diff));
1447		dns_rdata_reset(&rdata);
1448		dns_rdataset_disassociate(&rdataset);
1449		break;
1450	} while (pass < 2);
1451
1452	/*
1453	 * Delete the old NSEC3 and record the change.
1454	 */
1455	CHECK(delete(db, version, hashname, nsec3param, diff));
1456
1457	/*
1458	 *  Delete NSEC3 records for now non active nodes.
1459	 */
1460	dns_name_init(&empty, NULL);
1461	dns_name_clone(name, &empty);
1462	do {
1463		labels = dns_name_countlabels(&empty) - 1;
1464		if (labels <= dns_name_countlabels(origin))
1465			break;
1466		dns_name_getlabelsequence(&empty, 1, labels, &empty);
1467		CHECK(deleteit(db, version, &empty, &yesno));
1468		if (!yesno)
1469			break;
1470
1471		CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1472					 &empty, origin, hash, iterations,
1473					 salt, salt_length));
1474		result = dns_dbiterator_seek(dbit, hashname);
1475		if (result == ISC_R_NOTFOUND)
1476			goto success;
1477		if (result != ISC_R_SUCCESS)
1478			goto failure;
1479
1480		CHECK(dns_dbiterator_current(dbit, &node, NULL));
1481		CHECK(dns_dbiterator_pause(dbit));
1482		result = dns_db_findrdataset(db, node, version,
1483					     dns_rdatatype_nsec3, 0,
1484					     (isc_stdtime_t) 0, &rdataset,
1485					     NULL);
1486		dns_db_detachnode(db, &node);
1487		if (result == ISC_R_NOTFOUND)
1488			goto success;
1489		if (result != ISC_R_SUCCESS)
1490			goto failure;
1491
1492		result = find_nsec3(&nsec3, &rdataset, nsec3param);
1493		if (result == ISC_R_SUCCESS) {
1494			next_length = nsec3.next_length;
1495			INSIST(next_length <= sizeof(nexthash));
1496			memcpy(nexthash, nsec3.next, next_length);
1497		}
1498		dns_rdataset_disassociate(&rdataset);
1499		if (result == ISC_R_NOMORE)
1500			goto success;
1501		if (result != ISC_R_SUCCESS)
1502			goto failure;
1503
1504		pass = 0;
1505		do {
1506			result = dns_dbiterator_prev(dbit);
1507			if (result == ISC_R_NOMORE) {
1508				pass++;
1509				CHECK(dns_dbiterator_last(dbit));
1510			}
1511			CHECK(dns_dbiterator_current(dbit, &node, prev));
1512			CHECK(dns_dbiterator_pause(dbit));
1513			result = dns_db_findrdataset(db, node, version,
1514						     dns_rdatatype_nsec3, 0,
1515						     (isc_stdtime_t) 0,
1516						     &rdataset, NULL);
1517			dns_db_detachnode(db, &node);
1518			if (result != ISC_R_SUCCESS)
1519				continue;
1520			result = find_nsec3(&nsec3, &rdataset, nsec3param);
1521			if (result == ISC_R_NOMORE) {
1522				dns_rdataset_disassociate(&rdataset);
1523				continue;
1524			}
1525			if (result != ISC_R_SUCCESS)
1526				goto failure;
1527
1528			/*
1529			 * Delete the old previous NSEC3.
1530			 */
1531			CHECK(delete(db, version, prev, nsec3param, diff));
1532
1533			/*
1534			 * Fixup the previous NSEC3.
1535			 */
1536			nsec3.next = nexthash;
1537			nsec3.next_length = next_length;
1538			isc_buffer_init(&buffer, nsec3buf,
1539					sizeof(nsec3buf));
1540			CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1541						   dns_rdatatype_nsec3, &nsec3,
1542						   &buffer));
1543			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
1544						   prev, rdataset.ttl, &rdata,
1545						   &tuple));
1546			CHECK(do_one_tuple(&tuple, db, version, diff));
1547			dns_rdata_reset(&rdata);
1548			dns_rdataset_disassociate(&rdataset);
1549			break;
1550		} while (pass < 2);
1551
1552		INSIST(pass < 2);
1553
1554		/*
1555		 * Delete the old NSEC3 and record the change.
1556		 */
1557		CHECK(delete(db, version, hashname, nsec3param, diff));
1558	} while (1);
1559
1560 success:
1561	result = ISC_R_SUCCESS;
1562
1563 failure:
1564	if (dbit != NULL)
1565		dns_dbiterator_destroy(&dbit);
1566	if (dns_rdataset_isassociated(&rdataset))
1567		dns_rdataset_disassociate(&rdataset);
1568	if (node != NULL)
1569		dns_db_detachnode(db, &node);
1570	return (result);
1571}
1572
1573isc_result_t
1574dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1575		    dns_diff_t *diff)
1576{
1577	return (dns_nsec3_delnsec3sx(db, version, name, 0, diff));
1578}
1579
1580isc_result_t
1581dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1582		     dns_rdatatype_t privatetype, dns_diff_t *diff)
1583{
1584	dns_dbnode_t *node = NULL;
1585	dns_rdata_nsec3param_t nsec3param;
1586	dns_rdataset_t rdataset;
1587	isc_result_t result;
1588
1589	dns_rdataset_init(&rdataset);
1590
1591	/*
1592	 * Find the NSEC3 parameters for this zone.
1593	 */
1594	result = dns_db_getoriginnode(db, &node);
1595	if (result != ISC_R_SUCCESS)
1596		return (result);
1597
1598	result = dns_db_findrdataset(db, node, version,
1599				     dns_rdatatype_nsec3param, 0, 0,
1600				     &rdataset, NULL);
1601	if (result == ISC_R_NOTFOUND)
1602		goto try_private;
1603	if (result != ISC_R_SUCCESS)
1604		goto failure;
1605
1606	/*
1607	 * Update each active NSEC3 chain.
1608	 */
1609	for (result = dns_rdataset_first(&rdataset);
1610	     result == ISC_R_SUCCESS;
1611	     result = dns_rdataset_next(&rdataset)) {
1612		dns_rdata_t rdata = DNS_RDATA_INIT;
1613
1614		dns_rdataset_current(&rdataset, &rdata);
1615		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
1616
1617		if (nsec3param.flags != 0)
1618			continue;
1619		/*
1620		 * We have a active chain.  Update it.
1621		 */
1622		CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1623	}
1624	dns_rdataset_disassociate(&rdataset);
1625
1626 try_private:
1627	if (privatetype == 0)
1628		goto success;
1629	result = dns_db_findrdataset(db, node, version, privatetype, 0, 0,
1630				     &rdataset, NULL);
1631	if (result == ISC_R_NOTFOUND)
1632		goto success;
1633	if (result != ISC_R_SUCCESS)
1634		goto failure;
1635
1636	/*
1637	 * Update each NSEC3 chain being built.
1638	 */
1639	for (result = dns_rdataset_first(&rdataset);
1640	     result == ISC_R_SUCCESS;
1641	     result = dns_rdataset_next(&rdataset)) {
1642		dns_rdata_t rdata1 = DNS_RDATA_INIT;
1643		dns_rdata_t rdata2 = DNS_RDATA_INIT;
1644		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1645
1646		dns_rdataset_current(&rdataset, &rdata1);
1647		if (!dns_nsec3param_fromprivate(&rdata1,  &rdata2,
1648						buf, sizeof(buf)))
1649			continue;
1650		CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
1651
1652		if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
1653			continue;
1654		if (better_param(&rdataset, &rdata2))
1655			continue;
1656
1657		/*
1658		 * We have a active chain.  Update it.
1659		 */
1660		CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1661	}
1662	if (result == ISC_R_NOMORE)
1663 success:
1664		result = ISC_R_SUCCESS;
1665
1666 failure:
1667	if (dns_rdataset_isassociated(&rdataset))
1668		dns_rdataset_disassociate(&rdataset);
1669	if (node != NULL)
1670		dns_db_detachnode(db, &node);
1671
1672	return (result);
1673}
1674
1675isc_result_t
1676dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
1677		 isc_boolean_t complete, isc_boolean_t *answer)
1678{
1679	return (dns_nsec3_activex(db, version, complete, 0, answer));
1680}
1681
1682isc_result_t
1683dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version,
1684		  isc_boolean_t complete, dns_rdatatype_t privatetype,
1685		  isc_boolean_t *answer)
1686{
1687	dns_dbnode_t *node = NULL;
1688	dns_rdataset_t rdataset;
1689	dns_rdata_nsec3param_t nsec3param;
1690	isc_result_t result;
1691
1692	REQUIRE(answer != NULL);
1693
1694	dns_rdataset_init(&rdataset);
1695
1696	result = dns_db_getoriginnode(db, &node);
1697	if (result != ISC_R_SUCCESS)
1698		return (result);
1699
1700	result = dns_db_findrdataset(db, node, version,
1701				     dns_rdatatype_nsec3param, 0, 0,
1702				     &rdataset, NULL);
1703
1704	if (result == ISC_R_NOTFOUND)
1705		goto try_private;
1706
1707	if (result != ISC_R_SUCCESS) {
1708		dns_db_detachnode(db, &node);
1709		return (result);
1710	}
1711	for (result = dns_rdataset_first(&rdataset);
1712	     result == ISC_R_SUCCESS;
1713	     result = dns_rdataset_next(&rdataset)) {
1714		dns_rdata_t rdata = DNS_RDATA_INIT;
1715
1716		dns_rdataset_current(&rdataset, &rdata);
1717		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1718		RUNTIME_CHECK(result == ISC_R_SUCCESS);
1719
1720		if (nsec3param.flags == 0)
1721			break;
1722	}
1723	dns_rdataset_disassociate(&rdataset);
1724	if (result == ISC_R_SUCCESS) {
1725		dns_db_detachnode(db, &node);
1726		*answer = ISC_TRUE;
1727		return (ISC_R_SUCCESS);
1728	}
1729	if (result == ISC_R_NOMORE)
1730		*answer = ISC_FALSE;
1731
1732 try_private:
1733	if (privatetype == 0 || complete) {
1734		*answer = ISC_FALSE;
1735		return (ISC_R_SUCCESS);
1736	}
1737	result = dns_db_findrdataset(db, node, version, privatetype, 0, 0,
1738				     &rdataset, NULL);
1739
1740	dns_db_detachnode(db, &node);
1741	if (result == ISC_R_NOTFOUND) {
1742		*answer = ISC_FALSE;
1743		return (ISC_R_SUCCESS);
1744	}
1745	if (result != ISC_R_SUCCESS)
1746		return (result);
1747
1748	for (result = dns_rdataset_first(&rdataset);
1749	     result == ISC_R_SUCCESS;
1750	     result = dns_rdataset_next(&rdataset)) {
1751		dns_rdata_t rdata1 = DNS_RDATA_INIT;
1752		dns_rdata_t rdata2 = DNS_RDATA_INIT;
1753		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1754
1755		dns_rdataset_current(&rdataset, &rdata1);
1756		if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
1757						buf, sizeof(buf)))
1758			continue;
1759		result = dns_rdata_tostruct(&rdata2, &nsec3param, NULL);
1760		RUNTIME_CHECK(result == ISC_R_SUCCESS);
1761
1762		if (!complete && CREATE(nsec3param.flags))
1763			break;
1764	}
1765	dns_rdataset_disassociate(&rdataset);
1766	if (result == ISC_R_SUCCESS) {
1767		*answer = ISC_TRUE;
1768		result = ISC_R_SUCCESS;
1769	}
1770	if (result == ISC_R_NOMORE) {
1771		*answer = ISC_FALSE;
1772		result = ISC_R_SUCCESS;
1773	}
1774
1775	return (result);
1776}
1777
1778isc_result_t
1779dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
1780			isc_mem_t *mctx, unsigned int *iterationsp)
1781{
1782	dns_dbnode_t *node = NULL;
1783	dns_rdataset_t rdataset;
1784	dst_key_t *key = NULL;
1785	isc_buffer_t buffer;
1786	isc_result_t result;
1787	unsigned int bits, minbits = 4096;
1788
1789	result = dns_db_getoriginnode(db, &node);
1790	if (result != ISC_R_SUCCESS)
1791		return (result);
1792
1793	dns_rdataset_init(&rdataset);
1794	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
1795				     0, 0, &rdataset, NULL);
1796	dns_db_detachnode(db, &node);
1797	if (result == ISC_R_NOTFOUND) {
1798		*iterationsp = 0;
1799		return (ISC_R_SUCCESS);
1800	}
1801	if (result != ISC_R_SUCCESS)
1802		goto failure;
1803
1804	for (result = dns_rdataset_first(&rdataset);
1805	     result == ISC_R_SUCCESS;
1806	     result = dns_rdataset_next(&rdataset)) {
1807		dns_rdata_t rdata = DNS_RDATA_INIT;
1808
1809		dns_rdataset_current(&rdataset, &rdata);
1810		isc_buffer_init(&buffer, rdata.data, rdata.length);
1811		isc_buffer_add(&buffer, rdata.length);
1812		CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
1813				      &buffer, mctx, &key));
1814		bits = dst_key_size(key);
1815		dst_key_free(&key);
1816		if (minbits > bits)
1817			minbits = bits;
1818	}
1819	if (result != ISC_R_NOMORE)
1820		goto failure;
1821
1822	if (minbits <= 1024)
1823		*iterationsp = 150;
1824	else if (minbits <= 2048)
1825		*iterationsp = 500;
1826	else
1827		*iterationsp = 2500;
1828	result = ISC_R_SUCCESS;
1829
1830 failure:
1831	if (dns_rdataset_isassociated(&rdataset))
1832		dns_rdataset_disassociate(&rdataset);
1833	return (result);
1834}