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.2 2009/06/04 02:56:14 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;
91 unsigned char *nsec_bits, *bm;
92 unsigned int max_type;
93 dns_rdatasetiter_t *rdsiter;
96 REQUIRE(salt_length < 256U);
97 REQUIRE(hash_length < 256U);
98 REQUIRE(flags <= 0xffU);
99 REQUIRE(hashalg <= 0xffU);
100 REQUIRE(iterations <= 0xffffU);
104 REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
108 memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
115 *p++ = iterations >> 8;
119 memcpy(p, salt, salt_length);
123 memcpy(p, nexthash, hash_length);
126 r.length = p - buffer;
130 * Use the end of the space for a raw bitmap leaving enough
131 * space for the window identifiers and length octets.
133 bm = r.base + r.length + 512;
134 nsec_bits = r.base + r.length;
137 goto collapse_bitmap;
138 dns_rdataset_init(&rdataset);
140 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
141 if (result != ISC_R_SUCCESS)
144 for (result = dns_rdatasetiter_first(rdsiter);
145 result == ISC_R_SUCCESS;
146 result = dns_rdatasetiter_next(rdsiter))
148 dns_rdatasetiter_current(rdsiter, &rdataset);
149 if (rdataset.type != dns_rdatatype_nsec &&
150 rdataset.type != dns_rdatatype_nsec3 &&
151 rdataset.type != dns_rdatatype_rrsig) {
152 if (rdataset.type > max_type)
153 max_type = rdataset.type;
154 set_bit(bm, rdataset.type, 1);
155 /* Don't set RRSIG for insecure delegation. */
156 if (rdataset.type != dns_rdatatype_ns)
159 dns_rdataset_disassociate(&rdataset);
162 if (dns_rdatatype_rrsig > max_type)
163 max_type = dns_rdatatype_rrsig;
164 set_bit(bm, dns_rdatatype_rrsig, 1);
168 * At zone cuts, deny the existence of glue in the parent zone.
170 if (bit_isset(bm, dns_rdatatype_ns) &&
171 ! bit_isset(bm, dns_rdatatype_soa)) {
172 for (i = 0; i <= max_type; i++) {
173 if (bit_isset(bm, i) &&
174 ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
179 dns_rdatasetiter_destroy(&rdsiter);
180 if (result != ISC_R_NOMORE)
184 for (window = 0; window < 256; window++) {
185 if (window * 256 > max_type)
187 for (octet = 31; octet >= 0; octet--)
188 if (bm[window * 32 + octet] != 0)
192 nsec_bits[0] = window;
193 nsec_bits[1] = octet + 1;
195 * Note: potentially overlapping move.
197 memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
198 nsec_bits += 3 + octet;
200 r.length = nsec_bits - r.base;
201 INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
202 dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
204 return (ISC_R_SUCCESS);
208 dns_nsec3_typepresent(dns_rdata_t *rdata, dns_rdatatype_t type) {
209 dns_rdata_nsec3_t nsec3;
211 isc_boolean_t present;
212 unsigned int i, len, window;
214 REQUIRE(rdata != NULL);
215 REQUIRE(rdata->type == dns_rdatatype_nsec3);
217 /* This should never fail */
218 result = dns_rdata_tostruct(rdata, &nsec3, NULL);
219 INSIST(result == ISC_R_SUCCESS);
222 for (i = 0; i < nsec3.len; i += len) {
223 INSIST(i + 2 <= nsec3.len);
224 window = nsec3.typebits[i];
225 len = nsec3.typebits[i + 1];
226 INSIST(len > 0 && len <= 32);
228 INSIST(i + len <= nsec3.len);
229 if (window * 256 > type)
231 if ((window + 1) * 256 <= type)
233 if (type < (window * 256) + len * 8)
234 present = ISC_TF(bit_isset(&nsec3.typebits[i],
238 dns_rdata_freestruct(&nsec3);
243 dns_nsec3_hashname(dns_fixedname_t *result,
244 unsigned char rethash[NSEC3_MAX_HASH_LENGTH],
245 size_t *hash_length, dns_name_t *name, dns_name_t *origin,
246 dns_hash_t hashalg, unsigned int iterations,
247 const unsigned char *salt, size_t saltlength)
249 unsigned char hash[NSEC3_MAX_HASH_LENGTH];
250 unsigned char nametext[DNS_NAME_FORMATSIZE];
251 dns_fixedname_t fixed;
252 dns_name_t *downcased;
253 isc_buffer_t namebuffer;
260 memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
262 dns_fixedname_init(&fixed);
263 downcased = dns_fixedname_name(&fixed);
264 dns_name_downcase(name, downcased, NULL);
266 /* hash the node name */
267 len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
268 downcased->ndata, downcased->length);
270 return (DNS_R_BADALG);
272 if (hash_length != NULL)
275 /* convert the hash to base32hex */
276 region.base = rethash;
278 isc_buffer_init(&namebuffer, nametext, sizeof nametext);
279 isc_base32hex_totext(®ion, 1, "", &namebuffer);
281 /* convert the hex to a domain name */
282 dns_fixedname_init(result);
283 return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
288 dns_nsec3_hashlength(dns_hash_t hash) {
291 case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
297 dns_nsec3_supportedhash(dns_hash_t hash) {
299 case dns_hash_sha1: return (ISC_TRUE);
305 * Update a single RR in version 'ver' of 'db' and log the
309 * \li '*tuple' == NULL. Either the tuple is freed, or its
310 * ownership has been transferred to the diff.
313 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
316 dns_diff_t temp_diff;
320 * Create a singleton diff.
322 dns_diff_init(diff->mctx, &temp_diff);
323 temp_diff.resign = diff->resign;
324 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
327 * Apply it to the database.
329 result = dns_diff_apply(&temp_diff, db, ver);
330 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
331 if (result != ISC_R_SUCCESS) {
332 dns_difftuple_free(tuple);
337 * Merge it into the current pending journal entry.
339 dns_diff_appendminimal(diff, tuple);
342 * Do not clear temp_diff.
344 return (ISC_R_SUCCESS);
348 * Set '*exists' to true iff the given name exists, to false otherwise.
351 name_exists(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
352 isc_boolean_t *exists)
355 dns_dbnode_t *node = NULL;
356 dns_rdatasetiter_t *iter = NULL;
358 result = dns_db_findnode(db, name, ISC_FALSE, &node);
359 if (result == ISC_R_NOTFOUND) {
361 return (ISC_R_SUCCESS);
363 if (result != ISC_R_SUCCESS)
366 result = dns_db_allrdatasets(db, node, version,
367 (isc_stdtime_t) 0, &iter);
368 if (result != ISC_R_SUCCESS)
371 result = dns_rdatasetiter_first(iter);
372 if (result == ISC_R_SUCCESS) {
374 } else if (result == ISC_R_NOMORE) {
376 result = ISC_R_SUCCESS;
379 dns_rdatasetiter_destroy(&iter);
382 dns_db_detachnode(db, &node);
387 match_nsec3param(const dns_rdata_nsec3_t *nsec3,
388 const dns_rdata_nsec3param_t *nsec3param)
390 if (nsec3->hash == nsec3param->hash &&
391 nsec3->iterations == nsec3param->iterations &&
392 nsec3->salt_length == nsec3param->salt_length &&
393 !memcmp(nsec3->salt, nsec3param->salt, nsec3->salt_length))
399 * Delete NSEC3 records at "name" which match "param", recording the
403 delete(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
404 const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
406 dns_dbnode_t *node = NULL ;
407 dns_difftuple_t *tuple = NULL;
408 dns_rdata_nsec3_t nsec3;
409 dns_rdataset_t rdataset;
412 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
413 if (result == ISC_R_NOTFOUND)
414 return (ISC_R_SUCCESS);
415 if (result != ISC_R_SUCCESS)
418 dns_rdataset_init(&rdataset);
419 result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
420 (isc_stdtime_t) 0, &rdataset, NULL);
422 if (result == ISC_R_NOTFOUND) {
423 result = ISC_R_SUCCESS;
426 if (result != ISC_R_SUCCESS)
429 for (result = dns_rdataset_first(&rdataset);
430 result == ISC_R_SUCCESS;
431 result = dns_rdataset_next(&rdataset))
433 dns_rdata_t rdata = DNS_RDATA_INIT;
434 dns_rdataset_current(&rdataset, &rdata);
435 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
437 if (!match_nsec3param(&nsec3, nsec3param))
440 result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
441 rdataset.ttl, &rdata, &tuple);
442 if (result != ISC_R_SUCCESS)
444 result = do_one_tuple(&tuple, db, version, diff);
445 if (result != ISC_R_SUCCESS)
448 if (result != ISC_R_NOMORE)
450 result = ISC_R_SUCCESS;
453 dns_rdataset_disassociate(&rdataset);
455 dns_db_detachnode(db, &node);
460 #ifndef RFC5155_STRICT
462 better_param(dns_rdataset_t *nsec3paramset, dns_rdata_t *param) {
463 dns_rdataset_t rdataset;
466 if (REMOVE(param->data[1]))
469 dns_rdataset_init(&rdataset);
470 dns_rdataset_clone(nsec3paramset, &rdataset);
471 for (result = dns_rdataset_first(&rdataset);
472 result == ISC_R_SUCCESS;
473 result = dns_rdataset_next(&rdataset)) {
474 dns_rdata_t rdata = DNS_RDATA_INIT;
475 dns_rdataset_current(&rdataset, &rdata);
476 if (rdata.length != param->length)
478 if (rdata.data[0] != param->data[0] ||
479 REMOVE(rdata.data[1]) ||
480 rdata.data[2] != param->data[2] ||
481 rdata.data[3] != param->data[3] ||
482 rdata.data[4] != param->data[4] ||
483 memcmp(&rdata.data[5], ¶m->data[5], param->data[4]))
485 if (CREATE(rdata.data[1]) && !CREATE(param->data[1])) {
486 dns_rdataset_disassociate(&rdataset);
490 dns_rdataset_disassociate(&rdataset);
496 find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
497 const dns_rdata_nsec3param_t *nsec3param)
500 for (result = dns_rdataset_first(rdataset);
501 result == ISC_R_SUCCESS;
502 result = dns_rdataset_next(rdataset)) {
503 dns_rdata_t rdata = DNS_RDATA_INIT;
505 dns_rdataset_current(rdataset, &rdata);
506 CHECK(dns_rdata_tostruct(&rdata, nsec3, NULL));
507 dns_rdata_reset(&rdata);
508 if (match_nsec3param(nsec3, nsec3param))
516 dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version,
517 dns_name_t *name, const dns_rdata_nsec3param_t *nsec3param,
518 dns_ttl_t nsecttl, isc_boolean_t unsecure, dns_diff_t *diff)
520 dns_dbiterator_t *dbit = NULL;
521 dns_dbnode_t *node = NULL;
522 dns_dbnode_t *newnode = NULL;
523 dns_difftuple_t *tuple = NULL;
524 dns_fixedname_t fixed;
525 dns_fixedname_t fprev;
527 dns_name_t *hashname;
531 dns_rdata_nsec3_t nsec3;
532 dns_rdata_t rdata = DNS_RDATA_INIT;
533 dns_rdataset_t rdataset;
535 isc_boolean_t exists;
536 isc_boolean_t remove_unsecure = ISC_FALSE;
540 unsigned char *old_next;
542 unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
543 unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
544 unsigned int iterations;
547 unsigned int old_length;
548 unsigned int salt_length;
550 dns_fixedname_init(&fixed);
551 hashname = dns_fixedname_name(&fixed);
552 dns_fixedname_init(&fprev);
553 prev = dns_fixedname_name(&fprev);
555 dns_rdataset_init(&rdataset);
557 origin = dns_db_origin(db);
562 hash = nsec3param->hash;
563 iterations = nsec3param->iterations;
564 salt_length = nsec3param->salt_length;
565 salt = nsec3param->salt;
568 * Default flags for a new chain.
570 flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
573 * If this is the first NSEC3 in the chain nexthash will
574 * remain pointing to itself.
576 next_length = sizeof(nexthash);
577 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
578 name, origin, hash, iterations,
582 * Create the node if it doesn't exist and hold
583 * a reference to it until we have added the NSEC3.
585 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
588 * Seek the iterator to the 'newnode'.
590 CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
591 CHECK(dns_dbiterator_seek(dbit, hashname));
592 CHECK(dns_dbiterator_pause(dbit));
593 result = dns_db_findrdataset(db, newnode, version, dns_rdatatype_nsec3,
594 0, (isc_stdtime_t) 0, &rdataset, NULL);
596 * If we updating a existing NSEC3 then find its
599 if (result == ISC_R_SUCCESS) {
600 result = find_nsec3(&nsec3, &rdataset, nsec3param);
601 if (result == ISC_R_SUCCESS) {
602 if (!CREATE(nsec3param->flags))
604 next_length = nsec3.next_length;
605 INSIST(next_length <= sizeof(nexthash));
606 memcpy(nexthash, nsec3.next, next_length);
607 dns_rdataset_disassociate(&rdataset);
609 * If the NSEC3 is not for a unsecure delegation then
610 * we are just updating it. If it is for a unsecure
611 * delegation then we need find out if we need to
612 * remove the NSEC3 record or not by examining the
613 * previous NSEC3 record.
618 remove_unsecure = ISC_TRUE;
620 dns_rdataset_disassociate(&rdataset);
621 if (result != ISC_R_NOMORE)
627 * Find the previous NSEC3 (if any) and update it if required.
631 result = dns_dbiterator_prev(dbit);
632 if (result == ISC_R_NOMORE) {
634 CHECK(dns_dbiterator_last(dbit));
636 CHECK(dns_dbiterator_current(dbit, &node, prev));
637 CHECK(dns_dbiterator_pause(dbit));
638 result = dns_db_findrdataset(db, node, version,
639 dns_rdatatype_nsec3, 0,
640 (isc_stdtime_t) 0, &rdataset,
642 dns_db_detachnode(db, &node);
643 if (result != ISC_R_SUCCESS)
646 result = find_nsec3(&nsec3, &rdataset, nsec3param);
647 if (result == ISC_R_NOMORE) {
648 dns_rdataset_disassociate(&rdataset);
651 if (result != ISC_R_SUCCESS)
654 if (remove_unsecure) {
655 dns_rdataset_disassociate(&rdataset);
657 * We have found the previous NSEC3 record and can now
658 * see if the existing NSEC3 record needs to be
659 * updated or deleted.
661 if (!OPTOUT(nsec3.flags)) {
663 * Just update the NSEC3 record.
668 * This is actually a deletion not a add.
670 result = dns_nsec3_delnsec3(db, version, name,
676 * Is this is a unsecure delegation we are adding?
677 * If so no change is required.
679 if (OPTOUT(nsec3.flags) && unsecure) {
680 dns_rdataset_disassociate(&rdataset);
685 old_next = nsec3.next;
686 old_length = nsec3.next_length;
689 * Delete the old previous NSEC3.
691 CHECK(delete(db, version, prev, nsec3param, diff));
694 * Fixup the previous NSEC3.
696 nsec3.next = nexthash;
697 nsec3.next_length = next_length;
698 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
699 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
700 dns_rdatatype_nsec3, &nsec3,
702 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
703 rdataset.ttl, &rdata, &tuple));
704 CHECK(do_one_tuple(&tuple, db, version, diff));
705 INSIST(old_length <= sizeof(nexthash));
706 memcpy(nexthash, old_next, old_length);
707 if (!CREATE(nsec3param->flags))
709 dns_rdata_reset(&rdata);
710 dns_rdataset_disassociate(&rdataset);
716 * Create the NSEC3 RDATA.
718 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
719 CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
720 salt, salt_length, nexthash, next_length,
722 dns_db_detachnode(db, &node);
725 * Delete the old NSEC3 and record the change.
727 CHECK(delete(db, version, hashname, nsec3param, diff));
729 * Add the new NSEC3 and record the change.
731 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
732 hashname, nsecttl, &rdata, &tuple));
733 CHECK(do_one_tuple(&tuple, db, version, diff));
734 INSIST(tuple == NULL);
735 dns_rdata_reset(&rdata);
736 dns_db_detachnode(db, &newnode);
739 * Add missing NSEC3 records for empty nodes
741 dns_name_init(&empty, NULL);
742 dns_name_clone(name, &empty);
744 labels = dns_name_countlabels(&empty) - 1;
745 if (labels <= dns_name_countlabels(origin))
747 dns_name_getlabelsequence(&empty, 1, labels, &empty);
748 CHECK(name_exists(db, version, &empty, &exists));
751 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
752 &empty, origin, hash, iterations,
756 * Create the node if it doesn't exist and hold
757 * a reference to it until we have added the NSEC3
758 * or we discover we don't need to add make a change.
760 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
761 result = dns_db_findrdataset(db, newnode, version,
762 dns_rdatatype_nsec3, 0,
763 (isc_stdtime_t) 0, &rdataset,
765 if (result == ISC_R_SUCCESS) {
766 result = find_nsec3(&nsec3, &rdataset, nsec3param);
767 dns_rdataset_disassociate(&rdataset);
768 if (result == ISC_R_SUCCESS) {
769 dns_db_detachnode(db, &newnode);
772 if (result != ISC_R_NOMORE)
777 * Find the previous NSEC3 and update it.
779 CHECK(dns_dbiterator_seek(dbit, hashname));
782 result = dns_dbiterator_prev(dbit);
783 if (result == ISC_R_NOMORE) {
785 CHECK(dns_dbiterator_last(dbit));
787 CHECK(dns_dbiterator_current(dbit, &node, prev));
788 CHECK(dns_dbiterator_pause(dbit));
789 result = dns_db_findrdataset(db, node, version,
790 dns_rdatatype_nsec3, 0,
793 dns_db_detachnode(db, &node);
794 if (result != ISC_R_SUCCESS)
796 result = find_nsec3(&nsec3, &rdataset, nsec3param);
797 if (result == ISC_R_NOMORE) {
798 dns_rdataset_disassociate(&rdataset);
801 if (result != ISC_R_SUCCESS)
804 old_next = nsec3.next;
805 old_length = nsec3.next_length;
808 * Delete the old previous NSEC3.
810 CHECK(delete(db, version, prev, nsec3param, diff));
813 * Fixup the previous NSEC3.
815 nsec3.next = nexthash;
816 nsec3.next_length = next_length;
817 isc_buffer_init(&buffer, nsec3buf,
819 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
820 dns_rdatatype_nsec3, &nsec3,
822 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
823 prev, rdataset.ttl, &rdata,
825 CHECK(do_one_tuple(&tuple, db, version, diff));
826 INSIST(old_length <= sizeof(nexthash));
827 memcpy(nexthash, old_next, old_length);
828 if (!CREATE(nsec3param->flags))
830 dns_rdata_reset(&rdata);
831 dns_rdataset_disassociate(&rdataset);
838 * Create the NSEC3 RDATA for the empty node.
840 CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
841 iterations, salt, salt_length,
842 nexthash, next_length, nsec3buf,
845 * Delete the old NSEC3 and record the change.
847 CHECK(delete(db, version, hashname, nsec3param, diff));
850 * Add the new NSEC3 and record the change.
852 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
853 hashname, nsecttl, &rdata, &tuple));
854 CHECK(do_one_tuple(&tuple, db, version, diff));
855 INSIST(tuple == NULL);
856 dns_rdata_reset(&rdata);
857 dns_db_detachnode(db, &newnode);
860 if (result == ISC_R_NOMORE)
861 result = ISC_R_SUCCESS;
865 dns_dbiterator_destroy(&dbit);
866 if (dns_rdataset_isassociated(&rdataset))
867 dns_rdataset_disassociate(&rdataset);
869 dns_db_detachnode(db, &node);
871 dns_db_detachnode(db, &newnode);
876 * Add NSEC3 records for "name", recording the change in "diff".
877 * The existing NSEC3 records are removed.
880 dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
881 dns_name_t *name, dns_ttl_t nsecttl,
882 isc_boolean_t unsecure, dns_diff_t *diff)
884 dns_dbnode_t *node = NULL;
885 dns_rdata_nsec3param_t nsec3param;
886 dns_rdataset_t rdataset;
889 dns_rdataset_init(&rdataset);
892 * Find the NSEC3 parameters for this zone.
894 result = dns_db_getoriginnode(db, &node);
895 if (result != ISC_R_SUCCESS)
898 result = dns_db_findrdataset(db, node, version,
899 dns_rdatatype_nsec3param, 0, 0,
901 dns_db_detachnode(db, &node);
902 if (result == ISC_R_NOTFOUND)
903 return (ISC_R_SUCCESS);
904 if (result != ISC_R_SUCCESS)
908 * Update each active NSEC3 chain.
910 for (result = dns_rdataset_first(&rdataset);
911 result == ISC_R_SUCCESS;
912 result = dns_rdataset_next(&rdataset)) {
913 dns_rdata_t rdata = DNS_RDATA_INIT;
915 dns_rdataset_current(&rdataset, &rdata);
916 dns_rdata_tostruct(&rdata, &nsec3param, NULL);
918 #ifdef RFC5155_STRICT
919 if (nsec3param.flags != 0)
922 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
924 if (better_param(&rdataset, &rdata))
929 * We have a active chain. Update it.
931 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
932 nsecttl, unsecure, diff));
934 if (result == ISC_R_NOMORE)
935 result = ISC_R_SUCCESS;
938 if (dns_rdataset_isassociated(&rdataset))
939 dns_rdataset_disassociate(&rdataset);
941 dns_db_detachnode(db, &node);
947 * Determine whether any NSEC3 records that were associated with
948 * 'name' should be deleted or if they should continue to exist.
949 * ISC_TRUE indicates they should be deleted.
950 * ISC_FALSE indicates they should be retained.
953 deleteit(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
954 isc_boolean_t *yesno)
957 dns_fixedname_t foundname;
958 dns_fixedname_init(&foundname);
960 result = dns_db_find(db, name, ver, dns_rdatatype_any,
961 DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
962 (isc_stdtime_t) 0, NULL,
963 dns_fixedname_name(&foundname),
965 if (result == DNS_R_EMPTYNAME || result == ISC_R_SUCCESS ||
966 result == DNS_R_ZONECUT) {
968 return (ISC_R_SUCCESS);
970 if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
971 result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
973 return (ISC_R_SUCCESS);
983 dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
984 const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
986 dns_dbiterator_t *dbit = NULL;
987 dns_dbnode_t *node = NULL;
988 dns_difftuple_t *tuple = NULL;
989 dns_fixedname_t fixed;
990 dns_fixedname_t fprev;
992 dns_name_t *hashname;
996 dns_rdata_nsec3_t nsec3;
997 dns_rdata_t rdata = DNS_RDATA_INIT;
998 dns_rdataset_t rdataset;
1000 isc_boolean_t yesno;
1001 isc_buffer_t buffer;
1002 isc_result_t result;
1003 unsigned char *salt;
1004 unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
1005 unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
1006 unsigned int iterations;
1007 unsigned int labels;
1009 unsigned int salt_length;
1011 dns_fixedname_init(&fixed);
1012 hashname = dns_fixedname_name(&fixed);
1013 dns_fixedname_init(&fprev);
1014 prev = dns_fixedname_name(&fprev);
1016 dns_rdataset_init(&rdataset);
1018 origin = dns_db_origin(db);
1023 hash = nsec3param->hash;
1024 iterations = nsec3param->iterations;
1025 salt_length = nsec3param->salt_length;
1026 salt = nsec3param->salt;
1029 * If this is the first NSEC3 in the chain nexthash will
1030 * remain pointing to itself.
1032 next_length = sizeof(nexthash);
1033 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1034 name, origin, hash, iterations,
1035 salt, salt_length));
1037 CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
1039 result = dns_dbiterator_seek(dbit, hashname);
1040 if (result == ISC_R_NOTFOUND)
1042 if (result != ISC_R_SUCCESS)
1045 CHECK(dns_dbiterator_current(dbit, &node, NULL));
1046 CHECK(dns_dbiterator_pause(dbit));
1047 result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
1048 0, (isc_stdtime_t) 0, &rdataset, NULL);
1049 dns_db_detachnode(db, &node);
1050 if (result == ISC_R_NOTFOUND)
1052 if (result != ISC_R_SUCCESS)
1056 * If we find a existing NSEC3 for this chain then save the
1059 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1060 if (result == ISC_R_SUCCESS) {
1061 next_length = nsec3.next_length;
1062 INSIST(next_length <= sizeof(nexthash));
1063 memcpy(nexthash, nsec3.next, next_length);
1065 dns_rdataset_disassociate(&rdataset);
1066 if (result == ISC_R_NOMORE)
1068 if (result != ISC_R_SUCCESS)
1072 * Find the previous NSEC3 and update it.
1076 result = dns_dbiterator_prev(dbit);
1077 if (result == ISC_R_NOMORE) {
1079 CHECK(dns_dbiterator_last(dbit));
1081 CHECK(dns_dbiterator_current(dbit, &node, prev));
1082 CHECK(dns_dbiterator_pause(dbit));
1083 result = dns_db_findrdataset(db, node, version,
1084 dns_rdatatype_nsec3, 0,
1085 (isc_stdtime_t) 0, &rdataset,
1087 dns_db_detachnode(db, &node);
1088 if (result != ISC_R_SUCCESS)
1090 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1091 if (result == ISC_R_NOMORE) {
1092 dns_rdataset_disassociate(&rdataset);
1095 if (result != ISC_R_SUCCESS)
1099 * Delete the old previous NSEC3.
1101 CHECK(delete(db, version, prev, nsec3param, diff));
1104 * Fixup the previous NSEC3.
1106 nsec3.next = nexthash;
1107 nsec3.next_length = next_length;
1108 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
1109 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1110 dns_rdatatype_nsec3, &nsec3,
1112 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
1113 rdataset.ttl, &rdata, &tuple));
1114 CHECK(do_one_tuple(&tuple, db, version, diff));
1115 dns_rdata_reset(&rdata);
1116 dns_rdataset_disassociate(&rdataset);
1121 * Delete the old NSEC3 and record the change.
1123 CHECK(delete(db, version, hashname, nsec3param, diff));
1126 * Delete NSEC3 records for now non active nodes.
1128 dns_name_init(&empty, NULL);
1129 dns_name_clone(name, &empty);
1131 labels = dns_name_countlabels(&empty) - 1;
1132 if (labels <= dns_name_countlabels(origin))
1134 dns_name_getlabelsequence(&empty, 1, labels, &empty);
1135 CHECK(deleteit(db, version, &empty, &yesno));
1139 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1140 &empty, origin, hash, iterations,
1141 salt, salt_length));
1142 result = dns_dbiterator_seek(dbit, hashname);
1143 if (result == ISC_R_NOTFOUND)
1145 if (result != ISC_R_SUCCESS)
1148 CHECK(dns_dbiterator_current(dbit, &node, NULL));
1149 CHECK(dns_dbiterator_pause(dbit));
1150 result = dns_db_findrdataset(db, node, version,
1151 dns_rdatatype_nsec3, 0,
1152 (isc_stdtime_t) 0, &rdataset,
1154 dns_db_detachnode(db, &node);
1155 if (result == ISC_R_NOTFOUND)
1157 if (result != ISC_R_SUCCESS)
1160 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1161 if (result == ISC_R_SUCCESS) {
1162 next_length = nsec3.next_length;
1163 INSIST(next_length <= sizeof(nexthash));
1164 memcpy(nexthash, nsec3.next, next_length);
1166 dns_rdataset_disassociate(&rdataset);
1167 if (result == ISC_R_NOMORE)
1169 if (result != ISC_R_SUCCESS)
1174 result = dns_dbiterator_prev(dbit);
1175 if (result == ISC_R_NOMORE) {
1177 CHECK(dns_dbiterator_last(dbit));
1179 CHECK(dns_dbiterator_current(dbit, &node, prev));
1180 CHECK(dns_dbiterator_pause(dbit));
1181 result = dns_db_findrdataset(db, node, version,
1182 dns_rdatatype_nsec3, 0,
1185 dns_db_detachnode(db, &node);
1186 if (result != ISC_R_SUCCESS)
1188 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1189 if (result == ISC_R_NOMORE) {
1190 dns_rdataset_disassociate(&rdataset);
1193 if (result != ISC_R_SUCCESS)
1197 * Delete the old previous NSEC3.
1199 CHECK(delete(db, version, prev, nsec3param, diff));
1202 * Fixup the previous NSEC3.
1204 nsec3.next = nexthash;
1205 nsec3.next_length = next_length;
1206 isc_buffer_init(&buffer, nsec3buf,
1208 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1209 dns_rdatatype_nsec3, &nsec3,
1211 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
1212 prev, rdataset.ttl, &rdata,
1214 CHECK(do_one_tuple(&tuple, db, version, diff));
1215 dns_rdata_reset(&rdata);
1216 dns_rdataset_disassociate(&rdataset);
1223 * Delete the old NSEC3 and record the change.
1225 CHECK(delete(db, version, hashname, nsec3param, diff));
1229 result = ISC_R_SUCCESS;
1233 dns_dbiterator_destroy(&dbit);
1234 if (dns_rdataset_isassociated(&rdataset))
1235 dns_rdataset_disassociate(&rdataset);
1237 dns_db_detachnode(db, &node);
1242 dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1245 dns_dbnode_t *node = NULL;
1246 dns_rdata_nsec3param_t nsec3param;
1247 dns_rdataset_t rdataset;
1248 isc_result_t result;
1250 dns_rdataset_init(&rdataset);
1253 * Find the NSEC3 parameters for this zone.
1255 result = dns_db_getoriginnode(db, &node);
1256 if (result != ISC_R_SUCCESS)
1259 result = dns_db_findrdataset(db, node, version,
1260 dns_rdatatype_nsec3param, 0, 0,
1262 dns_db_detachnode(db, &node);
1263 if (result == ISC_R_NOTFOUND)
1264 return (ISC_R_SUCCESS);
1265 if (result != ISC_R_SUCCESS)
1269 * Update each active NSEC3 chain.
1271 for (result = dns_rdataset_first(&rdataset);
1272 result == ISC_R_SUCCESS;
1273 result = dns_rdataset_next(&rdataset)) {
1274 dns_rdata_t rdata = DNS_RDATA_INIT;
1276 dns_rdataset_current(&rdataset, &rdata);
1277 dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1279 #ifdef RFC5155_STRICT
1280 if (nsec3param.flags != 0)
1283 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
1285 if (better_param(&rdataset, &rdata))
1290 * We have a active chain. Update it.
1292 CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1294 if (result == ISC_R_NOMORE)
1295 result = ISC_R_SUCCESS;
1298 if (dns_rdataset_isassociated(&rdataset))
1299 dns_rdataset_disassociate(&rdataset);
1301 dns_db_detachnode(db, &node);
1307 dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
1308 isc_boolean_t complete, isc_boolean_t *answer)
1310 dns_dbnode_t *node = NULL;
1311 dns_rdataset_t rdataset;
1312 dns_rdata_nsec3param_t nsec3param;
1313 isc_result_t result;
1315 REQUIRE(answer != NULL);
1317 dns_rdataset_init(&rdataset);
1319 result = dns_db_getoriginnode(db, &node);
1320 if (result != ISC_R_SUCCESS)
1323 result = dns_db_findrdataset(db, node, version,
1324 dns_rdatatype_nsec3param, 0, 0,
1326 dns_db_detachnode(db, &node);
1328 if (result == ISC_R_NOTFOUND) {
1329 *answer = ISC_FALSE;
1330 return (ISC_R_SUCCESS);
1332 if (result != ISC_R_SUCCESS)
1334 for (result = dns_rdataset_first(&rdataset);
1335 result == ISC_R_SUCCESS;
1336 result = dns_rdataset_next(&rdataset)) {
1337 dns_rdata_t rdata = DNS_RDATA_INIT;
1339 dns_rdataset_current(&rdataset, &rdata);
1340 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1341 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1343 if ((nsec3param.flags) == 0 ||
1344 (!complete && CREATE(nsec3param.flags)))
1347 dns_rdataset_disassociate(&rdataset);
1348 if (result == ISC_R_SUCCESS)
1350 if (result == ISC_R_NOMORE) {
1351 *answer = ISC_FALSE;
1352 result = ISC_R_SUCCESS;
1358 dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
1359 isc_mem_t *mctx, unsigned int *iterationsp)
1361 dns_dbnode_t *node = NULL;
1362 dns_rdataset_t rdataset;
1363 dst_key_t *key = NULL;
1364 isc_buffer_t buffer;
1365 isc_result_t result;
1366 isc_uint16_t bits, minbits = 4096;
1368 result = dns_db_getoriginnode(db, &node);
1369 if (result != ISC_R_SUCCESS)
1372 dns_rdataset_init(&rdataset);
1373 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
1374 0, 0, &rdataset, NULL);
1375 dns_db_detachnode(db, &node);
1376 if (result == ISC_R_NOTFOUND) {
1378 return (ISC_R_SUCCESS);
1380 if (result != ISC_R_SUCCESS)
1383 for (result = dns_rdataset_first(&rdataset);
1384 result == ISC_R_SUCCESS;
1385 result = dns_rdataset_next(&rdataset)) {
1386 dns_rdata_t rdata = DNS_RDATA_INIT;
1388 dns_rdataset_current(&rdataset, &rdata);
1389 isc_buffer_init(&buffer, rdata.data, rdata.length);
1390 isc_buffer_add(&buffer, rdata.length);
1391 CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
1392 &buffer, mctx, &key));
1393 bits = dst_key_getbits(key);
1398 if (result != ISC_R_NOMORE)
1401 if (minbits <= 1024)
1403 else if (minbits <= 2048)
1406 *iterationsp = 2500;
1407 result = ISC_R_SUCCESS;
1410 if (dns_rdataset_isassociated(&rdataset))
1411 dns_rdataset_disassociate(&rdataset);