2 * Copyright (C) 2006, 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
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.
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.
17 /* $Id: nsec3.c,v 1.6.12.4 2009/11/03 23:47:46 tbox Exp $ */
21 #include <isc/base32.h>
22 #include <isc/buffer.h>
24 #include <isc/iterated_hash.h>
25 #include <isc/string.h>
31 #include <dns/dbiterator.h>
33 #include <dns/fixedname.h>
34 #include <dns/nsec3.h>
35 #include <dns/rdata.h>
36 #include <dns/rdatalist.h>
37 #include <dns/rdataset.h>
38 #include <dns/rdatasetiter.h>
39 #include <dns/rdatastruct.h>
40 #include <dns/result.h>
42 #define CHECK(x) do { \
44 if (result != ISC_R_SUCCESS) \
48 #define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
49 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
50 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
53 set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
54 unsigned int shift, mask;
56 shift = 7 - (index % 8);
60 array[index / 8] |= mask;
62 array[index / 8] &= (~mask & 0xFF);
66 bit_isset(unsigned char *array, unsigned int index) {
67 unsigned int byte, shift, mask;
69 byte = array[index / 8];
70 shift = 7 - (index % 8);
73 return ((byte & mask) != 0);
77 dns_nsec3_buildrdata(dns_db_t *db, dns_dbversion_t *version,
78 dns_dbnode_t *node, unsigned int hashalg,
79 unsigned int flags, unsigned int iterations,
80 const unsigned char *salt, size_t salt_length,
81 const unsigned char *nexthash, size_t hash_length,
82 unsigned char *buffer, dns_rdata_t *rdata)
85 dns_rdataset_t rdataset;
87 unsigned int i, window;
90 isc_boolean_t found_ns;
91 isc_boolean_t need_rrsig;
93 unsigned char *nsec_bits, *bm;
94 unsigned int max_type;
95 dns_rdatasetiter_t *rdsiter;
98 REQUIRE(salt_length < 256U);
99 REQUIRE(hash_length < 256U);
100 REQUIRE(flags <= 0xffU);
101 REQUIRE(hashalg <= 0xffU);
102 REQUIRE(iterations <= 0xffffU);
106 REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
110 memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
117 *p++ = iterations >> 8;
121 memcpy(p, salt, salt_length);
125 memcpy(p, nexthash, hash_length);
128 r.length = p - buffer;
132 * Use the end of the space for a raw bitmap leaving enough
133 * space for the window identifiers and length octets.
135 bm = r.base + r.length + 512;
136 nsec_bits = r.base + r.length;
139 goto collapse_bitmap;
140 dns_rdataset_init(&rdataset);
142 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
143 if (result != ISC_R_SUCCESS)
145 found = found_ns = need_rrsig = ISC_FALSE;
146 for (result = dns_rdatasetiter_first(rdsiter);
147 result == ISC_R_SUCCESS;
148 result = dns_rdatasetiter_next(rdsiter))
150 dns_rdatasetiter_current(rdsiter, &rdataset);
151 if (rdataset.type != dns_rdatatype_nsec &&
152 rdataset.type != dns_rdatatype_nsec3 &&
153 rdataset.type != dns_rdatatype_rrsig) {
154 if (rdataset.type > max_type)
155 max_type = rdataset.type;
156 set_bit(bm, rdataset.type, 1);
158 * Work out if we need to set the RRSIG bit for
159 * this node. We set the RRSIG bit if either of
160 * the following conditions are met:
161 * 1) We have a SOA or DS then we need to set
162 * the RRSIG bit as both always will be signed.
163 * 2) We set the RRSIG bit if we don't have
164 * a NS record but do have other data.
166 if (rdataset.type == dns_rdatatype_soa ||
167 rdataset.type == dns_rdatatype_ds)
168 need_rrsig = ISC_TRUE;
169 else if (rdataset.type == dns_rdatatype_ns)
174 dns_rdataset_disassociate(&rdataset);
176 if ((found && !found_ns) || need_rrsig) {
177 if (dns_rdatatype_rrsig > max_type)
178 max_type = dns_rdatatype_rrsig;
179 set_bit(bm, dns_rdatatype_rrsig, 1);
183 * At zone cuts, deny the existence of glue in the parent zone.
185 if (bit_isset(bm, dns_rdatatype_ns) &&
186 ! bit_isset(bm, dns_rdatatype_soa)) {
187 for (i = 0; i <= max_type; i++) {
188 if (bit_isset(bm, i) &&
189 ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
194 dns_rdatasetiter_destroy(&rdsiter);
195 if (result != ISC_R_NOMORE)
199 for (window = 0; window < 256; window++) {
200 if (window * 256 > max_type)
202 for (octet = 31; octet >= 0; octet--)
203 if (bm[window * 32 + octet] != 0)
207 nsec_bits[0] = window;
208 nsec_bits[1] = octet + 1;
210 * Note: potentially overlapping move.
212 memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
213 nsec_bits += 3 + octet;
215 r.length = nsec_bits - r.base;
216 INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
217 dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
219 return (ISC_R_SUCCESS);
223 dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
224 dns_rdata_nsec3_t nsec3;
226 isc_boolean_t present;
227 unsigned int i, len, window;
229 REQUIRE(rdata != NULL);
230 REQUIRE(rdata->type == dns_rdatatype_nsec3);
232 /* This should never fail */
233 result = dns_rdata_tostruct(rdata, &nsec3, NULL);
234 INSIST(result == ISC_R_SUCCESS);
237 for (i = 0; i < nsec3.len; i += len) {
238 INSIST(i + 2 <= nsec3.len);
239 window = nsec3.typebits[i];
240 len = nsec3.typebits[i + 1];
241 INSIST(len > 0 && len <= 32);
243 INSIST(i + len <= nsec3.len);
244 if (window * 256 > type)
246 if ((window + 1) * 256 <= type)
248 if (type < (window * 256) + len * 8)
249 present = ISC_TF(bit_isset(&nsec3.typebits[i],
253 dns_rdata_freestruct(&nsec3);
258 dns_nsec3_hashname(dns_fixedname_t *result,
259 unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
260 size_t *hash_length, dns_name_t *name, dns_name_t *origin,
261 dns_hash_t hashalg, unsigned int iterations,
262 const unsigned char *salt, size_t saltlength)
264 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
265 unsigned char nametext[DNS_NAME_FORMATSIZE];
266 dns_fixedname_t fixed;
267 dns_name_t *downcased;
268 isc_buffer_t namebuffer;
275 memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
277 dns_fixedname_init(&fixed);
278 downcased = dns_fixedname_name(&fixed);
279 dns_name_downcase(name, downcased, NULL);
281 /* hash the node name */
282 len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
283 downcased->ndata, downcased->length);
285 return (DNS_R_BADALG);
287 if (hash_length != NULL)
290 /* convert the hash to base32hex */
291 region.base = rethash;
293 isc_buffer_init(&namebuffer, nametext, sizeof nametext);
294 isc_base32hex_totext(®ion, 1, "", &namebuffer);
296 /* convert the hex to a domain name */
297 dns_fixedname_init(result);
298 return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
303 dns_nsec3_hashlength(dns_hash_t hash) {
306 case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
312 dns_nsec3_supportedhash(dns_hash_t hash) {
314 case dns_hash_sha1: return (ISC_TRUE);
320 * Update a single RR in version 'ver' of 'db' and log the
324 * \li '*tuple' == NULL. Either the tuple is freed, or its
325 * ownership has been transferred to the diff.
328 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
331 dns_diff_t temp_diff;
335 * Create a singleton diff.
337 dns_diff_init(diff->mctx, &temp_diff);
338 temp_diff.resign = diff->resign;
339 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
342 * Apply it to the database.
344 result = dns_diff_apply(&temp_diff, db, ver);
345 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
346 if (result != ISC_R_SUCCESS) {
347 dns_difftuple_free(tuple);
352 * Merge it into the current pending journal entry.
354 dns_diff_appendminimal(diff, tuple);
357 * Do not clear temp_diff.
359 return (ISC_R_SUCCESS);
363 * Set '*exists' to true iff the given name exists, to false otherwise.
366 name_exists(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
367 isc_boolean_t *exists)
370 dns_dbnode_t *node = NULL;
371 dns_rdatasetiter_t *iter = NULL;
373 result = dns_db_findnode(db, name, ISC_FALSE, &node);
374 if (result == ISC_R_NOTFOUND) {
376 return (ISC_R_SUCCESS);
378 if (result != ISC_R_SUCCESS)
381 result = dns_db_allrdatasets(db, node, version,
382 (isc_stdtime_t) 0, &iter);
383 if (result != ISC_R_SUCCESS)
386 result = dns_rdatasetiter_first(iter);
387 if (result == ISC_R_SUCCESS) {
389 } else if (result == ISC_R_NOMORE) {
391 result = ISC_R_SUCCESS;
394 dns_rdatasetiter_destroy(&iter);
397 dns_db_detachnode(db, &node);
402 match_nsec3param(const dns_rdata_nsec3_t *nsec3,
403 const dns_rdata_nsec3param_t *nsec3param)
405 if (nsec3->hash == nsec3param->hash &&
406 nsec3->iterations == nsec3param->iterations &&
407 nsec3->salt_length == nsec3param->salt_length &&
408 !memcmp(nsec3->salt, nsec3param->salt, nsec3->salt_length))
414 * Delete NSEC3 records at "name" which match "param", recording the
418 delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
419 const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
421 dns_dbnode_t *node = NULL ;
422 dns_difftuple_t *tuple = NULL;
423 dns_rdata_nsec3_t nsec3;
424 dns_rdataset_t rdataset;
427 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
428 if (result == ISC_R_NOTFOUND)
429 return (ISC_R_SUCCESS);
430 if (result != ISC_R_SUCCESS)
433 dns_rdataset_init(&rdataset);
434 result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
435 (isc_stdtime_t) 0, &rdataset, NULL);
437 if (result == ISC_R_NOTFOUND) {
438 result = ISC_R_SUCCESS;
441 if (result != ISC_R_SUCCESS)
444 for (result = dns_rdataset_first(&rdataset);
445 result == ISC_R_SUCCESS;
446 result = dns_rdataset_next(&rdataset))
448 dns_rdata_t rdata = DNS_RDATA_INIT;
449 dns_rdataset_current(&rdataset, &rdata);
450 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
452 if (!match_nsec3param(&nsec3, nsec3param))
455 result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
456 rdataset.ttl, &rdata, &tuple);
457 if (result != ISC_R_SUCCESS)
459 result = do_one_tuple(&tuple, db, version, diff);
460 if (result != ISC_R_SUCCESS)
463 if (result != ISC_R_NOMORE)
465 result = ISC_R_SUCCESS;
468 dns_rdataset_disassociate(&rdataset);
470 dns_db_detachnode(db, &node);
475 #ifndef RFC5155_STRICT
477 better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
478 dns_rdataset_t rdataset;
481 if (REMOVE(param->data[1]))
484 dns_rdataset_init(&rdataset);
485 dns_rdataset_clone(nsec3paramset, &rdataset);
486 for (result = dns_rdataset_first(&rdataset);
487 result == ISC_R_SUCCESS;
488 result = dns_rdataset_next(&rdataset)) {
489 dns_rdata_t rdata = DNS_RDATA_INIT;
490 dns_rdataset_current(&rdataset, &rdata);
491 if (rdata.length != param->length)
493 if (rdata.data[0] != param->data[0] ||
494 REMOVE(rdata.data[1]) ||
495 rdata.data[2] != param->data[2] ||
496 rdata.data[3] != param->data[3] ||
497 rdata.data[4] != param->data[4] ||
498 memcmp(&rdata.data[5], ¶m->data[5], param->data[4]))
500 if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
501 dns_rdataset_disassociate(&rdataset);
505 dns_rdataset_disassociate(&rdataset);
511 find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
512 const dns_rdata_nsec3param_t *nsec3param)
515 for (result = dns_rdataset_first(rdataset);
516 result == ISC_R_SUCCESS;
517 result = dns_rdataset_next(rdataset)) {
518 dns_rdata_t rdata = DNS_RDATA_INIT;
520 dns_rdataset_current(rdataset, &rdata);
521 CHECK(dns_rdata_tostruct(&rdata, nsec3, NULL));
522 dns_rdata_reset(&rdata);
523 if (match_nsec3param(nsec3, nsec3param))
531 dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
532 dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
533 dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff)
535 dns_dbiterator_t *dbit = NULL;
536 dns_dbnode_t *node = NULL;
537 dns_dbnode_t *newnode = NULL;
538 dns_difftuple_t *tuple = NULL;
539 dns_fixedname_t fixed;
540 dns_fixedname_t fprev;
542 dns_name_t *hashname;
546 dns_rdata_nsec3_t nsec3;
547 dns_rdata_t rdata = DNS_RDATA_INIT;
548 dns_rdataset_t rdataset;
550 isc_boolean_t exists;
551 isc_boolean_t remove_unsecure = ISC_FALSE;
555 unsigned char *old_next;
557 unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
558 unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
559 unsigned int iterations;
562 unsigned int old_length;
563 unsigned int salt_length;
565 dns_fixedname_init(&fixed);
566 hashname = dns_fixedname_name(&fixed);
567 dns_fixedname_init(&fprev);
568 prev = dns_fixedname_name(&fprev);
570 dns_rdataset_init(&rdataset);
572 origin = dns_db_origin(db);
577 hash = nsec3param->hash;
578 iterations = nsec3param->iterations;
579 salt_length = nsec3param->salt_length;
580 salt = nsec3param->salt;
583 * Default flags for a new chain.
585 flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
588 * If this is the first NSEC3 in the chain nexthash will
589 * remain pointing to itself.
591 next_length = sizeof(nexthash);
592 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
593 name, origin, hash, iterations,
597 * Create the node if it doesn't exist and hold
598 * a reference to it until we have added the NSEC3.
600 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
603 * Seek the iterator to the 'newnode'.
605 CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
606 CHECK(dns_dbiterator_seek(dbit, hashname));
607 CHECK(dns_dbiterator_pause(dbit));
608 result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
609 0, (isc_stdtime_t) 0, &rdataset, NULL);
611 * If we updating a existing NSEC3 then find its
614 if (result == ISC_R_SUCCESS) {
615 result = find_nsec3(&nsec3, &rdataset, nsec3param);
616 if (result == ISC_R_SUCCESS) {
617 if (!CREATE(nsec3param->flags))
619 next_length = nsec3.next_length;
620 INSIST(next_length <= sizeof(nexthash));
621 memcpy(nexthash, nsec3.next, next_length);
622 dns_rdataset_disassociate(&rdataset);
624 * If the NSEC3 is not for a unsecure delegation then
625 * we are just updating it. If it is for a unsecure
626 * delegation then we need find out if we need to
627 * remove the NSEC3 record or not by examining the
628 * previous NSEC3 record.
633 remove_unsecure = ISC_TRUE;
635 dns_rdataset_disassociate(&rdataset);
636 if (result != ISC_R_NOMORE)
642 * Find the previous NSEC3 (if any) and update it if required.
646 result = dns_dbiterator_prev(dbit);
647 if (result == ISC_R_NOMORE) {
649 CHECK(dns_dbiterator_last(dbit));
651 CHECK(dns_dbiterator_current(dbit, &node, prev));
652 CHECK(dns_dbiterator_pause(dbit));
653 result = dns_db_findrdataset(db, node, version,
654 dns_rdatatype_nsec3, 0,
655 (isc_stdtime_t) 0, &rdataset,
657 dns_db_detachnode(db, &node);
658 if (result != ISC_R_SUCCESS)
661 result = find_nsec3(&nsec3, &rdataset, nsec3param);
662 if (result == ISC_R_NOMORE) {
663 dns_rdataset_disassociate(&rdataset);
666 if (result != ISC_R_SUCCESS)
669 if (remove_unsecure) {
670 dns_rdataset_disassociate(&rdataset);
672 * We have found the previous NSEC3 record and can now
673 * see if the existing NSEC3 record needs to be
674 * updated or deleted.
676 if (!OPTOUT(nsec3.flags)) {
678 * Just update the NSEC3 record.
683 * This is actually a deletion not a add.
685 result = dns_nsec3_delnsec3(db, version, name,
691 * Is this is a unsecure delegation we are adding?
692 * If so no change is required.
694 if (OPTOUT(nsec3.flags) && unsecure) {
695 dns_rdataset_disassociate(&rdataset);
700 old_next = nsec3.next;
701 old_length = nsec3.next_length;
704 * Delete the old previous NSEC3.
706 CHECK(delete(db, version, prev, nsec3param, diff));
709 * Fixup the previous NSEC3.
711 nsec3.next = nexthash;
712 nsec3.next_length = next_length;
713 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
714 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
715 dns_rdatatype_nsec3, &nsec3,
717 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
718 rdataset.ttl, &rdata, &tuple));
719 CHECK(do_one_tuple(&tuple, db, version, diff));
720 INSIST(old_length <= sizeof(nexthash));
721 memcpy(nexthash, old_next, old_length);
722 if (!CREATE(nsec3param->flags))
724 dns_rdata_reset(&rdata);
725 dns_rdataset_disassociate(&rdataset);
731 * Create the NSEC3 RDATA.
733 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
734 CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
735 salt, salt_length, nexthash, next_length,
737 dns_db_detachnode(db, &node);
740 * Delete the old NSEC3 and record the change.
742 CHECK(delete(db, version, hashname, nsec3param, diff));
744 * Add the new NSEC3 and record the change.
746 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
747 hashname, nsecttl, &rdata, &tuple));
748 CHECK(do_one_tuple(&tuple, db, version, diff));
749 INSIST(tuple == NULL);
750 dns_rdata_reset(&rdata);
751 dns_db_detachnode(db, &newnode);
754 * Add missing NSEC3 records for empty nodes
756 dns_name_init(&empty, NULL);
757 dns_name_clone(name, &empty);
759 labels = dns_name_countlabels(&empty) - 1;
760 if (labels <= dns_name_countlabels(origin))
762 dns_name_getlabelsequence(&empty, 1, labels, &empty);
763 CHECK(name_exists(db, version, &empty, &exists));
766 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
767 &empty, origin, hash, iterations,
771 * Create the node if it doesn't exist and hold
772 * a reference to it until we have added the NSEC3
773 * or we discover we don't need to add make a change.
775 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
776 result = dns_db_findrdataset(db, newnode, version,
777 dns_rdatatype_nsec3, 0,
778 (isc_stdtime_t) 0, &rdataset,
780 if (result == ISC_R_SUCCESS) {
781 result = find_nsec3(&nsec3, &rdataset, nsec3param);
782 dns_rdataset_disassociate(&rdataset);
783 if (result == ISC_R_SUCCESS) {
784 dns_db_detachnode(db, &newnode);
787 if (result != ISC_R_NOMORE)
792 * Find the previous NSEC3 and update it.
794 CHECK(dns_dbiterator_seek(dbit, hashname));
797 result = dns_dbiterator_prev(dbit);
798 if (result == ISC_R_NOMORE) {
800 CHECK(dns_dbiterator_last(dbit));
802 CHECK(dns_dbiterator_current(dbit, &node, prev));
803 CHECK(dns_dbiterator_pause(dbit));
804 result = dns_db_findrdataset(db, node, version,
805 dns_rdatatype_nsec3, 0,
808 dns_db_detachnode(db, &node);
809 if (result != ISC_R_SUCCESS)
811 result = find_nsec3(&nsec3, &rdataset, nsec3param);
812 if (result == ISC_R_NOMORE) {
813 dns_rdataset_disassociate(&rdataset);
816 if (result != ISC_R_SUCCESS)
819 old_next = nsec3.next;
820 old_length = nsec3.next_length;
823 * Delete the old previous NSEC3.
825 CHECK(delete(db, version, prev, nsec3param, diff));
828 * Fixup the previous NSEC3.
830 nsec3.next = nexthash;
831 nsec3.next_length = next_length;
832 isc_buffer_init(&buffer, nsec3buf,
834 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
835 dns_rdatatype_nsec3, &nsec3,
837 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
838 prev, rdataset.ttl, &rdata,
840 CHECK(do_one_tuple(&tuple, db, version, diff));
841 INSIST(old_length <= sizeof(nexthash));
842 memcpy(nexthash, old_next, old_length);
843 if (!CREATE(nsec3param->flags))
845 dns_rdata_reset(&rdata);
846 dns_rdataset_disassociate(&rdataset);
853 * Create the NSEC3 RDATA for the empty node.
855 CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
856 iterations, salt, salt_length,
857 nexthash, next_length, nsec3buf,
860 * Delete the old NSEC3 and record the change.
862 CHECK(delete(db, version, hashname, nsec3param, diff));
865 * Add the new NSEC3 and record the change.
867 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
868 hashname, nsecttl, &rdata, &tuple));
869 CHECK(do_one_tuple(&tuple, db, version, diff));
870 INSIST(tuple == NULL);
871 dns_rdata_reset(&rdata);
872 dns_db_detachnode(db, &newnode);
875 if (result == ISC_R_NOMORE)
876 result = ISC_R_SUCCESS;
880 dns_dbiterator_destroy(&dbit);
881 if (dns_rdataset_isassociated(&rdataset))
882 dns_rdataset_disassociate(&rdataset);
884 dns_db_detachnode(db, &node);
886 dns_db_detachnode(db, &newnode);
891 * Add NSEC3 records for "name", recording the change in "diff".
892 * The existing NSEC3 records are removed.
895 dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
896 dns_name_t *name, dns_ttl_t nsecttl,
897 isc_boolean_t unsecure, dns_diff_t *diff)
899 dns_dbnode_t *node = NULL;
900 dns_rdata_nsec3param_t nsec3param;
901 dns_rdataset_t rdataset;
904 dns_rdataset_init(&rdataset);
907 * Find the NSEC3 parameters for this zone.
909 result = dns_db_getoriginnode(db, &node);
910 if (result != ISC_R_SUCCESS)
913 result = dns_db_findrdataset(db, node, version,
914 dns_rdatatype_nsec3param, 0, 0,
916 dns_db_detachnode(db, &node);
917 if (result == ISC_R_NOTFOUND)
918 return (ISC_R_SUCCESS);
919 if (result != ISC_R_SUCCESS)
923 * Update each active NSEC3 chain.
925 for (result = dns_rdataset_first(&rdataset);
926 result == ISC_R_SUCCESS;
927 result = dns_rdataset_next(&rdataset)) {
928 dns_rdata_t rdata = DNS_RDATA_INIT;
930 dns_rdataset_current(&rdataset, &rdata);
931 dns_rdata_tostruct(&rdata, &nsec3param, NULL);
933 #ifdef RFC5155_STRICT
934 if (nsec3param.flags != 0)
937 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
939 if (better_param(&rdataset, &rdata))
944 * We have a active chain. Update it.
946 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
947 nsecttl, unsecure, diff));
949 if (result == ISC_R_NOMORE)
950 result = ISC_R_SUCCESS;
953 if (dns_rdataset_isassociated(&rdataset))
954 dns_rdataset_disassociate(&rdataset);
956 dns_db_detachnode(db, &node);
962 * Determine whether any NSEC3 records that were associated with
963 * 'name' should be deleted or if they should continue to exist.
964 * ISC_TRUE indicates they should be deleted.
965 * ISC_FALSE indicates they should be retained.
968 deleteit(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
969 isc_boolean_t *yesno)
972 dns_fixedname_t foundname;
973 dns_fixedname_init(&foundname);
975 result = dns_db_find(db, name, ver, dns_rdatatype_any,
976 DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
977 (isc_stdtime_t) 0, NULL,
978 dns_fixedname_name(&foundname),
980 if (result == DNS_R_EMPTYNAME || result == ISC_R_SUCCESS ||
981 result == DNS_R_ZONECUT) {
983 return (ISC_R_SUCCESS);
985 if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
986 result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
988 return (ISC_R_SUCCESS);
998 dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
999 const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
1001 dns_dbiterator_t *dbit = NULL;
1002 dns_dbnode_t *node = NULL;
1003 dns_difftuple_t *tuple = NULL;
1004 dns_fixedname_t fixed;
1005 dns_fixedname_t fprev;
1007 dns_name_t *hashname;
1011 dns_rdata_nsec3_t nsec3;
1012 dns_rdata_t rdata = DNS_RDATA_INIT;
1013 dns_rdataset_t rdataset;
1015 isc_boolean_t yesno;
1016 isc_buffer_t buffer;
1017 isc_result_t result;
1018 unsigned char *salt;
1019 unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
1020 unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
1021 unsigned int iterations;
1022 unsigned int labels;
1024 unsigned int salt_length;
1026 dns_fixedname_init(&fixed);
1027 hashname = dns_fixedname_name(&fixed);
1028 dns_fixedname_init(&fprev);
1029 prev = dns_fixedname_name(&fprev);
1031 dns_rdataset_init(&rdataset);
1033 origin = dns_db_origin(db);
1038 hash = nsec3param->hash;
1039 iterations = nsec3param->iterations;
1040 salt_length = nsec3param->salt_length;
1041 salt = nsec3param->salt;
1044 * If this is the first NSEC3 in the chain nexthash will
1045 * remain pointing to itself.
1047 next_length = sizeof(nexthash);
1048 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1049 name, origin, hash, iterations,
1050 salt, salt_length));
1052 CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
1054 result = dns_dbiterator_seek(dbit, hashname);
1055 if (result == ISC_R_NOTFOUND)
1057 if (result != ISC_R_SUCCESS)
1060 CHECK(dns_dbiterator_current(dbit, &node, NULL));
1061 CHECK(dns_dbiterator_pause(dbit));
1062 result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
1063 0, (isc_stdtime_t) 0, &rdataset, NULL);
1064 dns_db_detachnode(db, &node);
1065 if (result == ISC_R_NOTFOUND)
1067 if (result != ISC_R_SUCCESS)
1071 * If we find a existing NSEC3 for this chain then save the
1074 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1075 if (result == ISC_R_SUCCESS) {
1076 next_length = nsec3.next_length;
1077 INSIST(next_length <= sizeof(nexthash));
1078 memcpy(nexthash, nsec3.next, next_length);
1080 dns_rdataset_disassociate(&rdataset);
1081 if (result == ISC_R_NOMORE)
1083 if (result != ISC_R_SUCCESS)
1087 * Find the previous NSEC3 and update it.
1091 result = dns_dbiterator_prev(dbit);
1092 if (result == ISC_R_NOMORE) {
1094 CHECK(dns_dbiterator_last(dbit));
1096 CHECK(dns_dbiterator_current(dbit, &node, prev));
1097 CHECK(dns_dbiterator_pause(dbit));
1098 result = dns_db_findrdataset(db, node, version,
1099 dns_rdatatype_nsec3, 0,
1100 (isc_stdtime_t) 0, &rdataset,
1102 dns_db_detachnode(db, &node);
1103 if (result != ISC_R_SUCCESS)
1105 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1106 if (result == ISC_R_NOMORE) {
1107 dns_rdataset_disassociate(&rdataset);
1110 if (result != ISC_R_SUCCESS)
1114 * Delete the old previous NSEC3.
1116 CHECK(delete(db, version, prev, nsec3param, diff));
1119 * Fixup the previous NSEC3.
1121 nsec3.next = nexthash;
1122 nsec3.next_length = next_length;
1123 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
1124 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1125 dns_rdatatype_nsec3, &nsec3,
1127 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
1128 rdataset.ttl, &rdata, &tuple));
1129 CHECK(do_one_tuple(&tuple, db, version, diff));
1130 dns_rdata_reset(&rdata);
1131 dns_rdataset_disassociate(&rdataset);
1136 * Delete the old NSEC3 and record the change.
1138 CHECK(delete(db, version, hashname, nsec3param, diff));
1141 * Delete NSEC3 records for now non active nodes.
1143 dns_name_init(&empty, NULL);
1144 dns_name_clone(name, &empty);
1146 labels = dns_name_countlabels(&empty) - 1;
1147 if (labels <= dns_name_countlabels(origin))
1149 dns_name_getlabelsequence(&empty, 1, labels, &empty);
1150 CHECK(deleteit(db, version, &empty, &yesno));
1154 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1155 &empty, origin, hash, iterations,
1156 salt, salt_length));
1157 result = dns_dbiterator_seek(dbit, hashname);
1158 if (result == ISC_R_NOTFOUND)
1160 if (result != ISC_R_SUCCESS)
1163 CHECK(dns_dbiterator_current(dbit, &node, NULL));
1164 CHECK(dns_dbiterator_pause(dbit));
1165 result = dns_db_findrdataset(db, node, version,
1166 dns_rdatatype_nsec3, 0,
1167 (isc_stdtime_t) 0, &rdataset,
1169 dns_db_detachnode(db, &node);
1170 if (result == ISC_R_NOTFOUND)
1172 if (result != ISC_R_SUCCESS)
1175 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1176 if (result == ISC_R_SUCCESS) {
1177 next_length = nsec3.next_length;
1178 INSIST(next_length <= sizeof(nexthash));
1179 memcpy(nexthash, nsec3.next, next_length);
1181 dns_rdataset_disassociate(&rdataset);
1182 if (result == ISC_R_NOMORE)
1184 if (result != ISC_R_SUCCESS)
1189 result = dns_dbiterator_prev(dbit);
1190 if (result == ISC_R_NOMORE) {
1192 CHECK(dns_dbiterator_last(dbit));
1194 CHECK(dns_dbiterator_current(dbit, &node, prev));
1195 CHECK(dns_dbiterator_pause(dbit));
1196 result = dns_db_findrdataset(db, node, version,
1197 dns_rdatatype_nsec3, 0,
1200 dns_db_detachnode(db, &node);
1201 if (result != ISC_R_SUCCESS)
1203 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1204 if (result == ISC_R_NOMORE) {
1205 dns_rdataset_disassociate(&rdataset);
1208 if (result != ISC_R_SUCCESS)
1212 * Delete the old previous NSEC3.
1214 CHECK(delete(db, version, prev, nsec3param, diff));
1217 * Fixup the previous NSEC3.
1219 nsec3.next = nexthash;
1220 nsec3.next_length = next_length;
1221 isc_buffer_init(&buffer, nsec3buf,
1223 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1224 dns_rdatatype_nsec3, &nsec3,
1226 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
1227 prev, rdataset.ttl, &rdata,
1229 CHECK(do_one_tuple(&tuple, db, version, diff));
1230 dns_rdata_reset(&rdata);
1231 dns_rdataset_disassociate(&rdataset);
1238 * Delete the old NSEC3 and record the change.
1240 CHECK(delete(db, version, hashname, nsec3param, diff));
1244 result = ISC_R_SUCCESS;
1248 dns_dbiterator_destroy(&dbit);
1249 if (dns_rdataset_isassociated(&rdataset))
1250 dns_rdataset_disassociate(&rdataset);
1252 dns_db_detachnode(db, &node);
1257 dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1260 dns_dbnode_t *node = NULL;
1261 dns_rdata_nsec3param_t nsec3param;
1262 dns_rdataset_t rdataset;
1263 isc_result_t result;
1265 dns_rdataset_init(&rdataset);
1268 * Find the NSEC3 parameters for this zone.
1270 result = dns_db_getoriginnode(db, &node);
1271 if (result != ISC_R_SUCCESS)
1274 result = dns_db_findrdataset(db, node, version,
1275 dns_rdatatype_nsec3param, 0, 0,
1277 dns_db_detachnode(db, &node);
1278 if (result == ISC_R_NOTFOUND)
1279 return (ISC_R_SUCCESS);
1280 if (result != ISC_R_SUCCESS)
1284 * Update each active NSEC3 chain.
1286 for (result = dns_rdataset_first(&rdataset);
1287 result == ISC_R_SUCCESS;
1288 result = dns_rdataset_next(&rdataset)) {
1289 dns_rdata_t rdata = DNS_RDATA_INIT;
1291 dns_rdataset_current(&rdataset, &rdata);
1292 dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1294 #ifdef RFC5155_STRICT
1295 if (nsec3param.flags != 0)
1298 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
1300 if (better_param(&rdataset, &rdata))
1305 * We have a active chain. Update it.
1307 CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1309 if (result == ISC_R_NOMORE)
1310 result = ISC_R_SUCCESS;
1313 if (dns_rdataset_isassociated(&rdataset))
1314 dns_rdataset_disassociate(&rdataset);
1316 dns_db_detachnode(db, &node);
1322 dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
1323 isc_boolean_t complete, isc_boolean_t *answer)
1325 dns_dbnode_t *node = NULL;
1326 dns_rdataset_t rdataset;
1327 dns_rdata_nsec3param_t nsec3param;
1328 isc_result_t result;
1330 REQUIRE(answer != NULL);
1332 dns_rdataset_init(&rdataset);
1334 result = dns_db_getoriginnode(db, &node);
1335 if (result != ISC_R_SUCCESS)
1338 result = dns_db_findrdataset(db, node, version,
1339 dns_rdatatype_nsec3param, 0, 0,
1341 dns_db_detachnode(db, &node);
1343 if (result == ISC_R_NOTFOUND) {
1344 *answer = ISC_FALSE;
1345 return (ISC_R_SUCCESS);
1347 if (result != ISC_R_SUCCESS)
1349 for (result = dns_rdataset_first(&rdataset);
1350 result == ISC_R_SUCCESS;
1351 result = dns_rdataset_next(&rdataset)) {
1352 dns_rdata_t rdata = DNS_RDATA_INIT;
1354 dns_rdataset_current(&rdataset, &rdata);
1355 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1356 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1358 if ((nsec3param.flags) == 0 ||
1359 (!complete && CREATE(nsec3param.flags)))
1362 dns_rdataset_disassociate(&rdataset);
1363 if (result == ISC_R_SUCCESS)
1365 if (result == ISC_R_NOMORE) {
1366 *answer = ISC_FALSE;
1367 result = ISC_R_SUCCESS;
1373 dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
1374 isc_mem_t *mctx, unsigned int *iterationsp)
1376 dns_dbnode_t *node = NULL;
1377 dns_rdataset_t rdataset;
1378 dst_key_t *key = NULL;
1379 isc_buffer_t buffer;
1380 isc_result_t result;
1381 isc_uint16_t bits, minbits = 4096;
1383 result = dns_db_getoriginnode(db, &node);
1384 if (result != ISC_R_SUCCESS)
1387 dns_rdataset_init(&rdataset);
1388 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
1389 0, 0, &rdataset, NULL);
1390 dns_db_detachnode(db, &node);
1391 if (result == ISC_R_NOTFOUND) {
1393 return (ISC_R_SUCCESS);
1395 if (result != ISC_R_SUCCESS)
1398 for (result = dns_rdataset_first(&rdataset);
1399 result == ISC_R_SUCCESS;
1400 result = dns_rdataset_next(&rdataset)) {
1401 dns_rdata_t rdata = DNS_RDATA_INIT;
1403 dns_rdataset_current(&rdataset, &rdata);
1404 isc_buffer_init(&buffer, rdata.data, rdata.length);
1405 isc_buffer_add(&buffer, rdata.length);
1406 CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
1407 &buffer, mctx, &key));
1408 bits = dst_key_getbits(key);
1413 if (result != ISC_R_NOMORE)
1416 if (minbits <= 1024)
1418 else if (minbits <= 2048)
1421 *iterationsp = 2500;
1422 result = ISC_R_SUCCESS;
1425 if (dns_rdataset_isassociated(&rdataset))
1426 dns_rdataset_disassociate(&rdataset);