]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/bind9/lib/dns/nsec3.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / bind9 / lib / dns / nsec3.c
1 /*
2  * Copyright (C) 2006, 2008, 2009  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: nsec3.c,v 1.6.12.4 2009/11/03 23:47:46 tbox Exp $ */
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/dbiterator.h>
32 #include <dns/diff.h>
33 #include <dns/fixedname.h>
34 #include <dns/nsec3.h>
35 #include <dns/rdata.h>
36 #include <dns/rdatalist.h>
37 #include <dns/rdataset.h>
38 #include <dns/rdatasetiter.h>
39 #include <dns/rdatastruct.h>
40 #include <dns/result.h>
41
42 #define CHECK(x) do { \
43         result = (x); \
44         if (result != ISC_R_SUCCESS) \
45                 goto failure; \
46         } while (0)
47
48 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
49 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
50 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
51
52 static void
53 set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
54         unsigned int shift, mask;
55
56         shift = 7 - (index % 8);
57         mask = 1 << shift;
58
59         if (bit != 0)
60                 array[index / 8] |= mask;
61         else
62                 array[index / 8] &= (~mask & 0xFF);
63 }
64
65 static unsigned int
66 bit_isset(unsigned char *array, unsigned int index) {
67         unsigned int byte, shift, mask;
68
69         byte = array[index / 8];
70         shift = 7 - (index % 8);
71         mask = 1 << shift;
72
73         return ((byte & mask) != 0);
74 }
75
76 isc_result_t
77 dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
78                      dns_dbnode_t *node, unsigned int hashalg,
79                      unsigned int flags, unsigned int iterations,
80                      const unsigned char *salt, size_t salt_length,
81                      const unsigned char *nexthash, size_t hash_length,
82                      unsigned char *buffer, dns_rdata_t *rdata)
83 {
84         isc_result_t result;
85         dns_rdataset_t rdataset;
86         isc_region_t r;
87         unsigned int i, window;
88         int octet;
89         isc_boolean_t found;
90         isc_boolean_t found_ns;
91         isc_boolean_t need_rrsig;
92
93         unsigned char *nsec_bits, *bm;
94         unsigned int max_type;
95         dns_rdatasetiter_t *rdsiter;
96         unsigned char *p;
97
98         REQUIRE(salt_length < 256U);
99         REQUIRE(hash_length < 256U);
100         REQUIRE(flags <= 0xffU);
101         REQUIRE(hashalg <= 0xffU);
102         REQUIRE(iterations <= 0xffffU);
103
104         switch (hashalg) {
105         case dns_hash_sha1:
106                 REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
107                 break;
108         }
109
110         memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
111
112         p = buffer;
113
114         *p++ = hashalg;
115         *p++ = flags;
116
117         *p++ = iterations >> 8;
118         *p++ = iterations;
119
120         *p++ = salt_length;
121         memcpy(p, salt, salt_length);
122         p += salt_length;
123
124         *p++ = hash_length;
125         memcpy(p, nexthash, hash_length);
126         p += hash_length;
127
128         r.length = p - buffer;
129         r.base = buffer;
130
131         /*
132          * Use the end of the space for a raw bitmap leaving enough
133          * space for the window identifiers and length octets.
134          */
135         bm = r.base + r.length + 512;
136         nsec_bits = r.base + r.length;
137         max_type = 0;
138         if (node == NULL)
139                 goto collapse_bitmap;
140         dns_rdataset_init(&rdataset);
141         rdsiter = NULL;
142         result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
143         if (result != ISC_R_SUCCESS)
144                 return (result);
145         found = found_ns = need_rrsig = ISC_FALSE;
146         for (result = dns_rdatasetiter_first(rdsiter);
147              result == ISC_R_SUCCESS;
148              result = dns_rdatasetiter_next(rdsiter))
149         {
150                 dns_rdatasetiter_current(rdsiter, &rdataset);
151                 if (rdataset.type != dns_rdatatype_nsec &&
152                     rdataset.type != dns_rdatatype_nsec3 &&
153                     rdataset.type != dns_rdatatype_rrsig) {
154                         if (rdataset.type > max_type)
155                                 max_type = rdataset.type;
156                         set_bit(bm, rdataset.type, 1);
157                         /*
158                          * Work out if we need to set the RRSIG bit for
159                          * this node.  We set the RRSIG bit if either of
160                          * the following conditions are met:
161                          * 1) We have a SOA or DS then we need to set
162                          *    the RRSIG bit as both always will be signed.
163                          * 2) We set the RRSIG bit if we don't have
164                          *    a NS record but do have other data.
165                          */
166                         if (rdataset.type == dns_rdatatype_soa ||
167                             rdataset.type == dns_rdatatype_ds)
168                                 need_rrsig = ISC_TRUE;
169                         else if (rdataset.type == dns_rdatatype_ns)
170                                 found_ns = ISC_TRUE;
171                         else
172                                 found = ISC_TRUE;
173                 }
174                 dns_rdataset_disassociate(&rdataset);
175         }
176         if ((found && !found_ns) || need_rrsig) {
177                 if (dns_rdatatype_rrsig > max_type)
178                         max_type = dns_rdatatype_rrsig;
179                 set_bit(bm, dns_rdatatype_rrsig, 1);
180         }
181
182         /*
183          * At zone cuts, deny the existence of glue in the parent zone.
184          */
185         if (bit_isset(bm, dns_rdatatype_ns) &&
186             ! bit_isset(bm, dns_rdatatype_soa)) {
187                 for (i = 0; i <= max_type; i++) {
188                         if (bit_isset(bm, i) &&
189                             ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
190                                 set_bit(bm, i, 0);
191                 }
192         }
193
194         dns_rdatasetiter_destroy(&rdsiter);
195         if (result != ISC_R_NOMORE)
196                 return (result);
197
198  collapse_bitmap:
199         for (window = 0; window < 256; window++) {
200                 if (window * 256 > max_type)
201                         break;
202                 for (octet = 31; octet >= 0; octet--)
203                         if (bm[window * 32 + octet] != 0)
204                                 break;
205                 if (octet < 0)
206                         continue;
207                 nsec_bits[0] = window;
208                 nsec_bits[1] = octet + 1;
209                 /*
210                  * Note: potentially overlapping move.
211                  */
212                 memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
213                 nsec_bits += 3 + octet;
214         }
215         r.length = nsec_bits - r.base;
216         INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
217         dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
218
219         return (ISC_R_SUCCESS);
220 }
221
222 isc_boolean_t
223 dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
224         dns_rdata_nsec3_t nsec3;
225         isc_result_t result;
226         isc_boolean_t present;
227         unsigned int i, len, window;
228
229         REQUIRE(rdata != NULL);
230         REQUIRE(rdata->type == dns_rdatatype_nsec3);
231
232         /* This should never fail */
233         result = dns_rdata_tostruct(rdata, &nsec3, NULL);
234         INSIST(result == ISC_R_SUCCESS);
235
236         present = ISC_FALSE;
237         for (i = 0; i < nsec3.len; i += len) {
238                 INSIST(i + 2 <= nsec3.len);
239                 window = nsec3.typebits[i];
240                 len = nsec3.typebits[i + 1];
241                 INSIST(len > 0 && len <= 32);
242                 i += 2;
243                 INSIST(i + len <= nsec3.len);
244                 if (window * 256 > type)
245                         break;
246                 if ((window + 1) * 256 <= type)
247                         continue;
248                 if (type < (window * 256) + len * 8)
249                         present = ISC_TF(bit_isset(&nsec3.typebits[i],
250                                                    type % 256));
251                 break;
252         }
253         dns_rdata_freestruct(&nsec3);
254         return (present);
255 }
256
257 isc_result_t
258 dns_nsec3_hashname(dns_fixedname_t *result,
259                    unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
260                    size_t *hash_length, dns_name_t *name, dns_name_t *origin,
261                    dns_hash_t hashalg, unsigned int iterations,
262                    const unsigned char *salt, size_t saltlength)
263 {
264         unsigned char hash[NSEC3_MAX_HASH_LENGTH];
265         unsigned char nametext[DNS_NAME_FORMATSIZE];
266         dns_fixedname_t fixed;
267         dns_name_t *downcased;
268         isc_buffer_t namebuffer;
269         isc_region_t region;
270         size_t len;
271
272         if (rethash == NULL)
273                 rethash = hash;
274
275         memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
276
277         dns_fixedname_init(&fixed);
278         downcased = dns_fixedname_name(&fixed);
279         dns_name_downcase(name, downcased, NULL);
280
281         /* hash the node name */
282         len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
283                                 downcased->ndata, downcased->length);
284         if (len == 0U)
285                 return (DNS_R_BADALG);
286
287         if (hash_length != NULL)
288                 *hash_length = len;
289
290         /* convert the hash to base32hex */
291         region.base = rethash;
292         region.length = len;
293         isc_buffer_init(&namebuffer, nametext, sizeof nametext);
294         isc_base32hex_totext(&region, 1, "", &namebuffer);
295
296         /* convert the hex to a domain name */
297         dns_fixedname_init(result);
298         return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
299                                   origin, 0, NULL));
300 }
301
302 unsigned int
303 dns_nsec3_hashlength(dns_hash_t hash) {
304
305         switch (hash) {
306         case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
307         }
308         return (0);
309 }
310
311 isc_boolean_t
312 dns_nsec3_supportedhash(dns_hash_t hash) {
313         switch (hash) {
314         case dns_hash_sha1: return (ISC_TRUE);
315         }
316         return (ISC_FALSE);
317 }
318
319 /*%
320  * Update a single RR in version 'ver' of 'db' and log the
321  * update in 'diff'.
322  *
323  * Ensures:
324  * \li  '*tuple' == NULL.  Either the tuple is freed, or its
325  *      ownership has been transferred to the diff.
326  */
327 static isc_result_t
328 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
329              dns_diff_t *diff)
330 {
331         dns_diff_t temp_diff;
332         isc_result_t result;
333
334         /*
335          * Create a singleton diff.
336          */
337         dns_diff_init(diff->mctx, &temp_diff);
338         temp_diff.resign = diff->resign;
339         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
340
341         /*
342          * Apply it to the database.
343          */
344         result = dns_diff_apply(&temp_diff, db, ver);
345         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
346         if (result != ISC_R_SUCCESS) {
347                 dns_difftuple_free(tuple);
348                 return (result);
349         }
350
351         /*
352          * Merge it into the current pending journal entry.
353          */
354         dns_diff_appendminimal(diff, tuple);
355
356         /*
357          * Do not clear temp_diff.
358          */
359         return (ISC_R_SUCCESS);
360 }
361
362 /*%
363  * Set '*exists' to true iff the given name exists, to false otherwise.
364  */
365 static isc_result_t
366 name_exists(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
367             isc_boolean_t *exists)
368 {
369         isc_result_t result;
370         dns_dbnode_t *node = NULL;
371         dns_rdatasetiter_t *iter = NULL;
372
373         result = dns_db_findnode(db, name, ISC_FALSE, &node);
374         if (result == ISC_R_NOTFOUND) {
375                 *exists = ISC_FALSE;
376                 return (ISC_R_SUCCESS);
377         }
378         if (result != ISC_R_SUCCESS)
379                 return (result);
380
381         result = dns_db_allrdatasets(db, node, version,
382                                      (isc_stdtime_t) 0, &iter);
383         if (result != ISC_R_SUCCESS)
384                 goto cleanup_node;
385
386         result = dns_rdatasetiter_first(iter);
387         if (result == ISC_R_SUCCESS) {
388                 *exists = ISC_TRUE;
389         } else if (result == ISC_R_NOMORE) {
390                 *exists = ISC_FALSE;
391                 result = ISC_R_SUCCESS;
392         } else
393                 *exists = ISC_FALSE;
394         dns_rdatasetiter_destroy(&iter);
395
396  cleanup_node:
397         dns_db_detachnode(db, &node);
398         return (result);
399 }
400
401 static isc_boolean_t
402 match_nsec3param(const dns_rdata_nsec3_t *nsec3,
403                  const dns_rdata_nsec3param_t *nsec3param)
404 {
405         if (nsec3->hash == nsec3param->hash &&
406             nsec3->iterations == nsec3param->iterations &&
407             nsec3->salt_length == nsec3param->salt_length &&
408             !memcmp(nsec3->salt, nsec3param->salt, nsec3->salt_length))
409                 return (ISC_TRUE);
410         return (ISC_FALSE);
411 }
412
413 /*%
414  * Delete NSEC3 records at "name" which match "param", recording the
415  * change in "diff".
416  */
417 static isc_result_t
418 delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
419        const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
420 {
421         dns_dbnode_t *node = NULL ;
422         dns_difftuple_t *tuple = NULL;
423         dns_rdata_nsec3_t nsec3;
424         dns_rdataset_t rdataset;
425         isc_result_t result;
426
427         result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
428         if (result == ISC_R_NOTFOUND)
429                 return (ISC_R_SUCCESS);
430         if (result != ISC_R_SUCCESS)
431                 return (result);
432
433         dns_rdataset_init(&rdataset);
434         result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
435                                      (isc_stdtime_t) 0, &rdataset, NULL);
436
437         if (result == ISC_R_NOTFOUND) {
438                 result = ISC_R_SUCCESS;
439                 goto cleanup_node;
440         }
441         if (result != ISC_R_SUCCESS)
442                 goto cleanup_node;
443
444         for (result = dns_rdataset_first(&rdataset);
445              result == ISC_R_SUCCESS;
446              result = dns_rdataset_next(&rdataset))
447         {
448                 dns_rdata_t rdata = DNS_RDATA_INIT;
449                 dns_rdataset_current(&rdataset, &rdata);
450                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
451
452                 if (!match_nsec3param(&nsec3, nsec3param))
453                         continue;
454
455                 result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
456                                               rdataset.ttl, &rdata, &tuple);
457                 if (result != ISC_R_SUCCESS)
458                         goto failure;
459                 result = do_one_tuple(&tuple, db, version, diff);
460                 if (result != ISC_R_SUCCESS)
461                         goto failure;
462         }
463         if (result != ISC_R_NOMORE)
464                 goto failure;
465         result = ISC_R_SUCCESS;
466
467  failure:
468         dns_rdataset_disassociate(&rdataset);
469  cleanup_node:
470         dns_db_detachnode(db, &node);
471
472         return (result);
473 }
474
475 #ifndef RFC5155_STRICT
476 static isc_boolean_t
477 better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
478         dns_rdataset_t rdataset;
479         isc_result_t result;
480
481         if (REMOVE(param->data[1]))
482                 return (ISC_TRUE);
483
484         dns_rdataset_init(&rdataset);
485         dns_rdataset_clone(nsec3paramset, &rdataset);
486         for (result = dns_rdataset_first(&rdataset);
487              result == ISC_R_SUCCESS;
488              result = dns_rdataset_next(&rdataset)) {
489                 dns_rdata_t rdata =  DNS_RDATA_INIT;
490                 dns_rdataset_current(&rdataset, &rdata);
491                 if (rdata.length != param->length)
492                         continue;
493                 if (rdata.data[0] != param->data[0] ||
494                     REMOVE(rdata.data[1]) ||
495                     rdata.data[2] != param->data[2] ||
496                     rdata.data[3] != param->data[3] ||
497                     rdata.data[4] != param->data[4] ||
498                     memcmp(&rdata.data[5], &param->data[5], param->data[4]))
499                         continue;
500                 if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
501                         dns_rdataset_disassociate(&rdataset);
502                         return (ISC_TRUE);
503                 }
504         }
505         dns_rdataset_disassociate(&rdataset);
506         return (ISC_FALSE);
507 }
508 #endif
509
510 static isc_result_t
511 find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
512            const dns_rdata_nsec3param_t *nsec3param)
513 {
514         isc_result_t result;
515         for (result = dns_rdataset_first(rdataset);
516              result == ISC_R_SUCCESS;
517              result = dns_rdataset_next(rdataset)) {
518                 dns_rdata_t rdata = DNS_RDATA_INIT;
519
520                 dns_rdataset_current(rdataset, &rdata);
521                 CHECK(dns_rdata_tostruct(&rdata, nsec3, NULL));
522                 dns_rdata_reset(&rdata);
523                 if (match_nsec3param(nsec3, nsec3param))
524                         break;
525         }
526  failure:
527         return (result);
528 }
529
530 isc_result_t
531 dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
532                    dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
533                    dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff)
534 {
535         dns_dbiterator_t *dbit = NULL;
536         dns_dbnode_t *node = NULL;
537         dns_dbnode_t *newnode = NULL;
538         dns_difftuple_t *tuple = NULL;
539         dns_fixedname_t fixed;
540         dns_fixedname_t fprev;
541         dns_hash_t hash;
542         dns_name_t *hashname;
543         dns_name_t *origin;
544         dns_name_t *prev;
545         dns_name_t empty;
546         dns_rdata_nsec3_t nsec3;
547         dns_rdata_t rdata = DNS_RDATA_INIT;
548         dns_rdataset_t rdataset;
549         int pass;
550         isc_boolean_t exists;
551         isc_boolean_t remove_unsecure = ISC_FALSE;
552         isc_uint8_t flags;
553         isc_buffer_t buffer;
554         isc_result_t result;
555         unsigned char *old_next;
556         unsigned char *salt;
557         unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
558         unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
559         unsigned int iterations;
560         unsigned int labels;
561         size_t next_length;
562         unsigned int old_length;
563         unsigned int salt_length;
564
565         dns_fixedname_init(&fixed);
566         hashname = dns_fixedname_name(&fixed);
567         dns_fixedname_init(&fprev);
568         prev = dns_fixedname_name(&fprev);
569
570         dns_rdataset_init(&rdataset);
571
572         origin = dns_db_origin(db);
573
574         /*
575          * Chain parameters.
576          */
577         hash = nsec3param->hash;
578         iterations = nsec3param->iterations;
579         salt_length = nsec3param->salt_length;
580         salt = nsec3param->salt;
581
582         /*
583          * Default flags for a new chain.
584          */
585         flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
586
587         /*
588          * If this is the first NSEC3 in the chain nexthash will
589          * remain pointing to itself.
590          */
591         next_length = sizeof(nexthash);
592         CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
593                                  name, origin, hash, iterations,
594                                  salt, salt_length));
595
596         /*
597          * Create the node if it doesn't exist and hold
598          * a reference to it until we have added the NSEC3.
599          */
600         CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
601
602         /*
603          * Seek the iterator to the 'newnode'.
604          */
605         CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
606         CHECK(dns_dbiterator_seek(dbit, hashname));
607         CHECK(dns_dbiterator_pause(dbit));
608         result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
609                                      0, (isc_stdtime_t) 0, &rdataset, NULL);
610         /*
611          * If we updating a existing NSEC3 then find its
612          * next field.
613          */
614         if (result == ISC_R_SUCCESS) {
615                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
616                 if (result == ISC_R_SUCCESS) {
617                         if (!CREATE(nsec3param->flags))
618                                 flags = nsec3.flags;
619                         next_length = nsec3.next_length;
620                         INSIST(next_length <= sizeof(nexthash));
621                         memcpy(nexthash, nsec3.next, next_length);
622                         dns_rdataset_disassociate(&rdataset);
623                         /*
624                          * If the NSEC3 is not for a unsecure delegation then
625                          * we are just updating it.  If it is for a unsecure
626                          * delegation then we need find out if we need to
627                          * remove the NSEC3 record or not by examining the
628                          * previous NSEC3 record.
629                          */
630                         if (!unsecure)
631                                 goto addnsec3;
632                         else
633                                 remove_unsecure = ISC_TRUE;
634                 } else {
635                         dns_rdataset_disassociate(&rdataset);
636                         if (result != ISC_R_NOMORE)
637                                 goto failure;
638                 }
639         }
640
641         /*
642          * Find the previous NSEC3 (if any) and update it if required.
643          */
644         pass = 0;
645         do {
646                 result = dns_dbiterator_prev(dbit);
647                 if (result == ISC_R_NOMORE) {
648                         pass++;
649                         CHECK(dns_dbiterator_last(dbit));
650                 }
651                 CHECK(dns_dbiterator_current(dbit, &node, prev));
652                 CHECK(dns_dbiterator_pause(dbit));
653                 result = dns_db_findrdataset(db, node, version,
654                                              dns_rdatatype_nsec3, 0,
655                                              (isc_stdtime_t) 0, &rdataset,
656                                              NULL);
657                 dns_db_detachnode(db, &node);
658                 if (result != ISC_R_SUCCESS)
659                         continue;
660
661                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
662                 if (result == ISC_R_NOMORE) {
663                         dns_rdataset_disassociate(&rdataset);
664                         continue;
665                 }
666                 if (result != ISC_R_SUCCESS)
667                         goto failure;
668
669                 if (remove_unsecure) {
670                         dns_rdataset_disassociate(&rdataset);
671                         /*
672                          * We have found the previous NSEC3 record and can now
673                          * see if the existing NSEC3 record needs to be
674                          * updated or deleted.
675                          */
676                         if (!OPTOUT(nsec3.flags)) {
677                                 /*
678                                  * Just update the NSEC3 record.
679                                  */
680                                 goto addnsec3;
681                         } else {
682                                 /*
683                                  * This is actually a deletion not a add.
684                                  */
685                                 result = dns_nsec3_delnsec3(db, version, name,
686                                                             nsec3param, diff);
687                                 goto failure;
688                         }
689                 } else {
690                         /*
691                          * Is this is a unsecure delegation we are adding?
692                          * If so no change is required.
693                          */
694                         if (OPTOUT(nsec3.flags) && unsecure) {
695                                 dns_rdataset_disassociate(&rdataset);
696                                 goto failure;
697                         }
698                 }
699
700                 old_next = nsec3.next;
701                 old_length = nsec3.next_length;
702
703                 /*
704                  * Delete the old previous NSEC3.
705                  */
706                 CHECK(delete(db, version, prev, nsec3param, diff));
707
708                 /*
709                  * Fixup the previous NSEC3.
710                  */
711                 nsec3.next = nexthash;
712                 nsec3.next_length = next_length;
713                 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
714                 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
715                                            dns_rdatatype_nsec3, &nsec3,
716                                            &buffer));
717                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
718                                            rdataset.ttl, &rdata, &tuple));
719                 CHECK(do_one_tuple(&tuple, db, version, diff));
720                 INSIST(old_length <= sizeof(nexthash));
721                 memcpy(nexthash, old_next, old_length);
722                 if (!CREATE(nsec3param->flags))
723                         flags = nsec3.flags;
724                 dns_rdata_reset(&rdata);
725                 dns_rdataset_disassociate(&rdataset);
726                 break;
727         } while (pass < 2);
728
729  addnsec3:
730         /*
731          * Create the NSEC3 RDATA.
732          */
733         CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
734         CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
735                                    salt, salt_length, nexthash, next_length,
736                                    nsec3buf, &rdata));
737         dns_db_detachnode(db, &node);
738
739         /*
740          * Delete the old NSEC3 and record the change.
741          */
742         CHECK(delete(db, version, hashname, nsec3param, diff));
743         /*
744          * Add the new NSEC3 and record the change.
745          */
746         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
747                                    hashname, nsecttl, &rdata, &tuple));
748         CHECK(do_one_tuple(&tuple, db, version, diff));
749         INSIST(tuple == NULL);
750         dns_rdata_reset(&rdata);
751         dns_db_detachnode(db, &newnode);
752
753         /*
754          * Add missing NSEC3 records for empty nodes
755          */
756         dns_name_init(&empty, NULL);
757         dns_name_clone(name, &empty);
758         do {
759                 labels = dns_name_countlabels(&empty) - 1;
760                 if (labels <= dns_name_countlabels(origin))
761                         break;
762                 dns_name_getlabelsequence(&empty, 1, labels, &empty);
763                 CHECK(name_exists(db, version, &empty, &exists));
764                 if (exists)
765                         break;
766                 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
767                                          &empty, origin, hash, iterations,
768                                          salt, salt_length));
769
770                 /*
771                  * Create the node if it doesn't exist and hold
772                  * a reference to it until we have added the NSEC3
773                  * or we discover we don't need to add make a change.
774                  */
775                 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
776                 result = dns_db_findrdataset(db, newnode, version,
777                                              dns_rdatatype_nsec3, 0,
778                                              (isc_stdtime_t) 0, &rdataset,
779                                              NULL);
780                 if (result == ISC_R_SUCCESS) {
781                         result = find_nsec3(&nsec3, &rdataset, nsec3param);
782                         dns_rdataset_disassociate(&rdataset);
783                         if (result == ISC_R_SUCCESS) {
784                                 dns_db_detachnode(db, &newnode);
785                                 break;
786                         }
787                         if (result != ISC_R_NOMORE)
788                                 goto failure;
789                 }
790
791                 /*
792                  * Find the previous NSEC3 and update it.
793                  */
794                 CHECK(dns_dbiterator_seek(dbit, hashname));
795                 pass = 0;
796                 do {
797                         result = dns_dbiterator_prev(dbit);
798                         if (result == ISC_R_NOMORE) {
799                                 pass++;
800                                 CHECK(dns_dbiterator_last(dbit));
801                         }
802                         CHECK(dns_dbiterator_current(dbit, &node, prev));
803                         CHECK(dns_dbiterator_pause(dbit));
804                         result = dns_db_findrdataset(db, node, version,
805                                                      dns_rdatatype_nsec3, 0,
806                                                      (isc_stdtime_t) 0,
807                                                      &rdataset, NULL);
808                         dns_db_detachnode(db, &node);
809                         if (result != ISC_R_SUCCESS)
810                                 continue;
811                         result = find_nsec3(&nsec3, &rdataset, nsec3param);
812                         if (result == ISC_R_NOMORE) {
813                                 dns_rdataset_disassociate(&rdataset);
814                                 continue;
815                         }
816                         if (result != ISC_R_SUCCESS)
817                                 goto failure;
818
819                         old_next = nsec3.next;
820                         old_length = nsec3.next_length;
821
822                         /*
823                          * Delete the old previous NSEC3.
824                          */
825                         CHECK(delete(db, version, prev, nsec3param, diff));
826
827                         /*
828                          * Fixup the previous NSEC3.
829                          */
830                         nsec3.next = nexthash;
831                         nsec3.next_length = next_length;
832                         isc_buffer_init(&buffer, nsec3buf,
833                                         sizeof(nsec3buf));
834                         CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
835                                                    dns_rdatatype_nsec3, &nsec3,
836                                                    &buffer));
837                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
838                                                    prev, rdataset.ttl, &rdata,
839                                                    &tuple));
840                         CHECK(do_one_tuple(&tuple, db, version, diff));
841                         INSIST(old_length <= sizeof(nexthash));
842                         memcpy(nexthash, old_next, old_length);
843                         if (!CREATE(nsec3param->flags))
844                                 flags = nsec3.flags;
845                         dns_rdata_reset(&rdata);
846                         dns_rdataset_disassociate(&rdataset);
847                         break;
848                 } while (pass < 2);
849
850                 INSIST(pass < 2);
851
852                 /*
853                  * Create the NSEC3 RDATA for the empty node.
854                  */
855                 CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
856                                            iterations, salt, salt_length,
857                                            nexthash, next_length, nsec3buf,
858                                            &rdata));
859                 /*
860                  * Delete the old NSEC3 and record the change.
861                  */
862                 CHECK(delete(db, version, hashname, nsec3param, diff));
863
864                 /*
865                  * Add the new NSEC3 and record the change.
866                  */
867                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
868                                            hashname, nsecttl, &rdata, &tuple));
869                 CHECK(do_one_tuple(&tuple, db, version, diff));
870                 INSIST(tuple == NULL);
871                 dns_rdata_reset(&rdata);
872                 dns_db_detachnode(db, &newnode);
873         } while (1);
874
875         if (result == ISC_R_NOMORE)
876                 result = ISC_R_SUCCESS;
877
878  failure:
879         if (dbit != NULL)
880                 dns_dbiterator_destroy(&dbit);
881         if (dns_rdataset_isassociated(&rdataset))
882                 dns_rdataset_disassociate(&rdataset);
883         if (node != NULL)
884                 dns_db_detachnode(db, &node);
885         if (newnode != NULL)
886                 dns_db_detachnode(db, &newnode);
887         return (result);
888 }
889
890 /*%
891  * Add NSEC3 records for "name", recording the change in "diff".
892  * The existing NSEC3 records are removed.
893  */
894 isc_result_t
895 dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
896                     dns_name_t *name, dns_ttl_t nsecttl,
897                     isc_boolean_t unsecure, dns_diff_t *diff)
898 {
899         dns_dbnode_t *node = NULL;
900         dns_rdata_nsec3param_t nsec3param;
901         dns_rdataset_t rdataset;
902         isc_result_t result;
903
904         dns_rdataset_init(&rdataset);
905
906         /*
907          * Find the NSEC3 parameters for this zone.
908          */
909         result = dns_db_getoriginnode(db, &node);
910         if (result != ISC_R_SUCCESS)
911                 return (result);
912
913         result = dns_db_findrdataset(db, node, version,
914                                      dns_rdatatype_nsec3param, 0, 0,
915                                      &rdataset, NULL);
916         dns_db_detachnode(db, &node);
917         if (result == ISC_R_NOTFOUND)
918                 return (ISC_R_SUCCESS);
919         if (result != ISC_R_SUCCESS)
920                 return (result);
921
922         /*
923          * Update each active NSEC3 chain.
924          */
925         for (result = dns_rdataset_first(&rdataset);
926              result == ISC_R_SUCCESS;
927              result = dns_rdataset_next(&rdataset)) {
928                 dns_rdata_t rdata = DNS_RDATA_INIT;
929
930                 dns_rdataset_current(&rdataset, &rdata);
931                 dns_rdata_tostruct(&rdata, &nsec3param, NULL);
932
933 #ifdef RFC5155_STRICT
934                 if (nsec3param.flags != 0)
935                         continue;
936 #else
937                 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
938                         continue;
939                 if (better_param(&rdataset, &rdata))
940                         continue;
941 #endif
942
943                 /*
944                  * We have a active chain.  Update it.
945                  */
946                 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
947                                          nsecttl, unsecure, diff));
948         }
949         if (result == ISC_R_NOMORE)
950                 result = ISC_R_SUCCESS;
951
952  failure:
953         if (dns_rdataset_isassociated(&rdataset))
954                 dns_rdataset_disassociate(&rdataset);
955         if (node != NULL)
956                 dns_db_detachnode(db, &node);
957
958         return (result);
959 }
960
961 /*%
962  * Determine whether any NSEC3 records that were associated with
963  * 'name' should be deleted or if they should continue to exist.
964  * ISC_TRUE indicates they should be deleted.
965  * ISC_FALSE indicates they should be retained.
966  */
967 static isc_result_t
968 deleteit(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
969          isc_boolean_t *yesno)
970 {
971         isc_result_t result;
972         dns_fixedname_t foundname;
973         dns_fixedname_init(&foundname);
974
975         result = dns_db_find(db, name, ver, dns_rdatatype_any,
976                              DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
977                              (isc_stdtime_t) 0, NULL,
978                              dns_fixedname_name(&foundname),
979                              NULL, NULL);
980         if (result == DNS_R_EMPTYNAME || result == ISC_R_SUCCESS ||
981             result ==  DNS_R_ZONECUT) {
982                 *yesno = ISC_FALSE;
983                 return (ISC_R_SUCCESS);
984         }
985         if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
986             result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
987                 *yesno = ISC_TRUE;
988                 return (ISC_R_SUCCESS);
989         }
990         /*
991          * Silence compiler.
992          */
993         *yesno = ISC_TRUE;
994         return (result);
995 }
996
997 isc_result_t
998 dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
999                    const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
1000 {
1001         dns_dbiterator_t *dbit = NULL;
1002         dns_dbnode_t *node = NULL;
1003         dns_difftuple_t *tuple = NULL;
1004         dns_fixedname_t fixed;
1005         dns_fixedname_t fprev;
1006         dns_hash_t hash;
1007         dns_name_t *hashname;
1008         dns_name_t *origin;
1009         dns_name_t *prev;
1010         dns_name_t empty;
1011         dns_rdata_nsec3_t nsec3;
1012         dns_rdata_t rdata = DNS_RDATA_INIT;
1013         dns_rdataset_t rdataset;
1014         int pass;
1015         isc_boolean_t yesno;
1016         isc_buffer_t buffer;
1017         isc_result_t result;
1018         unsigned char *salt;
1019         unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
1020         unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
1021         unsigned int iterations;
1022         unsigned int labels;
1023         size_t next_length;
1024         unsigned int salt_length;
1025
1026         dns_fixedname_init(&fixed);
1027         hashname = dns_fixedname_name(&fixed);
1028         dns_fixedname_init(&fprev);
1029         prev = dns_fixedname_name(&fprev);
1030
1031         dns_rdataset_init(&rdataset);
1032
1033         origin = dns_db_origin(db);
1034
1035         /*
1036          * Chain parameters.
1037          */
1038         hash = nsec3param->hash;
1039         iterations = nsec3param->iterations;
1040         salt_length = nsec3param->salt_length;
1041         salt = nsec3param->salt;
1042
1043         /*
1044          * If this is the first NSEC3 in the chain nexthash will
1045          * remain pointing to itself.
1046          */
1047         next_length = sizeof(nexthash);
1048         CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1049                                  name, origin, hash, iterations,
1050                                  salt, salt_length));
1051
1052         CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
1053
1054         result = dns_dbiterator_seek(dbit, hashname);
1055         if (result == ISC_R_NOTFOUND)
1056                 goto success;
1057         if (result != ISC_R_SUCCESS)
1058                 goto failure;
1059
1060         CHECK(dns_dbiterator_current(dbit, &node, NULL));
1061         CHECK(dns_dbiterator_pause(dbit));
1062         result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
1063                                      0, (isc_stdtime_t) 0, &rdataset, NULL);
1064         dns_db_detachnode(db, &node);
1065         if (result == ISC_R_NOTFOUND)
1066                 goto success;
1067         if (result != ISC_R_SUCCESS)
1068                 goto failure;
1069
1070         /*
1071          * If we find a existing NSEC3 for this chain then save the
1072          * next field.
1073          */
1074         result = find_nsec3(&nsec3, &rdataset, nsec3param);
1075         if (result == ISC_R_SUCCESS) {
1076                 next_length = nsec3.next_length;
1077                 INSIST(next_length <= sizeof(nexthash));
1078                 memcpy(nexthash, nsec3.next, next_length);
1079         }
1080         dns_rdataset_disassociate(&rdataset);
1081         if (result == ISC_R_NOMORE)
1082                 goto success;
1083         if (result != ISC_R_SUCCESS)
1084                 goto failure;
1085
1086         /*
1087          * Find the previous NSEC3 and update it.
1088          */
1089         pass = 0;
1090         do {
1091                 result = dns_dbiterator_prev(dbit);
1092                 if (result == ISC_R_NOMORE) {
1093                         pass++;
1094                         CHECK(dns_dbiterator_last(dbit));
1095                 }
1096                 CHECK(dns_dbiterator_current(dbit, &node, prev));
1097                 CHECK(dns_dbiterator_pause(dbit));
1098                 result = dns_db_findrdataset(db, node, version,
1099                                              dns_rdatatype_nsec3, 0,
1100                                              (isc_stdtime_t) 0, &rdataset,
1101                                              NULL);
1102                 dns_db_detachnode(db, &node);
1103                 if (result != ISC_R_SUCCESS)
1104                         continue;
1105                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1106                 if (result == ISC_R_NOMORE) {
1107                         dns_rdataset_disassociate(&rdataset);
1108                         continue;
1109                 }
1110                 if (result != ISC_R_SUCCESS)
1111                         goto failure;
1112
1113                 /*
1114                  * Delete the old previous NSEC3.
1115                  */
1116                 CHECK(delete(db, version, prev, nsec3param, diff));
1117
1118                 /*
1119                  * Fixup the previous NSEC3.
1120                  */
1121                 nsec3.next = nexthash;
1122                 nsec3.next_length = next_length;
1123                 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
1124                 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1125                                            dns_rdatatype_nsec3, &nsec3,
1126                                            &buffer));
1127                 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
1128                                            rdataset.ttl, &rdata, &tuple));
1129                 CHECK(do_one_tuple(&tuple, db, version, diff));
1130                 dns_rdata_reset(&rdata);
1131                 dns_rdataset_disassociate(&rdataset);
1132                 break;
1133         } while (pass < 2);
1134
1135         /*
1136          * Delete the old NSEC3 and record the change.
1137          */
1138         CHECK(delete(db, version, hashname, nsec3param, diff));
1139
1140         /*
1141          *  Delete NSEC3 records for now non active nodes.
1142          */
1143         dns_name_init(&empty, NULL);
1144         dns_name_clone(name, &empty);
1145         do {
1146                 labels = dns_name_countlabels(&empty) - 1;
1147                 if (labels <= dns_name_countlabels(origin))
1148                         break;
1149                 dns_name_getlabelsequence(&empty, 1, labels, &empty);
1150                 CHECK(deleteit(db, version, &empty, &yesno));
1151                 if (!yesno)
1152                         break;
1153
1154                 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1155                                          &empty, origin, hash, iterations,
1156                                          salt, salt_length));
1157                 result = dns_dbiterator_seek(dbit, hashname);
1158                 if (result == ISC_R_NOTFOUND)
1159                         goto success;
1160                 if (result != ISC_R_SUCCESS)
1161                         goto failure;
1162
1163                 CHECK(dns_dbiterator_current(dbit, &node, NULL));
1164                 CHECK(dns_dbiterator_pause(dbit));
1165                 result = dns_db_findrdataset(db, node, version,
1166                                              dns_rdatatype_nsec3, 0,
1167                                              (isc_stdtime_t) 0, &rdataset,
1168                                              NULL);
1169                 dns_db_detachnode(db, &node);
1170                 if (result == ISC_R_NOTFOUND)
1171                         goto success;
1172                 if (result != ISC_R_SUCCESS)
1173                         goto failure;
1174
1175                 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1176                 if (result == ISC_R_SUCCESS) {
1177                         next_length = nsec3.next_length;
1178                         INSIST(next_length <= sizeof(nexthash));
1179                         memcpy(nexthash, nsec3.next, next_length);
1180                 }
1181                 dns_rdataset_disassociate(&rdataset);
1182                 if (result == ISC_R_NOMORE)
1183                         goto success;
1184                 if (result != ISC_R_SUCCESS)
1185                         goto failure;
1186
1187                 pass = 0;
1188                 do {
1189                         result = dns_dbiterator_prev(dbit);
1190                         if (result == ISC_R_NOMORE) {
1191                                 pass++;
1192                                 CHECK(dns_dbiterator_last(dbit));
1193                         }
1194                         CHECK(dns_dbiterator_current(dbit, &node, prev));
1195                         CHECK(dns_dbiterator_pause(dbit));
1196                         result = dns_db_findrdataset(db, node, version,
1197                                                      dns_rdatatype_nsec3, 0,
1198                                                      (isc_stdtime_t) 0,
1199                                                      &rdataset, NULL);
1200                         dns_db_detachnode(db, &node);
1201                         if (result != ISC_R_SUCCESS)
1202                                 continue;
1203                         result = find_nsec3(&nsec3, &rdataset, nsec3param);
1204                         if (result == ISC_R_NOMORE) {
1205                                 dns_rdataset_disassociate(&rdataset);
1206                                 continue;
1207                         }
1208                         if (result != ISC_R_SUCCESS)
1209                                 goto failure;
1210
1211                         /*
1212                          * Delete the old previous NSEC3.
1213                          */
1214                         CHECK(delete(db, version, prev, nsec3param, diff));
1215
1216                         /*
1217                          * Fixup the previous NSEC3.
1218                          */
1219                         nsec3.next = nexthash;
1220                         nsec3.next_length = next_length;
1221                         isc_buffer_init(&buffer, nsec3buf,
1222                                         sizeof(nsec3buf));
1223                         CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1224                                                    dns_rdatatype_nsec3, &nsec3,
1225                                                    &buffer));
1226                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
1227                                                    prev, rdataset.ttl, &rdata,
1228                                                    &tuple));
1229                         CHECK(do_one_tuple(&tuple, db, version, diff));
1230                         dns_rdata_reset(&rdata);
1231                         dns_rdataset_disassociate(&rdataset);
1232                         break;
1233                 } while (pass < 2);
1234
1235                 INSIST(pass < 2);
1236
1237                 /*
1238                  * Delete the old NSEC3 and record the change.
1239                  */
1240                 CHECK(delete(db, version, hashname, nsec3param, diff));
1241         } while (1);
1242
1243  success:
1244         result = ISC_R_SUCCESS;
1245
1246  failure:
1247         if (dbit != NULL)
1248                 dns_dbiterator_destroy(&dbit);
1249         if (dns_rdataset_isassociated(&rdataset))
1250                 dns_rdataset_disassociate(&rdataset);
1251         if (node != NULL)
1252                 dns_db_detachnode(db, &node);
1253         return (result);
1254 }
1255
1256 isc_result_t
1257 dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1258                     dns_diff_t *diff)
1259 {
1260         dns_dbnode_t *node = NULL;
1261         dns_rdata_nsec3param_t nsec3param;
1262         dns_rdataset_t rdataset;
1263         isc_result_t result;
1264
1265         dns_rdataset_init(&rdataset);
1266
1267         /*
1268          * Find the NSEC3 parameters for this zone.
1269          */
1270         result = dns_db_getoriginnode(db, &node);
1271         if (result != ISC_R_SUCCESS)
1272                 return (result);
1273
1274         result = dns_db_findrdataset(db, node, version,
1275                                      dns_rdatatype_nsec3param, 0, 0,
1276                                      &rdataset, NULL);
1277         dns_db_detachnode(db, &node);
1278         if (result == ISC_R_NOTFOUND)
1279                 return (ISC_R_SUCCESS);
1280         if (result != ISC_R_SUCCESS)
1281                 return (result);
1282
1283         /*
1284          * Update each active NSEC3 chain.
1285          */
1286         for (result = dns_rdataset_first(&rdataset);
1287              result == ISC_R_SUCCESS;
1288              result = dns_rdataset_next(&rdataset)) {
1289                 dns_rdata_t rdata = DNS_RDATA_INIT;
1290
1291                 dns_rdataset_current(&rdataset, &rdata);
1292                 dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1293
1294 #ifdef RFC5155_STRICT
1295                 if (nsec3param.flags != 0)
1296                         continue;
1297 #else
1298                 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
1299                         continue;
1300                 if (better_param(&rdataset, &rdata))
1301                         continue;
1302 #endif
1303
1304                 /*
1305                  * We have a active chain.  Update it.
1306                  */
1307                 CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1308         }
1309         if (result == ISC_R_NOMORE)
1310                 result = ISC_R_SUCCESS;
1311
1312  failure:
1313         if (dns_rdataset_isassociated(&rdataset))
1314                 dns_rdataset_disassociate(&rdataset);
1315         if (node != NULL)
1316                 dns_db_detachnode(db, &node);
1317
1318         return (result);
1319 }
1320
1321 isc_result_t
1322 dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
1323                  isc_boolean_t complete, isc_boolean_t *answer)
1324 {
1325         dns_dbnode_t *node = NULL;
1326         dns_rdataset_t rdataset;
1327         dns_rdata_nsec3param_t nsec3param;
1328         isc_result_t result;
1329
1330         REQUIRE(answer != NULL);
1331
1332         dns_rdataset_init(&rdataset);
1333
1334         result = dns_db_getoriginnode(db, &node);
1335         if (result != ISC_R_SUCCESS)
1336                 return (result);
1337
1338         result = dns_db_findrdataset(db, node, version,
1339                                      dns_rdatatype_nsec3param, 0, 0,
1340                                      &rdataset, NULL);
1341         dns_db_detachnode(db, &node);
1342
1343         if (result == ISC_R_NOTFOUND) {
1344                 *answer = ISC_FALSE;
1345                 return (ISC_R_SUCCESS);
1346         }
1347         if (result != ISC_R_SUCCESS)
1348                 return (result);
1349         for (result = dns_rdataset_first(&rdataset);
1350              result == ISC_R_SUCCESS;
1351              result = dns_rdataset_next(&rdataset)) {
1352                 dns_rdata_t rdata = DNS_RDATA_INIT;
1353
1354                 dns_rdataset_current(&rdataset, &rdata);
1355                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1356                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1357
1358                 if ((nsec3param.flags) == 0 ||
1359                     (!complete && CREATE(nsec3param.flags)))
1360                         break;
1361         }
1362         dns_rdataset_disassociate(&rdataset);
1363         if (result == ISC_R_SUCCESS)
1364                 *answer = ISC_TRUE;
1365         if (result == ISC_R_NOMORE) {
1366                 *answer = ISC_FALSE;
1367                 result = ISC_R_SUCCESS;
1368         }
1369         return (result);
1370 }
1371
1372 isc_result_t
1373 dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
1374                         isc_mem_t *mctx, unsigned int *iterationsp)
1375 {
1376         dns_dbnode_t *node = NULL;
1377         dns_rdataset_t rdataset;
1378         dst_key_t *key = NULL;
1379         isc_buffer_t buffer;
1380         isc_result_t result;
1381         isc_uint16_t bits, minbits = 4096;
1382
1383         result = dns_db_getoriginnode(db, &node);
1384         if (result != ISC_R_SUCCESS)
1385                 return (result);
1386
1387         dns_rdataset_init(&rdataset);
1388         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
1389                                      0, 0, &rdataset, NULL);
1390         dns_db_detachnode(db, &node);
1391         if (result == ISC_R_NOTFOUND) {
1392                 *iterationsp = 0;
1393                 return (ISC_R_SUCCESS);
1394         }
1395         if (result != ISC_R_SUCCESS)
1396                 goto failure;
1397
1398         for (result = dns_rdataset_first(&rdataset);
1399              result == ISC_R_SUCCESS;
1400              result = dns_rdataset_next(&rdataset)) {
1401                 dns_rdata_t rdata = DNS_RDATA_INIT;
1402
1403                 dns_rdataset_current(&rdataset, &rdata);
1404                 isc_buffer_init(&buffer, rdata.data, rdata.length);
1405                 isc_buffer_add(&buffer, rdata.length);
1406                 CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
1407                                       &buffer, mctx, &key));
1408                 bits = dst_key_getbits(key);
1409                 dst_key_free(&key);
1410                 if (minbits > bits)
1411                         minbits = bits;
1412         }
1413         if (result != ISC_R_NOMORE)
1414                 goto failure;
1415
1416         if (minbits <= 1024)
1417                 *iterationsp = 150;
1418         else if (minbits <= 2048)
1419                 *iterationsp = 500;
1420         else
1421                 *iterationsp = 2500;
1422         result = ISC_R_SUCCESS;
1423
1424  failure:
1425         if (dns_rdataset_isassociated(&rdataset))
1426                 dns_rdataset_disassociate(&rdataset);
1427         return (result);
1428 }