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