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