Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / nsec3.c
blob6c54932d4b34c10c655554ace04ca6f88509fe48
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2006, 2008, 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: nsec3.c,v 1.13 2009/12/01 05:28:40 marka Exp */
21 #include <config.h>
23 #include <isc/base32.h>
24 #include <isc/buffer.h>
25 #include <isc/hex.h>
26 #include <isc/iterated_hash.h>
27 #include <isc/string.h>
28 #include <isc/util.h>
30 #include <dst/dst.h>
32 #include <dns/db.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>
45 #define CHECK(x) do { \
46 result = (x); \
47 if (result != ISC_R_SUCCESS) \
48 goto failure; \
49 } while (0)
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)
55 static void
56 set_bit(unsigned char *array, unsigned int index, unsigned int bit) {
57 unsigned int shift, mask;
59 shift = 7 - (index % 8);
60 mask = 1 << shift;
62 if (bit != 0)
63 array[index / 8] |= mask;
64 else
65 array[index / 8] &= (~mask & 0xFF);
68 static unsigned int
69 bit_isset(unsigned char *array, unsigned int index) {
70 unsigned int byte, shift, mask;
72 byte = array[index / 8];
73 shift = 7 - (index % 8);
74 mask = 1 << shift;
76 return ((byte & mask) != 0);
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)
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;
96 unsigned char *nsec_bits, *bm;
97 unsigned int max_type;
98 dns_rdatasetiter_t *rdsiter;
99 unsigned char *p;
101 REQUIRE(salt_length < 256U);
102 REQUIRE(hash_length < 256U);
103 REQUIRE(flags <= 0xffU);
104 REQUIRE(hashalg <= 0xffU);
105 REQUIRE(iterations <= 0xffffU);
107 switch (hashalg) {
108 case dns_hash_sha1:
109 REQUIRE(hash_length == ISC_SHA1_DIGESTLENGTH);
110 break;
113 memset(buffer, 0, DNS_NSEC3_BUFFERSIZE);
115 p = buffer;
117 *p++ = hashalg;
118 *p++ = flags;
120 *p++ = iterations >> 8;
121 *p++ = iterations;
123 *p++ = salt_length;
124 memcpy(p, salt, salt_length);
125 p += salt_length;
127 *p++ = hash_length;
128 memcpy(p, nexthash, hash_length);
129 p += hash_length;
131 r.length = p - buffer;
132 r.base = buffer;
135 * Use the end of the space for a raw bitmap leaving enough
136 * space for the window identifiers and length octets.
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))
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);
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.
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;
177 dns_rdataset_disassociate(&rdataset);
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);
186 * At zone cuts, deny the existence of glue in the parent zone.
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);
197 dns_rdatasetiter_destroy(&rdsiter);
198 if (result != ISC_R_NOMORE)
199 return (result);
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;
213 * Note: potentially overlapping move.
215 memmove(&nsec_bits[2], &bm[window * 32], octet + 1);
216 nsec_bits += 3 + octet;
218 r.length = nsec_bits - r.base;
219 INSIST(r.length <= DNS_NSEC3_BUFFERSIZE);
220 dns_rdata_fromregion(rdata, dns_db_class(db), dns_rdatatype_nsec3, &r);
222 return (ISC_R_SUCCESS);
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;
232 REQUIRE(rdata != NULL);
233 REQUIRE(rdata->type == dns_rdatatype_nsec3);
235 /* This should never fail */
236 result = dns_rdata_tostruct(rdata, &nsec3, NULL);
237 INSIST(result == ISC_R_SUCCESS);
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;
256 dns_rdata_freestruct(&nsec3);
257 return (present);
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)
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;
275 if (rethash == NULL)
276 rethash = hash;
278 memset(rethash, 0, NSEC3_MAX_HASH_LENGTH);
280 dns_fixedname_init(&fixed);
281 downcased = dns_fixedname_name(&fixed);
282 dns_name_downcase(name, downcased, NULL);
284 /* hash the node name */
285 len = isc_iterated_hash(rethash, hashalg, iterations, salt, saltlength,
286 downcased->ndata, downcased->length);
287 if (len == 0U)
288 return (DNS_R_BADALG);
290 if (hash_length != NULL)
291 *hash_length = len;
293 /* convert the hash to base32hex */
294 region.base = rethash;
295 region.length = len;
296 isc_buffer_init(&namebuffer, nametext, sizeof nametext);
297 isc_base32hex_totext(&region, 1, "", &namebuffer);
299 /* convert the hex to a domain name */
300 dns_fixedname_init(result);
301 return (dns_name_fromtext(dns_fixedname_name(result), &namebuffer,
302 origin, 0, NULL));
305 unsigned int
306 dns_nsec3_hashlength(dns_hash_t hash) {
308 switch (hash) {
309 case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH);
311 return (0);
314 isc_boolean_t
315 dns_nsec3_supportedhash(dns_hash_t hash) {
316 switch (hash) {
317 case dns_hash_sha1: return (ISC_TRUE);
319 return (ISC_FALSE);
323 * Update a single RR in version 'ver' of 'db' and log the
324 * update in 'diff'.
326 * Ensures:
327 * \li '*tuple' == NULL. Either the tuple is freed, or its
328 * ownership has been transferred to the diff.
330 static isc_result_t
331 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
332 dns_diff_t *diff)
334 dns_diff_t temp_diff;
335 isc_result_t result;
338 * Create a singleton diff.
340 dns_diff_init(diff->mctx, &temp_diff);
341 temp_diff.resign = diff->resign;
342 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
345 * Apply it to the database.
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);
355 * Merge it into the current pending journal entry.
357 dns_diff_appendminimal(diff, tuple);
360 * Do not clear temp_diff.
362 return (ISC_R_SUCCESS);
366 * Set '*exists' to true iff the given name exists, to false otherwise.
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)
372 isc_result_t result;
373 dns_dbnode_t *node = NULL;
374 dns_rdatasetiter_t *iter = NULL;
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);
381 if (result != ISC_R_SUCCESS)
382 return (result);
384 result = dns_db_allrdatasets(db, node, version,
385 (isc_stdtime_t) 0, &iter);
386 if (result != ISC_R_SUCCESS)
387 goto cleanup_node;
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);
399 cleanup_node:
400 dns_db_detachnode(db, &node);
401 return (result);
404 static isc_boolean_t
405 match_nsec3param(const dns_rdata_nsec3_t *nsec3,
406 const dns_rdata_nsec3param_t *nsec3param)
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);
417 * Delete NSEC3 records at "name" which match "param", recording the
418 * change in "diff".
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)
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;
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);
436 dns_rdataset_init(&rdataset);
437 result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3, 0,
438 (isc_stdtime_t) 0, &rdataset, NULL);
440 if (result == ISC_R_NOTFOUND) {
441 result = ISC_R_SUCCESS;
442 goto cleanup_node;
444 if (result != ISC_R_SUCCESS)
445 goto cleanup_node;
447 for (result = dns_rdataset_first(&rdataset);
448 result == ISC_R_SUCCESS;
449 result = dns_rdataset_next(&rdataset))
451 dns_rdata_t rdata = DNS_RDATA_INIT;
452 dns_rdataset_current(&rdataset, &rdata);
453 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
455 if (!match_nsec3param(&nsec3, nsec3param))
456 continue;
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;
466 if (result != ISC_R_NOMORE)
467 goto failure;
468 result = ISC_R_SUCCESS;
470 failure:
471 dns_rdataset_disassociate(&rdataset);
472 cleanup_node:
473 dns_db_detachnode(db, &node);
475 return (result);
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;
483 if (REMOVE(param->data[1]))
484 return (ISC_TRUE);
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];
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);
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);
517 dns_rdataset_disassociate(&rdataset);
518 return (ISC_FALSE);
521 static isc_result_t
522 find_nsec3(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *rdataset,
523 const dns_rdata_nsec3param_t *nsec3param)
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;
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;
537 failure:
538 return (result);
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)
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;
562 isc_boolean_t 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;
576 dns_fixedname_init(&fixed);
577 hashname = dns_fixedname_name(&fixed);
578 dns_fixedname_init(&fprev);
579 prev = dns_fixedname_name(&fprev);
581 dns_rdataset_init(&rdataset);
583 origin = dns_db_origin(db);
586 * Chain parameters.
588 hash = nsec3param->hash;
589 iterations = nsec3param->iterations;
590 salt_length = nsec3param->salt_length;
591 salt = nsec3param->salt;
594 * Default flags for a new chain.
596 flags = nsec3param->flags & DNS_NSEC3FLAG_OPTOUT;
599 * If this is the first NSEC3 in the chain nexthash will
600 * remain pointing to itself.
602 next_length = sizeof(nexthash);
603 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
604 name, origin, hash, iterations,
605 salt, salt_length));
608 * Create the node if it doesn't exist and hold
609 * a reference to it until we have added the NSEC3.
611 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
614 * Seek the iterator to the 'newnode'.
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);
622 * If we updating a existing NSEC3 then find its
623 * next field.
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 memcpy(nexthash, nsec3.next, next_length);
633 dns_rdataset_disassociate(&rdataset);
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.
641 if (!unsecure)
642 goto addnsec3;
643 else
644 remove_unsecure = ISC_TRUE;
645 } else {
646 dns_rdataset_disassociate(&rdataset);
647 if (result != ISC_R_NOMORE)
648 goto failure;
653 * Find the previous NSEC3 (if any) and update it if required.
655 pass = 0;
656 do {
657 result = dns_dbiterator_prev(dbit);
658 if (result == ISC_R_NOMORE) {
659 pass++;
660 CHECK(dns_dbiterator_last(dbit));
662 CHECK(dns_dbiterator_current(dbit, &node, prev));
663 CHECK(dns_dbiterator_pause(dbit));
664 result = dns_db_findrdataset(db, node, version,
665 dns_rdatatype_nsec3, 0,
666 (isc_stdtime_t) 0, &rdataset,
667 NULL);
668 dns_db_detachnode(db, &node);
669 if (result != ISC_R_SUCCESS)
670 continue;
672 result = find_nsec3(&nsec3, &rdataset, nsec3param);
673 if (result == ISC_R_NOMORE) {
674 dns_rdataset_disassociate(&rdataset);
675 continue;
677 if (result != ISC_R_SUCCESS)
678 goto failure;
680 if (remove_unsecure) {
681 dns_rdataset_disassociate(&rdataset);
683 * We have found the previous NSEC3 record and can now
684 * see if the existing NSEC3 record needs to be
685 * updated or deleted.
687 if (!OPTOUT(nsec3.flags)) {
689 * Just update the NSEC3 record.
691 goto addnsec3;
692 } else {
694 * This is actually a deletion not a add.
696 result = dns_nsec3_delnsec3(db, version, name,
697 nsec3param, diff);
698 goto failure;
700 } else {
702 * Is this is a unsecure delegation we are adding?
703 * If so no change is required.
705 if (OPTOUT(nsec3.flags) && unsecure) {
706 dns_rdataset_disassociate(&rdataset);
707 goto failure;
711 old_next = nsec3.next;
712 old_length = nsec3.next_length;
715 * Delete the old previous NSEC3.
717 CHECK(delete(db, version, prev, nsec3param, diff));
720 * Fixup the previous NSEC3.
722 nsec3.next = nexthash;
723 nsec3.next_length = next_length;
724 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
725 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
726 dns_rdatatype_nsec3, &nsec3,
727 &buffer));
728 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
729 rdataset.ttl, &rdata, &tuple));
730 CHECK(do_one_tuple(&tuple, db, version, diff));
731 INSIST(old_length <= sizeof(nexthash));
732 memcpy(nexthash, old_next, old_length);
733 if (!CREATE(nsec3param->flags))
734 flags = nsec3.flags;
735 dns_rdata_reset(&rdata);
736 dns_rdataset_disassociate(&rdataset);
737 break;
738 } while (pass < 2);
740 addnsec3:
742 * Create the NSEC3 RDATA.
744 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
745 CHECK(dns_nsec3_buildrdata(db, version, node, hash, flags, iterations,
746 salt, salt_length, nexthash, next_length,
747 nsec3buf, &rdata));
748 dns_db_detachnode(db, &node);
751 * Delete the old NSEC3 and record the change.
753 CHECK(delete(db, version, hashname, nsec3param, diff));
755 * Add the new NSEC3 and record the change.
757 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
758 hashname, nsecttl, &rdata, &tuple));
759 CHECK(do_one_tuple(&tuple, db, version, diff));
760 INSIST(tuple == NULL);
761 dns_rdata_reset(&rdata);
762 dns_db_detachnode(db, &newnode);
765 * Add missing NSEC3 records for empty nodes
767 dns_name_init(&empty, NULL);
768 dns_name_clone(name, &empty);
769 do {
770 labels = dns_name_countlabels(&empty) - 1;
771 if (labels <= dns_name_countlabels(origin))
772 break;
773 dns_name_getlabelsequence(&empty, 1, labels, &empty);
774 CHECK(name_exists(db, version, &empty, &exists));
775 if (exists)
776 break;
777 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
778 &empty, origin, hash, iterations,
779 salt, salt_length));
782 * Create the node if it doesn't exist and hold
783 * a reference to it until we have added the NSEC3
784 * or we discover we don't need to add make a change.
786 CHECK(dns_db_findnsec3node(db, hashname, ISC_TRUE, &newnode));
787 result = dns_db_findrdataset(db, newnode, version,
788 dns_rdatatype_nsec3, 0,
789 (isc_stdtime_t) 0, &rdataset,
790 NULL);
791 if (result == ISC_R_SUCCESS) {
792 result = find_nsec3(&nsec3, &rdataset, nsec3param);
793 dns_rdataset_disassociate(&rdataset);
794 if (result == ISC_R_SUCCESS) {
795 dns_db_detachnode(db, &newnode);
796 break;
798 if (result != ISC_R_NOMORE)
799 goto failure;
803 * Find the previous NSEC3 and update it.
805 CHECK(dns_dbiterator_seek(dbit, hashname));
806 pass = 0;
807 do {
808 result = dns_dbiterator_prev(dbit);
809 if (result == ISC_R_NOMORE) {
810 pass++;
811 CHECK(dns_dbiterator_last(dbit));
813 CHECK(dns_dbiterator_current(dbit, &node, prev));
814 CHECK(dns_dbiterator_pause(dbit));
815 result = dns_db_findrdataset(db, node, version,
816 dns_rdatatype_nsec3, 0,
817 (isc_stdtime_t) 0,
818 &rdataset, NULL);
819 dns_db_detachnode(db, &node);
820 if (result != ISC_R_SUCCESS)
821 continue;
822 result = find_nsec3(&nsec3, &rdataset, nsec3param);
823 if (result == ISC_R_NOMORE) {
824 dns_rdataset_disassociate(&rdataset);
825 continue;
827 if (result != ISC_R_SUCCESS)
828 goto failure;
830 old_next = nsec3.next;
831 old_length = nsec3.next_length;
834 * Delete the old previous NSEC3.
836 CHECK(delete(db, version, prev, nsec3param, diff));
839 * Fixup the previous NSEC3.
841 nsec3.next = nexthash;
842 nsec3.next_length = next_length;
843 isc_buffer_init(&buffer, nsec3buf,
844 sizeof(nsec3buf));
845 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
846 dns_rdatatype_nsec3, &nsec3,
847 &buffer));
848 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
849 prev, rdataset.ttl, &rdata,
850 &tuple));
851 CHECK(do_one_tuple(&tuple, db, version, diff));
852 INSIST(old_length <= sizeof(nexthash));
853 memcpy(nexthash, old_next, old_length);
854 if (!CREATE(nsec3param->flags))
855 flags = nsec3.flags;
856 dns_rdata_reset(&rdata);
857 dns_rdataset_disassociate(&rdataset);
858 break;
859 } while (pass < 2);
861 INSIST(pass < 2);
864 * Create the NSEC3 RDATA for the empty node.
866 CHECK(dns_nsec3_buildrdata(db, version, NULL, hash, flags,
867 iterations, salt, salt_length,
868 nexthash, next_length, nsec3buf,
869 &rdata));
871 * Delete the old NSEC3 and record the change.
873 CHECK(delete(db, version, hashname, nsec3param, diff));
876 * Add the new NSEC3 and record the change.
878 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
879 hashname, nsecttl, &rdata, &tuple));
880 CHECK(do_one_tuple(&tuple, db, version, diff));
881 INSIST(tuple == NULL);
882 dns_rdata_reset(&rdata);
883 dns_db_detachnode(db, &newnode);
884 } while (1);
886 if (result == ISC_R_NOMORE)
887 result = ISC_R_SUCCESS;
889 failure:
890 if (dbit != NULL)
891 dns_dbiterator_destroy(&dbit);
892 if (dns_rdataset_isassociated(&rdataset))
893 dns_rdataset_disassociate(&rdataset);
894 if (node != NULL)
895 dns_db_detachnode(db, &node);
896 if (newnode != NULL)
897 dns_db_detachnode(db, &newnode);
898 return (result);
902 * Add NSEC3 records for "name", recording the change in "diff".
903 * The existing NSEC3 records are removed.
905 isc_result_t
906 dns_nsec3_addnsec3s(dns_db_t *db, dns_dbversion_t *version,
907 dns_name_t *name, dns_ttl_t nsecttl,
908 isc_boolean_t unsecure, dns_diff_t *diff)
910 dns_dbnode_t *node = NULL;
911 dns_rdata_nsec3param_t nsec3param;
912 dns_rdataset_t rdataset;
913 isc_result_t result;
915 dns_rdataset_init(&rdataset);
918 * Find the NSEC3 parameters for this zone.
920 result = dns_db_getoriginnode(db, &node);
921 if (result != ISC_R_SUCCESS)
922 return (result);
924 result = dns_db_findrdataset(db, node, version,
925 dns_rdatatype_nsec3param, 0, 0,
926 &rdataset, NULL);
927 dns_db_detachnode(db, &node);
928 if (result == ISC_R_NOTFOUND)
929 return (ISC_R_SUCCESS);
930 if (result != ISC_R_SUCCESS)
931 return (result);
934 * Update each active NSEC3 chain.
936 for (result = dns_rdataset_first(&rdataset);
937 result == ISC_R_SUCCESS;
938 result = dns_rdataset_next(&rdataset)) {
939 dns_rdata_t rdata = DNS_RDATA_INIT;
941 dns_rdataset_current(&rdataset, &rdata);
942 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
944 if (nsec3param.flags != 0)
945 continue;
947 * We have a active chain. Update it.
949 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
950 nsecttl, unsecure, diff));
952 if (result == ISC_R_NOMORE)
953 result = ISC_R_SUCCESS;
955 failure:
956 if (dns_rdataset_isassociated(&rdataset))
957 dns_rdataset_disassociate(&rdataset);
958 if (node != NULL)
959 dns_db_detachnode(db, &node);
961 return (result);
964 isc_boolean_t
965 dns_nsec3param_fromprivate(dns_rdata_t *src, dns_rdata_t *target,
966 unsigned char *buf, size_t buflen)
968 dns_decompress_t dctx;
969 isc_result_t result;
970 isc_buffer_t buf1;
971 isc_buffer_t buf2;
974 * Algorithm 0 (reserved by RFC 4034) is used to identify
975 * NSEC3PARAM records from DNSKEY pointers.
977 if (src->length < 1 || src->data[0] != 0)
978 return (ISC_FALSE);
980 isc_buffer_init(&buf1, src->data + 1, src->length - 1);
981 isc_buffer_add(&buf1, src->length - 1);
982 isc_buffer_setactive(&buf1, src->length - 1);
983 isc_buffer_init(&buf2, buf, buflen);
984 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
985 result = dns_rdata_fromwire(target, src->rdclass,
986 dns_rdatatype_nsec3param,
987 &buf1, &dctx, 0, &buf2);
988 dns_decompress_invalidate(&dctx);
990 return (ISC_TF(result == ISC_R_SUCCESS));
993 void
994 dns_nsec3param_toprivate(dns_rdata_t *src, dns_rdata_t *target,
995 dns_rdatatype_t privatetype,
996 unsigned char *buf, size_t buflen)
998 REQUIRE(buflen >= src->length + 1);
1000 REQUIRE(DNS_RDATA_INITIALIZED(target));
1002 memcpy(buf + 1, src->data, src->length);
1003 buf[0] = 0;
1004 target->data = buf;
1005 target->length = src->length + 1;
1006 target->type = privatetype;
1007 target->rdclass = src->rdclass;
1008 target->flags = 0;
1009 ISC_LINK_INIT(target, link);
1012 isc_result_t
1013 dns_nsec3_addnsec3sx(dns_db_t *db, dns_dbversion_t *version,
1014 dns_name_t *name, dns_ttl_t nsecttl,
1015 isc_boolean_t unsecure, dns_rdatatype_t type,
1016 dns_diff_t *diff)
1018 dns_dbnode_t *node = NULL;
1019 dns_rdata_nsec3param_t nsec3param;
1020 dns_rdataset_t rdataset;
1021 dns_rdataset_t prdataset;
1022 isc_result_t result;
1024 dns_rdataset_init(&rdataset);
1025 dns_rdataset_init(&prdataset);
1028 * Find the NSEC3 parameters for this zone.
1030 result = dns_db_getoriginnode(db, &node);
1031 if (result != ISC_R_SUCCESS)
1032 return (result);
1034 result = dns_db_findrdataset(db, node, version, type, 0, 0,
1035 &prdataset, NULL);
1036 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1037 goto failure;
1039 result = dns_db_findrdataset(db, node, version,
1040 dns_rdatatype_nsec3param, 0, 0,
1041 &rdataset, NULL);
1042 if (result == ISC_R_NOTFOUND)
1043 goto try_private;
1044 if (result != ISC_R_SUCCESS)
1045 goto failure;
1048 * Update each active NSEC3 chain.
1050 for (result = dns_rdataset_first(&rdataset);
1051 result == ISC_R_SUCCESS;
1052 result = dns_rdataset_next(&rdataset)) {
1053 dns_rdata_t rdata = DNS_RDATA_INIT;
1055 dns_rdataset_current(&rdataset, &rdata);
1056 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
1058 if (nsec3param.flags != 0)
1059 continue;
1062 * We have a active chain. Update it.
1064 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
1065 nsecttl, unsecure, diff));
1067 if (result != ISC_R_NOMORE)
1068 goto failure;
1070 dns_rdataset_disassociate(&rdataset);
1072 try_private:
1073 if (!dns_rdataset_isassociated(&prdataset))
1074 goto success;
1076 * Update each active NSEC3 chain.
1078 for (result = dns_rdataset_first(&prdataset);
1079 result == ISC_R_SUCCESS;
1080 result = dns_rdataset_next(&prdataset)) {
1081 dns_rdata_t rdata1 = DNS_RDATA_INIT;
1082 dns_rdata_t rdata2 = DNS_RDATA_INIT;
1083 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1085 dns_rdataset_current(&prdataset, &rdata1);
1086 if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
1087 buf, sizeof(buf)))
1088 continue;
1089 CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
1091 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
1092 continue;
1093 if (better_param(&prdataset, &rdata2))
1094 continue;
1097 * We have a active chain. Update it.
1099 CHECK(dns_nsec3_addnsec3(db, version, name, &nsec3param,
1100 nsecttl, unsecure, diff));
1102 if (result == ISC_R_NOMORE)
1103 success:
1104 result = ISC_R_SUCCESS;
1105 failure:
1106 if (dns_rdataset_isassociated(&rdataset))
1107 dns_rdataset_disassociate(&rdataset);
1108 if (dns_rdataset_isassociated(&prdataset))
1109 dns_rdataset_disassociate(&prdataset);
1110 if (node != NULL)
1111 dns_db_detachnode(db, &node);
1113 return (result);
1117 * Determine whether any NSEC3 records that were associated with
1118 * 'name' should be deleted or if they should continue to exist.
1119 * ISC_TRUE indicates they should be deleted.
1120 * ISC_FALSE indicates they should be retained.
1122 static isc_result_t
1123 deleteit(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1124 isc_boolean_t *yesno)
1126 isc_result_t result;
1127 dns_fixedname_t foundname;
1128 dns_fixedname_init(&foundname);
1130 result = dns_db_find(db, name, ver, dns_rdatatype_any,
1131 DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
1132 (isc_stdtime_t) 0, NULL,
1133 dns_fixedname_name(&foundname),
1134 NULL, NULL);
1135 if (result == DNS_R_EMPTYNAME || result == ISC_R_SUCCESS ||
1136 result == DNS_R_ZONECUT) {
1137 *yesno = ISC_FALSE;
1138 return (ISC_R_SUCCESS);
1140 if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
1141 result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
1142 *yesno = ISC_TRUE;
1143 return (ISC_R_SUCCESS);
1146 * Silence compiler.
1148 *yesno = ISC_TRUE;
1149 return (result);
1152 isc_result_t
1153 dns_nsec3_delnsec3(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1154 const dns_rdata_nsec3param_t *nsec3param, dns_diff_t *diff)
1156 dns_dbiterator_t *dbit = NULL;
1157 dns_dbnode_t *node = NULL;
1158 dns_difftuple_t *tuple = NULL;
1159 dns_fixedname_t fixed;
1160 dns_fixedname_t fprev;
1161 dns_hash_t hash;
1162 dns_name_t *hashname;
1163 dns_name_t *origin;
1164 dns_name_t *prev;
1165 dns_name_t empty;
1166 dns_rdata_nsec3_t nsec3;
1167 dns_rdata_t rdata = DNS_RDATA_INIT;
1168 dns_rdataset_t rdataset;
1169 int pass;
1170 isc_boolean_t yesno;
1171 isc_buffer_t buffer;
1172 isc_result_t result;
1173 unsigned char *salt;
1174 unsigned char nexthash[NSEC3_MAX_HASH_LENGTH];
1175 unsigned char nsec3buf[DNS_NSEC3_BUFFERSIZE];
1176 unsigned int iterations;
1177 unsigned int labels;
1178 size_t next_length;
1179 unsigned int salt_length;
1181 dns_fixedname_init(&fixed);
1182 hashname = dns_fixedname_name(&fixed);
1183 dns_fixedname_init(&fprev);
1184 prev = dns_fixedname_name(&fprev);
1186 dns_rdataset_init(&rdataset);
1188 origin = dns_db_origin(db);
1191 * Chain parameters.
1193 hash = nsec3param->hash;
1194 iterations = nsec3param->iterations;
1195 salt_length = nsec3param->salt_length;
1196 salt = nsec3param->salt;
1199 * If this is the first NSEC3 in the chain nexthash will
1200 * remain pointing to itself.
1202 next_length = sizeof(nexthash);
1203 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1204 name, origin, hash, iterations,
1205 salt, salt_length));
1207 CHECK(dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbit));
1209 result = dns_dbiterator_seek(dbit, hashname);
1210 if (result == ISC_R_NOTFOUND)
1211 goto success;
1212 if (result != ISC_R_SUCCESS)
1213 goto failure;
1215 CHECK(dns_dbiterator_current(dbit, &node, NULL));
1216 CHECK(dns_dbiterator_pause(dbit));
1217 result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3,
1218 0, (isc_stdtime_t) 0, &rdataset, NULL);
1219 dns_db_detachnode(db, &node);
1220 if (result == ISC_R_NOTFOUND)
1221 goto success;
1222 if (result != ISC_R_SUCCESS)
1223 goto failure;
1226 * If we find a existing NSEC3 for this chain then save the
1227 * next field.
1229 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1230 if (result == ISC_R_SUCCESS) {
1231 next_length = nsec3.next_length;
1232 INSIST(next_length <= sizeof(nexthash));
1233 memcpy(nexthash, nsec3.next, next_length);
1235 dns_rdataset_disassociate(&rdataset);
1236 if (result == ISC_R_NOMORE)
1237 goto success;
1238 if (result != ISC_R_SUCCESS)
1239 goto failure;
1242 * Find the previous NSEC3 and update it.
1244 pass = 0;
1245 do {
1246 result = dns_dbiterator_prev(dbit);
1247 if (result == ISC_R_NOMORE) {
1248 pass++;
1249 CHECK(dns_dbiterator_last(dbit));
1251 CHECK(dns_dbiterator_current(dbit, &node, prev));
1252 CHECK(dns_dbiterator_pause(dbit));
1253 result = dns_db_findrdataset(db, node, version,
1254 dns_rdatatype_nsec3, 0,
1255 (isc_stdtime_t) 0, &rdataset,
1256 NULL);
1257 dns_db_detachnode(db, &node);
1258 if (result != ISC_R_SUCCESS)
1259 continue;
1260 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1261 if (result == ISC_R_NOMORE) {
1262 dns_rdataset_disassociate(&rdataset);
1263 continue;
1265 if (result != ISC_R_SUCCESS)
1266 goto failure;
1269 * Delete the old previous NSEC3.
1271 CHECK(delete(db, version, prev, nsec3param, diff));
1274 * Fixup the previous NSEC3.
1276 nsec3.next = nexthash;
1277 nsec3.next_length = next_length;
1278 isc_buffer_init(&buffer, nsec3buf, sizeof(nsec3buf));
1279 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1280 dns_rdatatype_nsec3, &nsec3,
1281 &buffer));
1282 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, prev,
1283 rdataset.ttl, &rdata, &tuple));
1284 CHECK(do_one_tuple(&tuple, db, version, diff));
1285 dns_rdata_reset(&rdata);
1286 dns_rdataset_disassociate(&rdataset);
1287 break;
1288 } while (pass < 2);
1291 * Delete the old NSEC3 and record the change.
1293 CHECK(delete(db, version, hashname, nsec3param, diff));
1296 * Delete NSEC3 records for now non active nodes.
1298 dns_name_init(&empty, NULL);
1299 dns_name_clone(name, &empty);
1300 do {
1301 labels = dns_name_countlabels(&empty) - 1;
1302 if (labels <= dns_name_countlabels(origin))
1303 break;
1304 dns_name_getlabelsequence(&empty, 1, labels, &empty);
1305 CHECK(deleteit(db, version, &empty, &yesno));
1306 if (!yesno)
1307 break;
1309 CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length,
1310 &empty, origin, hash, iterations,
1311 salt, salt_length));
1312 result = dns_dbiterator_seek(dbit, hashname);
1313 if (result == ISC_R_NOTFOUND)
1314 goto success;
1315 if (result != ISC_R_SUCCESS)
1316 goto failure;
1318 CHECK(dns_dbiterator_current(dbit, &node, NULL));
1319 CHECK(dns_dbiterator_pause(dbit));
1320 result = dns_db_findrdataset(db, node, version,
1321 dns_rdatatype_nsec3, 0,
1322 (isc_stdtime_t) 0, &rdataset,
1323 NULL);
1324 dns_db_detachnode(db, &node);
1325 if (result == ISC_R_NOTFOUND)
1326 goto success;
1327 if (result != ISC_R_SUCCESS)
1328 goto failure;
1330 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1331 if (result == ISC_R_SUCCESS) {
1332 next_length = nsec3.next_length;
1333 INSIST(next_length <= sizeof(nexthash));
1334 memcpy(nexthash, nsec3.next, next_length);
1336 dns_rdataset_disassociate(&rdataset);
1337 if (result == ISC_R_NOMORE)
1338 goto success;
1339 if (result != ISC_R_SUCCESS)
1340 goto failure;
1342 pass = 0;
1343 do {
1344 result = dns_dbiterator_prev(dbit);
1345 if (result == ISC_R_NOMORE) {
1346 pass++;
1347 CHECK(dns_dbiterator_last(dbit));
1349 CHECK(dns_dbiterator_current(dbit, &node, prev));
1350 CHECK(dns_dbiterator_pause(dbit));
1351 result = dns_db_findrdataset(db, node, version,
1352 dns_rdatatype_nsec3, 0,
1353 (isc_stdtime_t) 0,
1354 &rdataset, NULL);
1355 dns_db_detachnode(db, &node);
1356 if (result != ISC_R_SUCCESS)
1357 continue;
1358 result = find_nsec3(&nsec3, &rdataset, nsec3param);
1359 if (result == ISC_R_NOMORE) {
1360 dns_rdataset_disassociate(&rdataset);
1361 continue;
1363 if (result != ISC_R_SUCCESS)
1364 goto failure;
1367 * Delete the old previous NSEC3.
1369 CHECK(delete(db, version, prev, nsec3param, diff));
1372 * Fixup the previous NSEC3.
1374 nsec3.next = nexthash;
1375 nsec3.next_length = next_length;
1376 isc_buffer_init(&buffer, nsec3buf,
1377 sizeof(nsec3buf));
1378 CHECK(dns_rdata_fromstruct(&rdata, rdataset.rdclass,
1379 dns_rdatatype_nsec3, &nsec3,
1380 &buffer));
1381 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
1382 prev, rdataset.ttl, &rdata,
1383 &tuple));
1384 CHECK(do_one_tuple(&tuple, db, version, diff));
1385 dns_rdata_reset(&rdata);
1386 dns_rdataset_disassociate(&rdataset);
1387 break;
1388 } while (pass < 2);
1390 INSIST(pass < 2);
1393 * Delete the old NSEC3 and record the change.
1395 CHECK(delete(db, version, hashname, nsec3param, diff));
1396 } while (1);
1398 success:
1399 result = ISC_R_SUCCESS;
1401 failure:
1402 if (dbit != NULL)
1403 dns_dbiterator_destroy(&dbit);
1404 if (dns_rdataset_isassociated(&rdataset))
1405 dns_rdataset_disassociate(&rdataset);
1406 if (node != NULL)
1407 dns_db_detachnode(db, &node);
1408 return (result);
1411 isc_result_t
1412 dns_nsec3_delnsec3s(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1413 dns_diff_t *diff)
1415 return (dns_nsec3_delnsec3sx(db, version, name, 0, diff));
1418 isc_result_t
1419 dns_nsec3_delnsec3sx(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
1420 dns_rdatatype_t type, dns_diff_t *diff)
1422 dns_dbnode_t *node = NULL;
1423 dns_rdata_nsec3param_t nsec3param;
1424 dns_rdataset_t rdataset;
1425 isc_result_t result;
1427 dns_rdataset_init(&rdataset);
1430 * Find the NSEC3 parameters for this zone.
1432 result = dns_db_getoriginnode(db, &node);
1433 if (result != ISC_R_SUCCESS)
1434 return (result);
1436 result = dns_db_findrdataset(db, node, version,
1437 dns_rdatatype_nsec3param, 0, 0,
1438 &rdataset, NULL);
1439 if (result == ISC_R_NOTFOUND)
1440 goto try_private;
1441 if (result != ISC_R_SUCCESS)
1442 goto failure;
1445 * Update each active NSEC3 chain.
1447 for (result = dns_rdataset_first(&rdataset);
1448 result == ISC_R_SUCCESS;
1449 result = dns_rdataset_next(&rdataset)) {
1450 dns_rdata_t rdata = DNS_RDATA_INIT;
1452 dns_rdataset_current(&rdataset, &rdata);
1453 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
1455 if (nsec3param.flags != 0)
1456 continue;
1458 * We have a active chain. Update it.
1460 CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1462 dns_rdataset_disassociate(&rdataset);
1464 try_private:
1465 if (type == 0)
1466 goto success;
1467 result = dns_db_findrdataset(db, node, version, type, 0, 0,
1468 &rdataset, NULL);
1469 if (result == ISC_R_NOTFOUND)
1470 goto success;
1471 if (result != ISC_R_SUCCESS)
1472 goto failure;
1475 * Update each NSEC3 chain being built.
1477 for (result = dns_rdataset_first(&rdataset);
1478 result == ISC_R_SUCCESS;
1479 result = dns_rdataset_next(&rdataset)) {
1480 dns_rdata_t rdata1 = DNS_RDATA_INIT;
1481 dns_rdata_t rdata2 = DNS_RDATA_INIT;
1482 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1484 dns_rdataset_current(&rdataset, &rdata1);
1485 if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
1486 buf, sizeof(buf)))
1487 continue;
1488 CHECK(dns_rdata_tostruct(&rdata2, &nsec3param, NULL));
1490 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0)
1491 continue;
1492 if (better_param(&rdataset, &rdata2))
1493 continue;
1496 * We have a active chain. Update it.
1498 CHECK(dns_nsec3_delnsec3(db, version, name, &nsec3param, diff));
1500 if (result == ISC_R_NOMORE)
1501 success:
1502 result = ISC_R_SUCCESS;
1504 failure:
1505 if (dns_rdataset_isassociated(&rdataset))
1506 dns_rdataset_disassociate(&rdataset);
1507 if (node != NULL)
1508 dns_db_detachnode(db, &node);
1510 return (result);
1513 isc_result_t
1514 dns_nsec3_active(dns_db_t *db, dns_dbversion_t *version,
1515 isc_boolean_t complete, isc_boolean_t *answer)
1517 return (dns_nsec3_activex(db, version, complete, 0, answer));
1520 isc_result_t
1521 dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version,
1522 isc_boolean_t complete, dns_rdatatype_t type,
1523 isc_boolean_t *answer)
1525 dns_dbnode_t *node = NULL;
1526 dns_rdataset_t rdataset;
1527 dns_rdata_nsec3param_t nsec3param;
1528 isc_result_t result;
1530 REQUIRE(answer != NULL);
1532 dns_rdataset_init(&rdataset);
1534 result = dns_db_getoriginnode(db, &node);
1535 if (result != ISC_R_SUCCESS)
1536 return (result);
1538 result = dns_db_findrdataset(db, node, version,
1539 dns_rdatatype_nsec3param, 0, 0,
1540 &rdataset, NULL);
1542 if (result == ISC_R_NOTFOUND)
1543 goto try_private;
1545 if (result != ISC_R_SUCCESS) {
1546 dns_db_detachnode(db, &node);
1547 return (result);
1549 for (result = dns_rdataset_first(&rdataset);
1550 result == ISC_R_SUCCESS;
1551 result = dns_rdataset_next(&rdataset)) {
1552 dns_rdata_t rdata = DNS_RDATA_INIT;
1554 dns_rdataset_current(&rdataset, &rdata);
1555 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
1556 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1558 if (nsec3param.flags == 0)
1559 break;
1561 dns_rdataset_disassociate(&rdataset);
1562 if (result == ISC_R_SUCCESS) {
1563 dns_db_detachnode(db, &node);
1564 *answer = ISC_TRUE;
1565 return (ISC_R_SUCCESS);
1567 if (result == ISC_R_NOMORE)
1568 *answer = ISC_FALSE;
1570 try_private:
1571 if (type == 0 || complete) {
1572 *answer = ISC_FALSE;
1573 return (ISC_R_SUCCESS);
1575 result = dns_db_findrdataset(db, node, version, type, 0, 0,
1576 &rdataset, NULL);
1578 dns_db_detachnode(db, &node);
1579 if (result == ISC_R_NOTFOUND) {
1580 *answer = ISC_FALSE;
1581 return (ISC_R_SUCCESS);
1583 if (result != ISC_R_SUCCESS)
1584 return (result);
1586 for (result = dns_rdataset_first(&rdataset);
1587 result == ISC_R_SUCCESS;
1588 result = dns_rdataset_next(&rdataset)) {
1589 dns_rdata_t rdata1 = DNS_RDATA_INIT;
1590 dns_rdata_t rdata2 = DNS_RDATA_INIT;
1591 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
1593 dns_rdataset_current(&rdataset, &rdata1);
1594 if (!dns_nsec3param_fromprivate(&rdata1, &rdata2,
1595 buf, sizeof(buf)))
1596 continue;
1597 result = dns_rdata_tostruct(&rdata2, &nsec3param, NULL);
1598 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1600 if (!complete && CREATE(nsec3param.flags))
1601 break;
1603 dns_rdataset_disassociate(&rdataset);
1604 if (result == ISC_R_SUCCESS) {
1605 *answer = ISC_TRUE;
1606 result = ISC_R_SUCCESS;
1608 if (result == ISC_R_NOMORE) {
1609 *answer = ISC_FALSE;
1610 result = ISC_R_SUCCESS;
1613 return (result);
1616 isc_result_t
1617 dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
1618 isc_mem_t *mctx, unsigned int *iterationsp)
1620 dns_dbnode_t *node = NULL;
1621 dns_rdataset_t rdataset;
1622 dst_key_t *key = NULL;
1623 isc_buffer_t buffer;
1624 isc_result_t result;
1625 isc_uint16_t bits, minbits = 4096;
1627 result = dns_db_getoriginnode(db, &node);
1628 if (result != ISC_R_SUCCESS)
1629 return (result);
1631 dns_rdataset_init(&rdataset);
1632 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
1633 0, 0, &rdataset, NULL);
1634 dns_db_detachnode(db, &node);
1635 if (result == ISC_R_NOTFOUND) {
1636 *iterationsp = 0;
1637 return (ISC_R_SUCCESS);
1639 if (result != ISC_R_SUCCESS)
1640 goto failure;
1642 for (result = dns_rdataset_first(&rdataset);
1643 result == ISC_R_SUCCESS;
1644 result = dns_rdataset_next(&rdataset)) {
1645 dns_rdata_t rdata = DNS_RDATA_INIT;
1647 dns_rdataset_current(&rdataset, &rdata);
1648 isc_buffer_init(&buffer, rdata.data, rdata.length);
1649 isc_buffer_add(&buffer, rdata.length);
1650 CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass,
1651 &buffer, mctx, &key));
1652 bits = dst_key_getbits(key);
1653 dst_key_free(&key);
1654 if (minbits > bits)
1655 minbits = bits;
1657 if (result != ISC_R_NOMORE)
1658 goto failure;
1660 if (minbits <= 1024)
1661 *iterationsp = 150;
1662 else if (minbits <= 2048)
1663 *iterationsp = 500;
1664 else
1665 *iterationsp = 2500;
1666 result = ISC_R_SUCCESS;
1668 failure:
1669 if (dns_rdataset_isassociated(&rdataset))
1670 dns_rdataset_disassociate(&rdataset);
1671 return (result);