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