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