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