zoneverify.c revision 1.1.1.5 1 /* $NetBSD: zoneverify.c,v 1.1.1.5 2020/08/03 17:07:12 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
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 http://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 /*! \file */
15
16 #include <inttypes.h>
17 #include <stdarg.h>
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <string.h>
21
22 #include <isc/base32.h>
23 #include <isc/buffer.h>
24 #include <isc/heap.h>
25 #include <isc/iterated_hash.h>
26 #include <isc/log.h>
27 #include <isc/mem.h>
28 #include <isc/region.h>
29 #include <isc/result.h>
30 #include <isc/types.h>
31 #include <isc/util.h>
32
33 #include <dns/db.h>
34 #include <dns/dbiterator.h>
35 #include <dns/dnssec.h>
36 #include <dns/fixedname.h>
37 #include <dns/keytable.h>
38 #include <dns/keyvalues.h>
39 #include <dns/log.h>
40 #include <dns/name.h>
41 #include <dns/nsec.h>
42 #include <dns/nsec3.h>
43 #include <dns/rdata.h>
44 #include <dns/rdataset.h>
45 #include <dns/rdatasetiter.h>
46 #include <dns/rdatastruct.h>
47 #include <dns/rdatatype.h>
48 #include <dns/result.h>
49 #include <dns/secalg.h>
50 #include <dns/types.h>
51 #include <dns/zone.h>
52 #include <dns/zoneverify.h>
53
54 #include <dst/dst.h>
55
56 typedef struct vctx {
57 isc_mem_t *mctx;
58 dns_zone_t *zone;
59 dns_db_t *db;
60 dns_dbversion_t *ver;
61 dns_name_t *origin;
62 dns_keytable_t *secroots;
63 bool goodksk;
64 bool goodzsk;
65 dns_rdataset_t keyset;
66 dns_rdataset_t keysigs;
67 dns_rdataset_t soaset;
68 dns_rdataset_t soasigs;
69 dns_rdataset_t nsecset;
70 dns_rdataset_t nsecsigs;
71 dns_rdataset_t nsec3paramset;
72 dns_rdataset_t nsec3paramsigs;
73 unsigned char revoked_ksk[256];
74 unsigned char revoked_zsk[256];
75 unsigned char standby_ksk[256];
76 unsigned char standby_zsk[256];
77 unsigned char ksk_algorithms[256];
78 unsigned char zsk_algorithms[256];
79 unsigned char bad_algorithms[256];
80 unsigned char act_algorithms[256];
81 isc_heap_t *expected_chains;
82 isc_heap_t *found_chains;
83 } vctx_t;
84
85 struct nsec3_chain_fixed {
86 uint8_t hash;
87 uint8_t salt_length;
88 uint8_t next_length;
89 uint16_t iterations;
90 /*
91 * The following non-fixed-length data is stored in memory after the
92 * fields declared above for each NSEC3 chain element:
93 *
94 * unsigned char salt[salt_length];
95 * unsigned char owner[next_length];
96 * unsigned char next[next_length];
97 */
98 };
99
100 /*%
101 * Log a zone verification error described by 'fmt' and the variable arguments
102 * following it. Either use dns_zone_logv() or print to stderr, depending on
103 * whether the function was invoked from within named or by a standalone tool,
104 * respectively.
105 */
106 static void
107 zoneverify_log_error(const vctx_t *vctx, const char *fmt, ...) {
108 va_list ap;
109
110 va_start(ap, fmt);
111 if (vctx->zone != NULL) {
112 dns_zone_logv(vctx->zone, DNS_LOGCATEGORY_GENERAL,
113 ISC_LOG_ERROR, NULL, fmt, ap);
114 } else {
115 vfprintf(stderr, fmt, ap);
116 fprintf(stderr, "\n");
117 }
118 va_end(ap);
119 }
120
121 static bool
122 is_delegation(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
123 uint32_t *ttlp) {
124 dns_rdataset_t nsset;
125 isc_result_t result;
126
127 if (dns_name_equal(name, vctx->origin)) {
128 return (false);
129 }
130
131 dns_rdataset_init(&nsset);
132 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
133 dns_rdatatype_ns, 0, 0, &nsset, NULL);
134 if (dns_rdataset_isassociated(&nsset)) {
135 if (ttlp != NULL) {
136 *ttlp = nsset.ttl;
137 }
138 dns_rdataset_disassociate(&nsset);
139 }
140
141 return ((result == ISC_R_SUCCESS));
142 }
143
144 /*%
145 * Return true if version 'ver' of database 'db' contains a DNAME RRset at
146 * 'node'; return false otherwise.
147 */
148 static bool
149 has_dname(const vctx_t *vctx, dns_dbnode_t *node) {
150 dns_rdataset_t dnameset;
151 isc_result_t result;
152
153 dns_rdataset_init(&dnameset);
154 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
155 dns_rdatatype_dname, 0, 0, &dnameset,
156 NULL);
157 if (dns_rdataset_isassociated(&dnameset)) {
158 dns_rdataset_disassociate(&dnameset);
159 }
160
161 return ((result == ISC_R_SUCCESS));
162 }
163
164 static bool
165 goodsig(const vctx_t *vctx, dns_rdata_t *sigrdata, const dns_name_t *name,
166 dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset) {
167 dns_rdata_dnskey_t key;
168 dns_rdata_rrsig_t sig;
169 dst_key_t *dstkey = NULL;
170 isc_result_t result;
171
172 result = dns_rdata_tostruct(sigrdata, &sig, NULL);
173 RUNTIME_CHECK(result == ISC_R_SUCCESS);
174
175 for (result = dns_rdataset_first(keyrdataset); result == ISC_R_SUCCESS;
176 result = dns_rdataset_next(keyrdataset))
177 {
178 dns_rdata_t rdata = DNS_RDATA_INIT;
179 dns_rdataset_current(keyrdataset, &rdata);
180 result = dns_rdata_tostruct(&rdata, &key, NULL);
181 RUNTIME_CHECK(result == ISC_R_SUCCESS);
182 result = dns_dnssec_keyfromrdata(vctx->origin, &rdata,
183 vctx->mctx, &dstkey);
184 if (result != ISC_R_SUCCESS) {
185 return (false);
186 }
187 if (sig.algorithm != key.algorithm ||
188 sig.keyid != dst_key_id(dstkey) ||
189 !dns_name_equal(&sig.signer, vctx->origin))
190 {
191 dst_key_free(&dstkey);
192 continue;
193 }
194 result = dns_dnssec_verify(name, rdataset, dstkey, false, 0,
195 vctx->mctx, sigrdata, NULL);
196 dst_key_free(&dstkey);
197 if (result == ISC_R_SUCCESS || result == DNS_R_FROMWILDCARD) {
198 return (true);
199 }
200 }
201 return (false);
202 }
203
204 static bool
205 nsec_bitmap_equal(dns_rdata_nsec_t *nsec, dns_rdata_t *rdata) {
206 isc_result_t result;
207 dns_rdata_nsec_t tmpnsec;
208
209 result = dns_rdata_tostruct(rdata, &tmpnsec, NULL);
210 RUNTIME_CHECK(result == ISC_R_SUCCESS);
211
212 if (nsec->len != tmpnsec.len ||
213 memcmp(nsec->typebits, tmpnsec.typebits, nsec->len) != 0)
214 {
215 return (false);
216 }
217 return (true);
218 }
219
220 static isc_result_t
221 verifynsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
222 const dns_name_t *nextname, isc_result_t *vresult) {
223 unsigned char buffer[DNS_NSEC_BUFFERSIZE];
224 char namebuf[DNS_NAME_FORMATSIZE];
225 char nextbuf[DNS_NAME_FORMATSIZE];
226 char found[DNS_NAME_FORMATSIZE];
227 dns_rdataset_t rdataset;
228 dns_rdata_t rdata = DNS_RDATA_INIT;
229 dns_rdata_t tmprdata = DNS_RDATA_INIT;
230 dns_rdata_nsec_t nsec;
231 isc_result_t result;
232
233 dns_rdataset_init(&rdataset);
234 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
235 dns_rdatatype_nsec, 0, 0, &rdataset, NULL);
236 if (result != ISC_R_SUCCESS) {
237 dns_name_format(name, namebuf, sizeof(namebuf));
238 zoneverify_log_error(vctx, "Missing NSEC record for %s",
239 namebuf);
240 *vresult = ISC_R_FAILURE;
241 result = ISC_R_SUCCESS;
242 goto done;
243 }
244
245 result = dns_rdataset_first(&rdataset);
246 if (result != ISC_R_SUCCESS) {
247 zoneverify_log_error(vctx, "dns_rdataset_first(): %s",
248 isc_result_totext(result));
249 goto done;
250 }
251
252 dns_rdataset_current(&rdataset, &rdata);
253 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
254 RUNTIME_CHECK(result == ISC_R_SUCCESS);
255
256 /* Check next name is consistent */
257 if (!dns_name_equal(&nsec.next, nextname)) {
258 dns_name_format(name, namebuf, sizeof(namebuf));
259 dns_name_format(nextname, nextbuf, sizeof(nextbuf));
260 dns_name_format(&nsec.next, found, sizeof(found));
261 zoneverify_log_error(vctx,
262 "Bad NSEC record for %s, next name "
263 "mismatch (expected:%s, found:%s)",
264 namebuf, nextbuf, found);
265 *vresult = ISC_R_FAILURE;
266 goto done;
267 }
268
269 /* Check bit map is consistent */
270 result = dns_nsec_buildrdata(vctx->db, vctx->ver, node, nextname,
271 buffer, &tmprdata);
272 if (result != ISC_R_SUCCESS) {
273 zoneverify_log_error(vctx, "dns_nsec_buildrdata(): %s",
274 isc_result_totext(result));
275 goto done;
276 }
277 if (!nsec_bitmap_equal(&nsec, &tmprdata)) {
278 dns_name_format(name, namebuf, sizeof(namebuf));
279 zoneverify_log_error(vctx,
280 "Bad NSEC record for %s, bit map "
281 "mismatch",
282 namebuf);
283 *vresult = ISC_R_FAILURE;
284 goto done;
285 }
286
287 result = dns_rdataset_next(&rdataset);
288 if (result != ISC_R_NOMORE) {
289 dns_name_format(name, namebuf, sizeof(namebuf));
290 zoneverify_log_error(vctx, "Multiple NSEC records for %s",
291 namebuf);
292 *vresult = ISC_R_FAILURE;
293 goto done;
294 }
295
296 *vresult = ISC_R_SUCCESS;
297 result = ISC_R_SUCCESS;
298
299 done:
300 if (dns_rdataset_isassociated(&rdataset)) {
301 dns_rdataset_disassociate(&rdataset);
302 }
303
304 return (result);
305 }
306
307 static isc_result_t
308 check_no_rrsig(const vctx_t *vctx, const dns_rdataset_t *rdataset,
309 const dns_name_t *name, dns_dbnode_t *node) {
310 char namebuf[DNS_NAME_FORMATSIZE];
311 char typebuf[DNS_RDATATYPE_FORMATSIZE];
312 dns_rdataset_t sigrdataset;
313 dns_rdatasetiter_t *rdsiter = NULL;
314 isc_result_t result;
315
316 dns_rdataset_init(&sigrdataset);
317 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
318 if (result != ISC_R_SUCCESS) {
319 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
320 isc_result_totext(result));
321 return (result);
322 }
323 for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS;
324 result = dns_rdatasetiter_next(rdsiter))
325 {
326 dns_rdatasetiter_current(rdsiter, &sigrdataset);
327 if (sigrdataset.type == dns_rdatatype_rrsig &&
328 sigrdataset.covers == rdataset->type)
329 {
330 break;
331 }
332 dns_rdataset_disassociate(&sigrdataset);
333 }
334 if (result == ISC_R_SUCCESS) {
335 dns_name_format(name, namebuf, sizeof(namebuf));
336 dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
337 zoneverify_log_error(vctx,
338 "Warning: Found unexpected signatures "
339 "for %s/%s",
340 namebuf, typebuf);
341 }
342 if (dns_rdataset_isassociated(&sigrdataset)) {
343 dns_rdataset_disassociate(&sigrdataset);
344 }
345 dns_rdatasetiter_destroy(&rdsiter);
346
347 return (ISC_R_SUCCESS);
348 }
349
350 static bool
351 chain_compare(void *arg1, void *arg2) {
352 struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
353 size_t len;
354
355 /*
356 * Do each element in turn to get a stable sort.
357 */
358 if (e1->hash < e2->hash) {
359 return (true);
360 }
361 if (e1->hash > e2->hash) {
362 return (false);
363 }
364 if (e1->iterations < e2->iterations) {
365 return (true);
366 }
367 if (e1->iterations > e2->iterations) {
368 return (false);
369 }
370 if (e1->salt_length < e2->salt_length) {
371 return (true);
372 }
373 if (e1->salt_length > e2->salt_length) {
374 return (false);
375 }
376 if (e1->next_length < e2->next_length) {
377 return (true);
378 }
379 if (e1->next_length > e2->next_length) {
380 return (false);
381 }
382 len = e1->salt_length + 2 * e1->next_length;
383 if (memcmp(e1 + 1, e2 + 1, len) < 0) {
384 return (true);
385 }
386 return (false);
387 }
388
389 static bool
390 chain_equal(const struct nsec3_chain_fixed *e1,
391 const struct nsec3_chain_fixed *e2) {
392 size_t len;
393
394 if (e1->hash != e2->hash) {
395 return (false);
396 }
397 if (e1->iterations != e2->iterations) {
398 return (false);
399 }
400 if (e1->salt_length != e2->salt_length) {
401 return (false);
402 }
403 if (e1->next_length != e2->next_length) {
404 return (false);
405 }
406 len = e1->salt_length + 2 * e1->next_length;
407 if (memcmp(e1 + 1, e2 + 1, len) != 0) {
408 return (false);
409 }
410 return (true);
411 }
412
413 static isc_result_t
414 record_nsec3(const vctx_t *vctx, const unsigned char *rawhash,
415 const dns_rdata_nsec3_t *nsec3, isc_heap_t *chains) {
416 struct nsec3_chain_fixed *element;
417 size_t len;
418 unsigned char *cp;
419 isc_result_t result;
420
421 len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
422
423 element = isc_mem_get(vctx->mctx, len);
424 memset(element, 0, len);
425 element->hash = nsec3->hash;
426 element->salt_length = nsec3->salt_length;
427 element->next_length = nsec3->next_length;
428 element->iterations = nsec3->iterations;
429 cp = (unsigned char *)(element + 1);
430 memmove(cp, nsec3->salt, nsec3->salt_length);
431 cp += nsec3->salt_length;
432 memmove(cp, rawhash, nsec3->next_length);
433 cp += nsec3->next_length;
434 memmove(cp, nsec3->next, nsec3->next_length);
435 result = isc_heap_insert(chains, element);
436 if (result != ISC_R_SUCCESS) {
437 zoneverify_log_error(vctx, "isc_heap_insert failed: %s",
438 isc_result_totext(result));
439 isc_mem_put(vctx->mctx, element, len);
440 }
441 return (result);
442 }
443
444 static isc_result_t
445 match_nsec3(const vctx_t *vctx, const dns_name_t *name,
446 const dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset,
447 const unsigned char types[8192], unsigned int maxtype,
448 const unsigned char *rawhash, size_t rhsize,
449 isc_result_t *vresult) {
450 unsigned char cbm[8244];
451 char namebuf[DNS_NAME_FORMATSIZE];
452 dns_rdata_nsec3_t nsec3;
453 isc_result_t result;
454 unsigned int len;
455
456 /*
457 * Find matching NSEC3 record.
458 */
459 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
460 result = dns_rdataset_next(rdataset))
461 {
462 dns_rdata_t rdata = DNS_RDATA_INIT;
463 dns_rdataset_current(rdataset, &rdata);
464 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
465 RUNTIME_CHECK(result == ISC_R_SUCCESS);
466 if (nsec3.hash == nsec3param->hash &&
467 nsec3.next_length == rhsize &&
468 nsec3.iterations == nsec3param->iterations &&
469 nsec3.salt_length == nsec3param->salt_length &&
470 memcmp(nsec3.salt, nsec3param->salt,
471 nsec3param->salt_length) == 0)
472 {
473 break;
474 }
475 }
476 if (result != ISC_R_SUCCESS) {
477 dns_name_format(name, namebuf, sizeof(namebuf));
478 zoneverify_log_error(vctx, "Missing NSEC3 record for %s",
479 namebuf);
480 *vresult = result;
481 return (ISC_R_SUCCESS);
482 }
483
484 /*
485 * Check the type list.
486 */
487 len = dns_nsec_compressbitmap(cbm, types, maxtype);
488 if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) {
489 dns_name_format(name, namebuf, sizeof(namebuf));
490 zoneverify_log_error(vctx,
491 "Bad NSEC3 record for %s, bit map "
492 "mismatch",
493 namebuf);
494 *vresult = ISC_R_FAILURE;
495 return (ISC_R_SUCCESS);
496 }
497
498 /*
499 * Record chain.
500 */
501 result = record_nsec3(vctx, rawhash, &nsec3, vctx->expected_chains);
502 if (result != ISC_R_SUCCESS) {
503 zoneverify_log_error(vctx, "record_nsec3(): %s",
504 isc_result_totext(result));
505 return (result);
506 }
507
508 /*
509 * Make sure there is only one NSEC3 record with this set of
510 * parameters.
511 */
512 for (result = dns_rdataset_next(rdataset); result == ISC_R_SUCCESS;
513 result = dns_rdataset_next(rdataset))
514 {
515 dns_rdata_t rdata = DNS_RDATA_INIT;
516 dns_rdataset_current(rdataset, &rdata);
517 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
518 RUNTIME_CHECK(result == ISC_R_SUCCESS);
519 if (nsec3.hash == nsec3param->hash &&
520 nsec3.iterations == nsec3param->iterations &&
521 nsec3.salt_length == nsec3param->salt_length &&
522 memcmp(nsec3.salt, nsec3param->salt, nsec3.salt_length) ==
523 0)
524 {
525 dns_name_format(name, namebuf, sizeof(namebuf));
526 zoneverify_log_error(vctx,
527 "Multiple NSEC3 records with the "
528 "same parameter set for %s",
529 namebuf);
530 *vresult = DNS_R_DUPLICATE;
531 return (ISC_R_SUCCESS);
532 }
533 }
534 if (result != ISC_R_NOMORE) {
535 return (result);
536 }
537
538 *vresult = ISC_R_SUCCESS;
539
540 return (ISC_R_SUCCESS);
541 }
542
543 static bool
544 innsec3params(const dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
545 dns_rdata_nsec3param_t nsec3param;
546 isc_result_t result;
547
548 for (result = dns_rdataset_first(nsec3paramset);
549 result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset))
550 {
551 dns_rdata_t rdata = DNS_RDATA_INIT;
552
553 dns_rdataset_current(nsec3paramset, &rdata);
554 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
555 RUNTIME_CHECK(result == ISC_R_SUCCESS);
556 if (nsec3param.flags == 0 && nsec3param.hash == nsec3->hash &&
557 nsec3param.iterations == nsec3->iterations &&
558 nsec3param.salt_length == nsec3->salt_length &&
559 memcmp(nsec3param.salt, nsec3->salt, nsec3->salt_length) ==
560 0)
561 {
562 return (true);
563 }
564 }
565 return (false);
566 }
567
568 static isc_result_t
569 record_found(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
570 dns_rdataset_t *nsec3paramset) {
571 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
572 dns_rdata_nsec3_t nsec3;
573 dns_rdataset_t rdataset;
574 dns_label_t hashlabel;
575 isc_buffer_t b;
576 isc_result_t result;
577
578 if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
579 {
580 return (ISC_R_SUCCESS);
581 }
582
583 dns_rdataset_init(&rdataset);
584 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
585 dns_rdatatype_nsec3, 0, 0, &rdataset,
586 NULL);
587 if (result != ISC_R_SUCCESS) {
588 return (ISC_R_SUCCESS);
589 }
590
591 dns_name_getlabel(name, 0, &hashlabel);
592 isc_region_consume(&hashlabel, 1);
593 isc_buffer_init(&b, owner, sizeof(owner));
594 result = isc_base32hex_decoderegion(&hashlabel, &b);
595 if (result != ISC_R_SUCCESS) {
596 result = ISC_R_SUCCESS;
597 goto cleanup;
598 }
599
600 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
601 result = dns_rdataset_next(&rdataset))
602 {
603 dns_rdata_t rdata = DNS_RDATA_INIT;
604 dns_rdataset_current(&rdataset, &rdata);
605 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
606 RUNTIME_CHECK(result == ISC_R_SUCCESS);
607 if (nsec3.next_length != isc_buffer_usedlength(&b)) {
608 continue;
609 }
610 /*
611 * We only care about NSEC3 records that match a NSEC3PARAM
612 * record.
613 */
614 if (!innsec3params(&nsec3, nsec3paramset)) {
615 continue;
616 }
617
618 /*
619 * Record chain.
620 */
621 result = record_nsec3(vctx, owner, &nsec3, vctx->found_chains);
622 if (result != ISC_R_SUCCESS) {
623 zoneverify_log_error(vctx, "record_nsec3(): %s",
624 isc_result_totext(result));
625 goto cleanup;
626 }
627 }
628 result = ISC_R_SUCCESS;
629
630 cleanup:
631 dns_rdataset_disassociate(&rdataset);
632 return (result);
633 }
634
635 static isc_result_t
636 isoptout(const vctx_t *vctx, const dns_rdata_t *nsec3rdata, bool *optout) {
637 dns_rdataset_t rdataset;
638 dns_rdata_t rdata = DNS_RDATA_INIT;
639 dns_rdata_nsec3_t nsec3;
640 dns_rdata_nsec3param_t nsec3param;
641 dns_fixedname_t fixed;
642 dns_name_t *hashname;
643 isc_result_t result;
644 dns_dbnode_t *node = NULL;
645 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
646 size_t rhsize = sizeof(rawhash);
647
648 result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL);
649 RUNTIME_CHECK(result == ISC_R_SUCCESS);
650
651 dns_fixedname_init(&fixed);
652 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, vctx->origin,
653 vctx->origin, nsec3param.hash,
654 nsec3param.iterations, nsec3param.salt,
655 nsec3param.salt_length);
656 if (result != ISC_R_SUCCESS) {
657 zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s",
658 isc_result_totext(result));
659 return (result);
660 }
661
662 dns_rdataset_init(&rdataset);
663 hashname = dns_fixedname_name(&fixed);
664 result = dns_db_findnsec3node(vctx->db, hashname, false, &node);
665 if (result == ISC_R_SUCCESS) {
666 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
667 dns_rdatatype_nsec3, 0, 0,
668 &rdataset, NULL);
669 }
670 if (result != ISC_R_SUCCESS) {
671 *optout = false;
672 result = ISC_R_SUCCESS;
673 goto done;
674 }
675
676 result = dns_rdataset_first(&rdataset);
677 if (result != ISC_R_SUCCESS) {
678 zoneverify_log_error(vctx, "dns_rdataset_first(): %s",
679 isc_result_totext(result));
680 goto done;
681 }
682
683 dns_rdataset_current(&rdataset, &rdata);
684
685 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
686 RUNTIME_CHECK(result == ISC_R_SUCCESS);
687 *optout = ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
688
689 done:
690 if (dns_rdataset_isassociated(&rdataset)) {
691 dns_rdataset_disassociate(&rdataset);
692 }
693 if (node != NULL) {
694 dns_db_detachnode(vctx->db, &node);
695 }
696
697 return (result);
698 }
699
700 static isc_result_t
701 verifynsec3(const vctx_t *vctx, const dns_name_t *name,
702 const dns_rdata_t *rdata, bool delegation, bool empty,
703 const unsigned char types[8192], unsigned int maxtype,
704 isc_result_t *vresult) {
705 char namebuf[DNS_NAME_FORMATSIZE];
706 char hashbuf[DNS_NAME_FORMATSIZE];
707 dns_rdataset_t rdataset;
708 dns_rdata_nsec3param_t nsec3param;
709 dns_fixedname_t fixed;
710 dns_name_t *hashname;
711 isc_result_t result, tvresult = ISC_R_UNSET;
712 dns_dbnode_t *node = NULL;
713 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
714 size_t rhsize = sizeof(rawhash);
715 bool optout = false;
716
717 result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
718 RUNTIME_CHECK(result == ISC_R_SUCCESS);
719
720 if (nsec3param.flags != 0) {
721 return (ISC_R_SUCCESS);
722 }
723
724 if (!dns_nsec3_supportedhash(nsec3param.hash)) {
725 return (ISC_R_SUCCESS);
726 }
727
728 result = isoptout(vctx, rdata, &optout);
729 if (result != ISC_R_SUCCESS) {
730 return (result);
731 }
732
733 dns_fixedname_init(&fixed);
734 result = dns_nsec3_hashname(
735 &fixed, rawhash, &rhsize, name, vctx->origin, nsec3param.hash,
736 nsec3param.iterations, nsec3param.salt, nsec3param.salt_length);
737 if (result != ISC_R_SUCCESS) {
738 zoneverify_log_error(vctx, "dns_nsec3_hashname(): %s",
739 isc_result_totext(result));
740 return (result);
741 }
742
743 /*
744 * We don't use dns_db_find() here as it works with the chosen
745 * nsec3 chain and we may also be called with uncommitted data
746 * from dnssec-signzone so the secure status of the zone may not
747 * be up to date.
748 */
749 dns_rdataset_init(&rdataset);
750 hashname = dns_fixedname_name(&fixed);
751 result = dns_db_findnsec3node(vctx->db, hashname, false, &node);
752 if (result == ISC_R_SUCCESS) {
753 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
754 dns_rdatatype_nsec3, 0, 0,
755 &rdataset, NULL);
756 }
757 if (result != ISC_R_SUCCESS &&
758 (!delegation || (empty && !optout) ||
759 (!empty && dns_nsec_isset(types, dns_rdatatype_ds))))
760 {
761 dns_name_format(name, namebuf, sizeof(namebuf));
762 dns_name_format(hashname, hashbuf, sizeof(hashbuf));
763 zoneverify_log_error(vctx, "Missing NSEC3 record for %s (%s)",
764 namebuf, hashbuf);
765 } else if (result == ISC_R_NOTFOUND && delegation && (!empty || optout))
766 {
767 result = ISC_R_SUCCESS;
768 } else if (result == ISC_R_SUCCESS) {
769 result = match_nsec3(vctx, name, &nsec3param, &rdataset, types,
770 maxtype, rawhash, rhsize, &tvresult);
771 if (result != ISC_R_SUCCESS) {
772 goto done;
773 }
774 result = tvresult;
775 }
776
777 *vresult = result;
778 result = ISC_R_SUCCESS;
779
780 done:
781 if (dns_rdataset_isassociated(&rdataset)) {
782 dns_rdataset_disassociate(&rdataset);
783 }
784 if (node != NULL) {
785 dns_db_detachnode(vctx->db, &node);
786 }
787
788 return (result);
789 }
790
791 static isc_result_t
792 verifynsec3s(const vctx_t *vctx, const dns_name_t *name,
793 dns_rdataset_t *nsec3paramset, bool delegation, bool empty,
794 const unsigned char types[8192], unsigned int maxtype,
795 isc_result_t *vresult) {
796 isc_result_t result;
797
798 for (result = dns_rdataset_first(nsec3paramset);
799 result == ISC_R_SUCCESS; result = dns_rdataset_next(nsec3paramset))
800 {
801 dns_rdata_t rdata = DNS_RDATA_INIT;
802
803 dns_rdataset_current(nsec3paramset, &rdata);
804 result = verifynsec3(vctx, name, &rdata, delegation, empty,
805 types, maxtype, vresult);
806 if (result != ISC_R_SUCCESS) {
807 return (result);
808 }
809 if (*vresult != ISC_R_SUCCESS) {
810 break;
811 }
812 }
813 if (result == ISC_R_NOMORE) {
814 result = ISC_R_SUCCESS;
815 }
816 return (result);
817 }
818
819 static isc_result_t
820 verifyset(vctx_t *vctx, dns_rdataset_t *rdataset, const dns_name_t *name,
821 dns_dbnode_t *node, dns_rdataset_t *keyrdataset) {
822 unsigned char set_algorithms[256];
823 char namebuf[DNS_NAME_FORMATSIZE];
824 char algbuf[DNS_SECALG_FORMATSIZE];
825 char typebuf[DNS_RDATATYPE_FORMATSIZE];
826 dns_rdataset_t sigrdataset;
827 dns_rdatasetiter_t *rdsiter = NULL;
828 isc_result_t result;
829 int i;
830
831 dns_rdataset_init(&sigrdataset);
832 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
833 if (result != ISC_R_SUCCESS) {
834 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
835 isc_result_totext(result));
836 return (result);
837 }
838 for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS;
839 result = dns_rdatasetiter_next(rdsiter))
840 {
841 dns_rdatasetiter_current(rdsiter, &sigrdataset);
842 if (sigrdataset.type == dns_rdatatype_rrsig &&
843 sigrdataset.covers == rdataset->type)
844 {
845 break;
846 }
847 dns_rdataset_disassociate(&sigrdataset);
848 }
849 if (result != ISC_R_SUCCESS) {
850 dns_name_format(name, namebuf, sizeof(namebuf));
851 dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
852 zoneverify_log_error(vctx, "No signatures for %s/%s", namebuf,
853 typebuf);
854 for (i = 0; i < 256; i++) {
855 if (vctx->act_algorithms[i] != 0) {
856 vctx->bad_algorithms[i] = 1;
857 }
858 }
859 result = ISC_R_SUCCESS;
860 goto done;
861 }
862
863 memset(set_algorithms, 0, sizeof(set_algorithms));
864 for (result = dns_rdataset_first(&sigrdataset); result == ISC_R_SUCCESS;
865 result = dns_rdataset_next(&sigrdataset))
866 {
867 dns_rdata_t rdata = DNS_RDATA_INIT;
868 dns_rdata_rrsig_t sig;
869
870 dns_rdataset_current(&sigrdataset, &rdata);
871 result = dns_rdata_tostruct(&rdata, &sig, NULL);
872 RUNTIME_CHECK(result == ISC_R_SUCCESS);
873 if (rdataset->ttl != sig.originalttl) {
874 dns_name_format(name, namebuf, sizeof(namebuf));
875 dns_rdatatype_format(rdataset->type, typebuf,
876 sizeof(typebuf));
877 zoneverify_log_error(vctx,
878 "TTL mismatch for "
879 "%s %s keytag %u",
880 namebuf, typebuf, sig.keyid);
881 continue;
882 }
883 if ((set_algorithms[sig.algorithm] != 0) ||
884 (vctx->act_algorithms[sig.algorithm] == 0))
885 {
886 continue;
887 }
888 if (goodsig(vctx, &rdata, name, keyrdataset, rdataset)) {
889 dns_rdataset_settrust(rdataset, dns_trust_secure);
890 dns_rdataset_settrust(&sigrdataset, dns_trust_secure);
891 set_algorithms[sig.algorithm] = 1;
892 }
893 }
894 result = ISC_R_SUCCESS;
895
896 if (memcmp(set_algorithms, vctx->act_algorithms,
897 sizeof(set_algorithms))) {
898 dns_name_format(name, namebuf, sizeof(namebuf));
899 dns_rdatatype_format(rdataset->type, typebuf, sizeof(typebuf));
900 for (i = 0; i < 256; i++) {
901 if ((vctx->act_algorithms[i] != 0) &&
902 (set_algorithms[i] == 0)) {
903 dns_secalg_format(i, algbuf, sizeof(algbuf));
904 zoneverify_log_error(vctx,
905 "No correct %s signature "
906 "for %s %s",
907 algbuf, namebuf, typebuf);
908 vctx->bad_algorithms[i] = 1;
909 }
910 }
911 }
912
913 done:
914 if (dns_rdataset_isassociated(&sigrdataset)) {
915 dns_rdataset_disassociate(&sigrdataset);
916 }
917 dns_rdatasetiter_destroy(&rdsiter);
918
919 return (result);
920 }
921
922 static isc_result_t
923 verifynode(vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node,
924 bool delegation, dns_rdataset_t *keyrdataset,
925 dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
926 const dns_name_t *nextname, isc_result_t *vresult) {
927 unsigned char types[8192];
928 unsigned int maxtype = 0;
929 dns_rdataset_t rdataset;
930 dns_rdatasetiter_t *rdsiter = NULL;
931 isc_result_t result, tvresult = ISC_R_UNSET;
932
933 REQUIRE(vresult != NULL || (nsecset == NULL && nsec3paramset == NULL));
934
935 memset(types, 0, sizeof(types));
936 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
937 if (result != ISC_R_SUCCESS) {
938 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
939 isc_result_totext(result));
940 return (result);
941 }
942 result = dns_rdatasetiter_first(rdsiter);
943 dns_rdataset_init(&rdataset);
944 while (result == ISC_R_SUCCESS) {
945 dns_rdatasetiter_current(rdsiter, &rdataset);
946 /*
947 * If we are not at a delegation then everything should be
948 * signed. If we are at a delegation then only the DS set
949 * is signed. The NS set is not signed at a delegation but
950 * its existence is recorded in the bit map. Anything else
951 * other than NSEC and DS is not signed at a delegation.
952 */
953 if (rdataset.type != dns_rdatatype_rrsig &&
954 rdataset.type != dns_rdatatype_dnskey &&
955 (!delegation || rdataset.type == dns_rdatatype_ds ||
956 rdataset.type == dns_rdatatype_nsec))
957 {
958 result = verifyset(vctx, &rdataset, name, node,
959 keyrdataset);
960 if (result != ISC_R_SUCCESS) {
961 dns_rdataset_disassociate(&rdataset);
962 dns_rdatasetiter_destroy(&rdsiter);
963 return (result);
964 }
965 dns_nsec_setbit(types, rdataset.type, 1);
966 if (rdataset.type > maxtype) {
967 maxtype = rdataset.type;
968 }
969 } else if (rdataset.type != dns_rdatatype_rrsig &&
970 rdataset.type != dns_rdatatype_dnskey)
971 {
972 if (rdataset.type == dns_rdatatype_ns) {
973 dns_nsec_setbit(types, rdataset.type, 1);
974 }
975 result = check_no_rrsig(vctx, &rdataset, name, node);
976 if (result != ISC_R_SUCCESS) {
977 dns_rdataset_disassociate(&rdataset);
978 dns_rdatasetiter_destroy(&rdsiter);
979 return (result);
980 }
981 } else {
982 dns_nsec_setbit(types, rdataset.type, 1);
983 }
984 dns_rdataset_disassociate(&rdataset);
985 result = dns_rdatasetiter_next(rdsiter);
986 }
987 dns_rdatasetiter_destroy(&rdsiter);
988 if (result != ISC_R_NOMORE) {
989 zoneverify_log_error(vctx, "rdataset iteration failed: %s",
990 isc_result_totext(result));
991 return (result);
992 }
993
994 if (vresult == NULL) {
995 return (ISC_R_SUCCESS);
996 }
997
998 *vresult = ISC_R_SUCCESS;
999
1000 if (nsecset != NULL && dns_rdataset_isassociated(nsecset)) {
1001 result = verifynsec(vctx, name, node, nextname, &tvresult);
1002 if (result != ISC_R_SUCCESS) {
1003 return (result);
1004 }
1005 *vresult = tvresult;
1006 }
1007
1008 if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
1009 result = verifynsec3s(vctx, name, nsec3paramset, delegation,
1010 false, types, maxtype, &tvresult);
1011 if (result != ISC_R_SUCCESS) {
1012 return (result);
1013 }
1014 if (*vresult == ISC_R_SUCCESS) {
1015 *vresult = tvresult;
1016 }
1017 }
1018
1019 return (ISC_R_SUCCESS);
1020 }
1021
1022 static isc_result_t
1023 is_empty(const vctx_t *vctx, dns_dbnode_t *node, bool *empty) {
1024 dns_rdatasetiter_t *rdsiter = NULL;
1025 isc_result_t result;
1026
1027 result = dns_db_allrdatasets(vctx->db, node, vctx->ver, 0, &rdsiter);
1028 if (result != ISC_R_SUCCESS) {
1029 zoneverify_log_error(vctx, "dns_db_allrdatasets(): %s",
1030 isc_result_totext(result));
1031 return (result);
1032 }
1033 result = dns_rdatasetiter_first(rdsiter);
1034 dns_rdatasetiter_destroy(&rdsiter);
1035
1036 *empty = (result == ISC_R_NOMORE);
1037
1038 return (ISC_R_SUCCESS);
1039 }
1040
1041 static isc_result_t
1042 check_no_nsec(const vctx_t *vctx, const dns_name_t *name, dns_dbnode_t *node) {
1043 bool nsec_exists = false;
1044 dns_rdataset_t rdataset;
1045 isc_result_t result;
1046
1047 dns_rdataset_init(&rdataset);
1048 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1049 dns_rdatatype_nsec, 0, 0, &rdataset, NULL);
1050 if (result != ISC_R_NOTFOUND) {
1051 char namebuf[DNS_NAME_FORMATSIZE];
1052 dns_name_format(name, namebuf, sizeof(namebuf));
1053 zoneverify_log_error(vctx, "unexpected NSEC RRset at %s",
1054 namebuf);
1055 nsec_exists = true;
1056 }
1057
1058 if (dns_rdataset_isassociated(&rdataset)) {
1059 dns_rdataset_disassociate(&rdataset);
1060 }
1061
1062 return (nsec_exists ? ISC_R_FAILURE : ISC_R_SUCCESS);
1063 }
1064
1065 static bool
1066 newchain(const struct nsec3_chain_fixed *first,
1067 const struct nsec3_chain_fixed *e) {
1068 if (first->hash != e->hash || first->iterations != e->iterations ||
1069 first->salt_length != e->salt_length ||
1070 first->next_length != e->next_length ||
1071 memcmp(first + 1, e + 1, first->salt_length) != 0)
1072 {
1073 return (true);
1074 }
1075 return (false);
1076 }
1077
1078 static void
1079 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
1080 size_t len;
1081
1082 len = sizeof(*e) + e->salt_length + 2 * e->next_length;
1083 isc_mem_put(mctx, e, len);
1084 }
1085
1086 static void
1087 free_element_heap(void *element, void *uap) {
1088 struct nsec3_chain_fixed *e = (struct nsec3_chain_fixed *)element;
1089 isc_mem_t *mctx = (isc_mem_t *)uap;
1090
1091 free_element(mctx, e);
1092 }
1093
1094 static bool
1095 _checknext(const vctx_t *vctx, const struct nsec3_chain_fixed *first,
1096 const struct nsec3_chain_fixed *e) {
1097 char buf[512];
1098 const unsigned char *d1 = (const unsigned char *)(first + 1);
1099 const unsigned char *d2 = (const unsigned char *)(e + 1);
1100 isc_buffer_t b;
1101 isc_region_t sr;
1102
1103 d1 += first->salt_length + first->next_length;
1104 d2 += e->salt_length;
1105
1106 if (memcmp(d1, d2, first->next_length) == 0) {
1107 return (true);
1108 }
1109
1110 DE_CONST(d1 - first->next_length, sr.base);
1111 sr.length = first->next_length;
1112 isc_buffer_init(&b, buf, sizeof(buf));
1113 isc_base32hex_totext(&sr, 1, "", &b);
1114 zoneverify_log_error(vctx, "Break in NSEC3 chain at: %.*s",
1115 (int)isc_buffer_usedlength(&b), buf);
1116
1117 DE_CONST(d1, sr.base);
1118 sr.length = first->next_length;
1119 isc_buffer_init(&b, buf, sizeof(buf));
1120 isc_base32hex_totext(&sr, 1, "", &b);
1121 zoneverify_log_error(vctx, "Expected: %.*s",
1122 (int)isc_buffer_usedlength(&b), buf);
1123
1124 DE_CONST(d2, sr.base);
1125 sr.length = first->next_length;
1126 isc_buffer_init(&b, buf, sizeof(buf));
1127 isc_base32hex_totext(&sr, 1, "", &b);
1128 zoneverify_log_error(vctx, "Found: %.*s",
1129 (int)isc_buffer_usedlength(&b), buf);
1130
1131 return (false);
1132 }
1133
1134 static inline bool
1135 checknext(isc_mem_t *mctx, const vctx_t *vctx,
1136 const struct nsec3_chain_fixed *first, struct nsec3_chain_fixed *prev,
1137 const struct nsec3_chain_fixed *cur) {
1138 bool result = _checknext(vctx, prev, cur);
1139
1140 if (prev != first) {
1141 free_element(mctx, prev);
1142 }
1143
1144 return (result);
1145 }
1146
1147 static inline bool
1148 checklast(isc_mem_t *mctx, const vctx_t *vctx, struct nsec3_chain_fixed *first,
1149 struct nsec3_chain_fixed *prev) {
1150 bool result = _checknext(vctx, prev, first);
1151 if (prev != first) {
1152 free_element(mctx, prev);
1153 }
1154 free_element(mctx, first);
1155
1156 return (result);
1157 }
1158
1159 static isc_result_t
1160 verify_nsec3_chains(const vctx_t *vctx, isc_mem_t *mctx) {
1161 isc_result_t result = ISC_R_SUCCESS;
1162 struct nsec3_chain_fixed *e, *f = NULL;
1163 struct nsec3_chain_fixed *first = NULL, *prev = NULL;
1164
1165 while ((e = isc_heap_element(vctx->expected_chains, 1)) != NULL) {
1166 isc_heap_delete(vctx->expected_chains, 1);
1167 if (f == NULL) {
1168 f = isc_heap_element(vctx->found_chains, 1);
1169 }
1170 if (f != NULL) {
1171 isc_heap_delete(vctx->found_chains, 1);
1172
1173 /*
1174 * Check that they match.
1175 */
1176 if (chain_equal(e, f)) {
1177 free_element(mctx, f);
1178 f = NULL;
1179 } else {
1180 if (result == ISC_R_SUCCESS) {
1181 zoneverify_log_error(vctx, "Expected "
1182 "and found "
1183 "NSEC3 "
1184 "chains not "
1185 "equal");
1186 }
1187 result = ISC_R_FAILURE;
1188 /*
1189 * Attempt to resync found_chain.
1190 */
1191 while (f != NULL && !chain_compare(e, f)) {
1192 free_element(mctx, f);
1193 f = isc_heap_element(vctx->found_chains,
1194 1);
1195 if (f != NULL) {
1196 isc_heap_delete(
1197 vctx->found_chains, 1);
1198 }
1199 if (f != NULL && chain_equal(e, f)) {
1200 free_element(mctx, f);
1201 f = NULL;
1202 break;
1203 }
1204 }
1205 }
1206 } else if (result == ISC_R_SUCCESS) {
1207 zoneverify_log_error(vctx, "Expected and found NSEC3 "
1208 "chains "
1209 "not equal");
1210 result = ISC_R_FAILURE;
1211 }
1212
1213 if (first == NULL) {
1214 prev = first = e;
1215 } else if (newchain(first, e)) {
1216 if (!checklast(mctx, vctx, first, prev)) {
1217 result = ISC_R_FAILURE;
1218 }
1219
1220 prev = first = e;
1221 } else {
1222 if (!checknext(mctx, vctx, first, prev, e)) {
1223 result = ISC_R_FAILURE;
1224 }
1225
1226 prev = e;
1227 }
1228 }
1229 if (prev != NULL) {
1230 if (!checklast(mctx, vctx, first, prev)) {
1231 result = ISC_R_FAILURE;
1232 }
1233 }
1234 do {
1235 if (f != NULL) {
1236 if (result == ISC_R_SUCCESS) {
1237 zoneverify_log_error(vctx, "Expected and found "
1238 "NSEC3 chains not "
1239 "equal");
1240 result = ISC_R_FAILURE;
1241 }
1242 free_element(mctx, f);
1243 }
1244 f = isc_heap_element(vctx->found_chains, 1);
1245 if (f != NULL) {
1246 isc_heap_delete(vctx->found_chains, 1);
1247 }
1248 } while (f != NULL);
1249
1250 return (result);
1251 }
1252
1253 static isc_result_t
1254 verifyemptynodes(const vctx_t *vctx, const dns_name_t *name,
1255 const dns_name_t *prevname, bool isdelegation,
1256 dns_rdataset_t *nsec3paramset, isc_result_t *vresult) {
1257 dns_namereln_t reln;
1258 int order;
1259 unsigned int labels, nlabels, i;
1260 dns_name_t suffix;
1261 isc_result_t result, tvresult = ISC_R_UNSET;
1262
1263 *vresult = ISC_R_SUCCESS;
1264
1265 reln = dns_name_fullcompare(prevname, name, &order, &labels);
1266 if (order >= 0) {
1267 return (ISC_R_SUCCESS);
1268 }
1269
1270 nlabels = dns_name_countlabels(name);
1271
1272 if (reln == dns_namereln_commonancestor ||
1273 reln == dns_namereln_contains) {
1274 dns_name_init(&suffix, NULL);
1275 for (i = labels + 1; i < nlabels; i++) {
1276 dns_name_getlabelsequence(name, nlabels - i, i,
1277 &suffix);
1278 if (nsec3paramset != NULL &&
1279 dns_rdataset_isassociated(nsec3paramset)) {
1280 result = verifynsec3s(
1281 vctx, &suffix, nsec3paramset,
1282 isdelegation, true, NULL, 0, &tvresult);
1283 if (result != ISC_R_SUCCESS) {
1284 return (result);
1285 }
1286 if (*vresult == ISC_R_SUCCESS) {
1287 *vresult = tvresult;
1288 }
1289 }
1290 }
1291 }
1292
1293 return (ISC_R_SUCCESS);
1294 }
1295
1296 static isc_result_t
1297 vctx_init(vctx_t *vctx, isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
1298 dns_dbversion_t *ver, dns_name_t *origin, dns_keytable_t *secroots) {
1299 isc_result_t result;
1300
1301 memset(vctx, 0, sizeof(*vctx));
1302
1303 vctx->mctx = mctx;
1304 vctx->zone = zone;
1305 vctx->db = db;
1306 vctx->ver = ver;
1307 vctx->origin = origin;
1308 vctx->secroots = secroots;
1309 vctx->goodksk = false;
1310 vctx->goodzsk = false;
1311
1312 dns_rdataset_init(&vctx->keyset);
1313 dns_rdataset_init(&vctx->keysigs);
1314 dns_rdataset_init(&vctx->soaset);
1315 dns_rdataset_init(&vctx->soasigs);
1316 dns_rdataset_init(&vctx->nsecset);
1317 dns_rdataset_init(&vctx->nsecsigs);
1318 dns_rdataset_init(&vctx->nsec3paramset);
1319 dns_rdataset_init(&vctx->nsec3paramsigs);
1320
1321 vctx->expected_chains = NULL;
1322 result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1323 &vctx->expected_chains);
1324 if (result != ISC_R_SUCCESS) {
1325 return (result);
1326 }
1327
1328 vctx->found_chains = NULL;
1329 result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1330 &vctx->found_chains);
1331 if (result != ISC_R_SUCCESS) {
1332 isc_heap_destroy(&vctx->expected_chains);
1333 return (result);
1334 }
1335
1336 return (result);
1337 }
1338
1339 static void
1340 vctx_destroy(vctx_t *vctx) {
1341 if (dns_rdataset_isassociated(&vctx->keyset)) {
1342 dns_rdataset_disassociate(&vctx->keyset);
1343 }
1344 if (dns_rdataset_isassociated(&vctx->keysigs)) {
1345 dns_rdataset_disassociate(&vctx->keysigs);
1346 }
1347 if (dns_rdataset_isassociated(&vctx->soaset)) {
1348 dns_rdataset_disassociate(&vctx->soaset);
1349 }
1350 if (dns_rdataset_isassociated(&vctx->soasigs)) {
1351 dns_rdataset_disassociate(&vctx->soasigs);
1352 }
1353 if (dns_rdataset_isassociated(&vctx->nsecset)) {
1354 dns_rdataset_disassociate(&vctx->nsecset);
1355 }
1356 if (dns_rdataset_isassociated(&vctx->nsecsigs)) {
1357 dns_rdataset_disassociate(&vctx->nsecsigs);
1358 }
1359 if (dns_rdataset_isassociated(&vctx->nsec3paramset)) {
1360 dns_rdataset_disassociate(&vctx->nsec3paramset);
1361 }
1362 if (dns_rdataset_isassociated(&vctx->nsec3paramsigs)) {
1363 dns_rdataset_disassociate(&vctx->nsec3paramsigs);
1364 }
1365 isc_heap_foreach(vctx->expected_chains, free_element_heap, vctx->mctx);
1366 isc_heap_destroy(&vctx->expected_chains);
1367 isc_heap_foreach(vctx->found_chains, free_element_heap, vctx->mctx);
1368 isc_heap_destroy(&vctx->found_chains);
1369 }
1370
1371 static isc_result_t
1372 check_apex_rrsets(vctx_t *vctx) {
1373 dns_dbnode_t *node = NULL;
1374 isc_result_t result;
1375
1376 result = dns_db_findnode(vctx->db, vctx->origin, false, &node);
1377 if (result != ISC_R_SUCCESS) {
1378 zoneverify_log_error(vctx,
1379 "failed to find the zone's origin: %s",
1380 isc_result_totext(result));
1381 return (result);
1382 }
1383
1384 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1385 dns_rdatatype_dnskey, 0, 0, &vctx->keyset,
1386 &vctx->keysigs);
1387 if (result != ISC_R_SUCCESS) {
1388 zoneverify_log_error(vctx, "Zone contains no DNSSEC keys");
1389 goto done;
1390 }
1391
1392 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1393 dns_rdatatype_soa, 0, 0, &vctx->soaset,
1394 &vctx->soasigs);
1395 if (result != ISC_R_SUCCESS) {
1396 zoneverify_log_error(vctx, "Zone contains no SOA record");
1397 goto done;
1398 }
1399
1400 result = dns_db_findrdataset(vctx->db, node, vctx->ver,
1401 dns_rdatatype_nsec, 0, 0, &vctx->nsecset,
1402 &vctx->nsecsigs);
1403 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
1404 zoneverify_log_error(vctx, "NSEC lookup failed");
1405 goto done;
1406 }
1407
1408 result = dns_db_findrdataset(
1409 vctx->db, node, vctx->ver, dns_rdatatype_nsec3param, 0, 0,
1410 &vctx->nsec3paramset, &vctx->nsec3paramsigs);
1411 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
1412 zoneverify_log_error(vctx, "NSEC3PARAM lookup failed");
1413 goto done;
1414 }
1415
1416 if (!dns_rdataset_isassociated(&vctx->keysigs)) {
1417 zoneverify_log_error(vctx, "DNSKEY is not signed "
1418 "(keys offline or inactive?)");
1419 result = ISC_R_FAILURE;
1420 goto done;
1421 }
1422
1423 if (!dns_rdataset_isassociated(&vctx->soasigs)) {
1424 zoneverify_log_error(vctx, "SOA is not signed "
1425 "(keys offline or inactive?)");
1426 result = ISC_R_FAILURE;
1427 goto done;
1428 }
1429
1430 if (dns_rdataset_isassociated(&vctx->nsecset) &&
1431 !dns_rdataset_isassociated(&vctx->nsecsigs))
1432 {
1433 zoneverify_log_error(vctx, "NSEC is not signed "
1434 "(keys offline or inactive?)");
1435 result = ISC_R_FAILURE;
1436 goto done;
1437 }
1438
1439 if (dns_rdataset_isassociated(&vctx->nsec3paramset) &&
1440 !dns_rdataset_isassociated(&vctx->nsec3paramsigs))
1441 {
1442 zoneverify_log_error(vctx, "NSEC3PARAM is not signed "
1443 "(keys offline or inactive?)");
1444 result = ISC_R_FAILURE;
1445 goto done;
1446 }
1447
1448 if (!dns_rdataset_isassociated(&vctx->nsecset) &&
1449 !dns_rdataset_isassociated(&vctx->nsec3paramset))
1450 {
1451 zoneverify_log_error(vctx, "No valid NSEC/NSEC3 chain for "
1452 "testing");
1453 result = ISC_R_FAILURE;
1454 goto done;
1455 }
1456
1457 result = ISC_R_SUCCESS;
1458
1459 done:
1460 dns_db_detachnode(vctx->db, &node);
1461
1462 return (result);
1463 }
1464
1465 /*%
1466 * Update 'vctx' tables tracking active and standby key algorithms used in the
1467 * verified zone based on the signatures made using 'dnskey' (prepared from
1468 * 'rdata') found at zone apex. Set 'vctx->goodksk' or 'vctx->goodzsk' to true
1469 * if 'dnskey' correctly signs the DNSKEY RRset at zone apex and either
1470 * 'vctx->secroots' is NULL or 'dnskey' is present in 'vctx->secroots'.
1471 *
1472 * The variables to update are chosen based on 'is_ksk', which is true when
1473 * 'dnskey' is a KSK and false otherwise.
1474 */
1475 static void
1476 check_dnskey_sigs(vctx_t *vctx, const dns_rdata_dnskey_t *dnskey,
1477 dns_rdata_t *keyrdata, bool is_ksk) {
1478 unsigned char *active_keys = NULL, *standby_keys = NULL;
1479 dns_keynode_t *keynode = NULL;
1480 bool *goodkey = NULL;
1481 dst_key_t *key = NULL;
1482 isc_result_t result;
1483 dns_rdataset_t dsset;
1484
1485 active_keys = (is_ksk ? vctx->ksk_algorithms : vctx->zsk_algorithms);
1486 standby_keys = (is_ksk ? vctx->standby_ksk : vctx->standby_zsk);
1487 goodkey = (is_ksk ? &vctx->goodksk : &vctx->goodzsk);
1488
1489 /*
1490 * First, does this key sign the DNSKEY rrset?
1491 */
1492 if (!dns_dnssec_selfsigns(keyrdata, vctx->origin, &vctx->keyset,
1493 &vctx->keysigs, false, vctx->mctx))
1494 {
1495 if (!is_ksk &&
1496 dns_dnssec_signs(keyrdata, vctx->origin, &vctx->soaset,
1497 &vctx->soasigs, false, vctx->mctx))
1498 {
1499 if (active_keys[dnskey->algorithm] != 255) {
1500 active_keys[dnskey->algorithm]++;
1501 }
1502 } else {
1503 if (standby_keys[dnskey->algorithm] != 255) {
1504 standby_keys[dnskey->algorithm]++;
1505 }
1506 }
1507 return;
1508 }
1509
1510 if (active_keys[dnskey->algorithm] != 255) {
1511 active_keys[dnskey->algorithm]++;
1512 }
1513
1514 /*
1515 * If a trust anchor table was not supplied, a correctly self-signed
1516 * DNSKEY RRset is good enough.
1517 */
1518 if (vctx->secroots == NULL) {
1519 *goodkey = true;
1520 return;
1521 }
1522
1523 /*
1524 * Convert the supplied key rdata to dst_key_t. (If this
1525 * fails we can't go further.)
1526 */
1527 result = dns_dnssec_keyfromrdata(vctx->origin, keyrdata, vctx->mctx,
1528 &key);
1529 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1530
1531 /*
1532 * Look up the supplied key in the trust anchor table.
1533 * If we don't find an exact match, or if the keynode data
1534 * is NULL, then we have neither a DNSKEY nor a DS format
1535 * trust anchor, and can give up.
1536 */
1537 result = dns_keytable_find(vctx->secroots, vctx->origin, &keynode);
1538 if (result != ISC_R_SUCCESS) {
1539 /* No such trust anchor */
1540 goto cleanup;
1541 }
1542
1543 /*
1544 * If the keynode has any DS format trust anchors, that means
1545 * it doesn't have any DNSKEY ones. So, we can check for a DS
1546 * match and then stop.
1547 */
1548 dns_rdataset_init(&dsset);
1549 if (dns_keynode_dsset(keynode, &dsset)) {
1550 for (result = dns_rdataset_first(&dsset);
1551 result == ISC_R_SUCCESS;
1552 result = dns_rdataset_next(&dsset))
1553 {
1554 dns_rdata_t dsrdata = DNS_RDATA_INIT;
1555 dns_rdata_t newdsrdata = DNS_RDATA_INIT;
1556 unsigned char buf[DNS_DS_BUFFERSIZE];
1557 dns_rdata_ds_t ds;
1558
1559 dns_rdata_reset(&dsrdata);
1560 dns_rdataset_current(&dsset, &dsrdata);
1561 result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
1562 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1563
1564 if (ds.key_tag != dst_key_id(key) ||
1565 ds.algorithm != dst_key_alg(key)) {
1566 continue;
1567 }
1568
1569 result = dns_ds_buildrdata(vctx->origin, keyrdata,
1570 ds.digest_type, buf,
1571 &newdsrdata);
1572 if (result != ISC_R_SUCCESS) {
1573 continue;
1574 }
1575
1576 if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0) {
1577 dns_rdataset_settrust(&vctx->keyset,
1578 dns_trust_secure);
1579 dns_rdataset_settrust(&vctx->keysigs,
1580 dns_trust_secure);
1581 *goodkey = true;
1582 break;
1583 }
1584 }
1585 dns_rdataset_disassociate(&dsset);
1586
1587 goto cleanup;
1588 }
1589
1590 cleanup:
1591 if (keynode != NULL) {
1592 dns_keytable_detachkeynode(vctx->secroots, &keynode);
1593 }
1594 if (key != NULL) {
1595 dst_key_free(&key);
1596 }
1597 }
1598
1599 /*%
1600 * Check that the DNSKEY RR has at least one self signing KSK and one ZSK per
1601 * algorithm in it (or, if -x was used, one self-signing KSK).
1602 */
1603 static isc_result_t
1604 check_dnskey(vctx_t *vctx) {
1605 dns_rdata_t rdata = DNS_RDATA_INIT;
1606 dns_rdata_dnskey_t dnskey;
1607 isc_result_t result;
1608 bool is_ksk;
1609
1610 for (result = dns_rdataset_first(&vctx->keyset);
1611 result == ISC_R_SUCCESS; result = dns_rdataset_next(&vctx->keyset))
1612 {
1613 dns_rdataset_current(&vctx->keyset, &rdata);
1614 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1615 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1616 is_ksk = ((dnskey.flags & DNS_KEYFLAG_KSK) != 0);
1617
1618 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0) {
1619 /* Non zone key, skip. */
1620 } else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1621 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1622 !dns_dnssec_selfsigns(&rdata, vctx->origin,
1623 &vctx->keyset, &vctx->keysigs,
1624 false, vctx->mctx))
1625 {
1626 char namebuf[DNS_NAME_FORMATSIZE];
1627 char buffer[1024];
1628 isc_buffer_t buf;
1629
1630 dns_name_format(vctx->origin, namebuf,
1631 sizeof(namebuf));
1632 isc_buffer_init(&buf, buffer, sizeof(buffer));
1633 result = dns_rdata_totext(&rdata, NULL, &buf);
1634 if (result != ISC_R_SUCCESS) {
1635 zoneverify_log_error(
1636 vctx, "dns_rdata_totext: %s",
1637 isc_result_totext(result));
1638 return (ISC_R_FAILURE);
1639 }
1640 zoneverify_log_error(
1641 vctx,
1642 "revoked KSK is not self signed:\n"
1643 "%s DNSKEY %.*s",
1644 namebuf,
1645 (int)isc_buffer_usedlength(&buf),
1646 buffer);
1647 return (ISC_R_FAILURE);
1648 }
1649 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1650 vctx->revoked_ksk[dnskey.algorithm] != 255)
1651 {
1652 vctx->revoked_ksk[dnskey.algorithm]++;
1653 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1654 vctx->revoked_zsk[dnskey.algorithm] != 255)
1655 {
1656 vctx->revoked_zsk[dnskey.algorithm]++;
1657 }
1658 } else {
1659 check_dnskey_sigs(vctx, &dnskey, &rdata, is_ksk);
1660 }
1661 dns_rdata_freestruct(&dnskey);
1662 dns_rdata_reset(&rdata);
1663 }
1664
1665 return (ISC_R_SUCCESS);
1666 }
1667
1668 static void
1669 determine_active_algorithms(vctx_t *vctx, bool ignore_kskflag,
1670 bool keyset_kskonly,
1671 void (*report)(const char *, ...)) {
1672 char algbuf[DNS_SECALG_FORMATSIZE];
1673 int i;
1674
1675 report("Verifying the zone using the following algorithms:");
1676
1677 for (i = 0; i < 256; i++) {
1678 if (ignore_kskflag) {
1679 vctx->act_algorithms[i] = (vctx->ksk_algorithms[i] !=
1680 0 ||
1681 vctx->zsk_algorithms[i] != 0)
1682 ? 1
1683 : 0;
1684 } else {
1685 vctx->act_algorithms[i] = vctx->ksk_algorithms[i] != 0
1686 ? 1
1687 : 0;
1688 }
1689 if (vctx->act_algorithms[i] != 0) {
1690 dns_secalg_format(i, algbuf, sizeof(algbuf));
1691 report(" %s", algbuf);
1692 }
1693 }
1694 report(".\n");
1695
1696 if (ignore_kskflag || keyset_kskonly) {
1697 return;
1698 }
1699
1700 for (i = 0; i < 256; i++) {
1701 /*
1702 * The counts should both be zero or both be non-zero. Mark
1703 * the algorithm as bad if this is not met.
1704 */
1705 if ((vctx->ksk_algorithms[i] != 0) ==
1706 (vctx->zsk_algorithms[i] != 0)) {
1707 continue;
1708 }
1709 dns_secalg_format(i, algbuf, sizeof(algbuf));
1710 zoneverify_log_error(vctx, "Missing %s for algorithm %s",
1711 (vctx->ksk_algorithms[i] != 0) ? "ZSK"
1712 : "self-"
1713 "signed "
1714 "KSK",
1715 algbuf);
1716 vctx->bad_algorithms[i] = 1;
1717 }
1718 }
1719
1720 /*%
1721 * Check that all the records not yet verified were signed by keys that are
1722 * present in the DNSKEY RRset.
1723 */
1724 static isc_result_t
1725 verify_nodes(vctx_t *vctx, isc_result_t *vresult) {
1726 dns_fixedname_t fname, fnextname, fprevname, fzonecut;
1727 dns_name_t *name, *nextname, *prevname, *zonecut;
1728 dns_dbnode_t *node = NULL, *nextnode;
1729 dns_dbiterator_t *dbiter = NULL;
1730 bool done = false;
1731 isc_result_t tvresult = ISC_R_UNSET;
1732 isc_result_t result;
1733
1734 name = dns_fixedname_initname(&fname);
1735 nextname = dns_fixedname_initname(&fnextname);
1736 dns_fixedname_init(&fprevname);
1737 prevname = NULL;
1738 dns_fixedname_init(&fzonecut);
1739 zonecut = NULL;
1740
1741 result = dns_db_createiterator(vctx->db, DNS_DB_NONSEC3, &dbiter);
1742 if (result != ISC_R_SUCCESS) {
1743 zoneverify_log_error(vctx, "dns_db_createiterator(): %s",
1744 isc_result_totext(result));
1745 return (result);
1746 }
1747
1748 result = dns_dbiterator_first(dbiter);
1749 if (result != ISC_R_SUCCESS) {
1750 zoneverify_log_error(vctx, "dns_dbiterator_first(): %s",
1751 isc_result_totext(result));
1752 goto done;
1753 }
1754
1755 while (!done) {
1756 bool isdelegation = false;
1757
1758 result = dns_dbiterator_current(dbiter, &node, name);
1759 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
1760 zoneverify_log_error(vctx,
1761 "dns_dbiterator_current(): %s",
1762 isc_result_totext(result));
1763 goto done;
1764 }
1765 if (!dns_name_issubdomain(name, vctx->origin)) {
1766 result = check_no_nsec(vctx, name, node);
1767 if (result != ISC_R_SUCCESS) {
1768 dns_db_detachnode(vctx->db, &node);
1769 goto done;
1770 }
1771 dns_db_detachnode(vctx->db, &node);
1772 result = dns_dbiterator_next(dbiter);
1773 if (result == ISC_R_NOMORE) {
1774 done = true;
1775 } else if (result != ISC_R_SUCCESS) {
1776 zoneverify_log_error(vctx,
1777 "dns_dbiterator_next(): "
1778 "%s",
1779 isc_result_totext(result));
1780 goto done;
1781 }
1782 continue;
1783 }
1784 if (is_delegation(vctx, name, node, NULL)) {
1785 zonecut = dns_fixedname_name(&fzonecut);
1786 dns_name_copynf(name, zonecut);
1787 isdelegation = true;
1788 } else if (has_dname(vctx, node)) {
1789 zonecut = dns_fixedname_name(&fzonecut);
1790 dns_name_copynf(name, zonecut);
1791 }
1792 nextnode = NULL;
1793 result = dns_dbiterator_next(dbiter);
1794 while (result == ISC_R_SUCCESS) {
1795 bool empty;
1796 result = dns_dbiterator_current(dbiter, &nextnode,
1797 nextname);
1798 if (result != ISC_R_SUCCESS &&
1799 result != DNS_R_NEWORIGIN) {
1800 zoneverify_log_error(vctx,
1801 "dns_dbiterator_current():"
1802 " %s",
1803 isc_result_totext(result));
1804 dns_db_detachnode(vctx->db, &node);
1805 goto done;
1806 }
1807 if (!dns_name_issubdomain(nextname, vctx->origin) ||
1808 (zonecut != NULL &&
1809 dns_name_issubdomain(nextname, zonecut)))
1810 {
1811 result = check_no_nsec(vctx, nextname,
1812 nextnode);
1813 if (result != ISC_R_SUCCESS) {
1814 dns_db_detachnode(vctx->db, &node);
1815 dns_db_detachnode(vctx->db, &nextnode);
1816 goto done;
1817 }
1818 dns_db_detachnode(vctx->db, &nextnode);
1819 result = dns_dbiterator_next(dbiter);
1820 continue;
1821 }
1822 result = is_empty(vctx, nextnode, &empty);
1823 dns_db_detachnode(vctx->db, &nextnode);
1824 if (result != ISC_R_SUCCESS) {
1825 dns_db_detachnode(vctx->db, &node);
1826 goto done;
1827 }
1828 if (empty) {
1829 result = dns_dbiterator_next(dbiter);
1830 continue;
1831 }
1832 break;
1833 }
1834 if (result == ISC_R_NOMORE) {
1835 done = true;
1836 nextname = vctx->origin;
1837 } else if (result != ISC_R_SUCCESS) {
1838 zoneverify_log_error(vctx,
1839 "iterating through the database "
1840 "failed: %s",
1841 isc_result_totext(result));
1842 dns_db_detachnode(vctx->db, &node);
1843 goto done;
1844 }
1845 result = verifynode(vctx, name, node, isdelegation,
1846 &vctx->keyset, &vctx->nsecset,
1847 &vctx->nsec3paramset, nextname, &tvresult);
1848 if (result != ISC_R_SUCCESS) {
1849 dns_db_detachnode(vctx->db, &node);
1850 goto done;
1851 }
1852 if (*vresult == ISC_R_UNSET) {
1853 *vresult = ISC_R_SUCCESS;
1854 }
1855 if (*vresult == ISC_R_SUCCESS) {
1856 *vresult = tvresult;
1857 }
1858 if (prevname != NULL) {
1859 result = verifyemptynodes(
1860 vctx, name, prevname, isdelegation,
1861 &vctx->nsec3paramset, &tvresult);
1862 if (result != ISC_R_SUCCESS) {
1863 dns_db_detachnode(vctx->db, &node);
1864 goto done;
1865 }
1866 } else {
1867 prevname = dns_fixedname_name(&fprevname);
1868 }
1869 dns_name_copynf(name, prevname);
1870 if (*vresult == ISC_R_SUCCESS) {
1871 *vresult = tvresult;
1872 }
1873 dns_db_detachnode(vctx->db, &node);
1874 }
1875
1876 dns_dbiterator_destroy(&dbiter);
1877
1878 result = dns_db_createiterator(vctx->db, DNS_DB_NSEC3ONLY, &dbiter);
1879 if (result != ISC_R_SUCCESS) {
1880 zoneverify_log_error(vctx, "dns_db_createiterator(): %s",
1881 isc_result_totext(result));
1882 return (result);
1883 }
1884
1885 for (result = dns_dbiterator_first(dbiter); result == ISC_R_SUCCESS;
1886 result = dns_dbiterator_next(dbiter))
1887 {
1888 result = dns_dbiterator_current(dbiter, &node, name);
1889 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
1890 zoneverify_log_error(vctx,
1891 "dns_dbiterator_current(): %s",
1892 isc_result_totext(result));
1893 goto done;
1894 }
1895 result = verifynode(vctx, name, node, false, &vctx->keyset,
1896 NULL, NULL, NULL, NULL);
1897 if (result != ISC_R_SUCCESS) {
1898 zoneverify_log_error(vctx, "verifynode: %s",
1899 isc_result_totext(result));
1900 dns_db_detachnode(vctx->db, &node);
1901 goto done;
1902 }
1903 result = record_found(vctx, name, node, &vctx->nsec3paramset);
1904 dns_db_detachnode(vctx->db, &node);
1905 if (result != ISC_R_SUCCESS) {
1906 goto done;
1907 }
1908 }
1909
1910 result = ISC_R_SUCCESS;
1911
1912 done:
1913 dns_dbiterator_destroy(&dbiter);
1914
1915 return (result);
1916 }
1917
1918 static isc_result_t
1919 check_bad_algorithms(const vctx_t *vctx, void (*report)(const char *, ...)) {
1920 char algbuf[DNS_SECALG_FORMATSIZE];
1921 bool first = true;
1922 int i;
1923
1924 for (i = 0; i < 256; i++) {
1925 if (vctx->bad_algorithms[i] == 0) {
1926 continue;
1927 }
1928 if (first) {
1929 report("The zone is not fully signed "
1930 "for the following algorithms:");
1931 }
1932 dns_secalg_format(i, algbuf, sizeof(algbuf));
1933 report(" %s", algbuf);
1934 first = false;
1935 }
1936
1937 if (!first) {
1938 report(".\n");
1939 }
1940
1941 return (first ? ISC_R_SUCCESS : ISC_R_FAILURE);
1942 }
1943
1944 static void
1945 print_summary(const vctx_t *vctx, bool keyset_kskonly,
1946 void (*report)(const char *, ...)) {
1947 char algbuf[DNS_SECALG_FORMATSIZE];
1948 int i;
1949
1950 report("Zone fully signed:\n");
1951 for (i = 0; i < 256; i++) {
1952 if ((vctx->ksk_algorithms[i] == 0) &&
1953 (vctx->standby_ksk[i] == 0) &&
1954 (vctx->revoked_ksk[i] == 0) &&
1955 (vctx->zsk_algorithms[i] == 0) &&
1956 (vctx->standby_zsk[i] == 0) && (vctx->revoked_zsk[i] == 0))
1957 {
1958 continue;
1959 }
1960 dns_secalg_format(i, algbuf, sizeof(algbuf));
1961 report("Algorithm: %s: KSKs: "
1962 "%u active, %u stand-by, %u revoked\n",
1963 algbuf, vctx->ksk_algorithms[i], vctx->standby_ksk[i],
1964 vctx->revoked_ksk[i]);
1965 report("%*sZSKs: "
1966 "%u active, %u %s, %u revoked\n",
1967 (int)strlen(algbuf) + 13, "", vctx->zsk_algorithms[i],
1968 vctx->standby_zsk[i],
1969 keyset_kskonly ? "present" : "stand-by",
1970 vctx->revoked_zsk[i]);
1971 }
1972 }
1973
1974 isc_result_t
1975 dns_zoneverify_dnssec(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
1976 dns_name_t *origin, dns_keytable_t *secroots,
1977 isc_mem_t *mctx, bool ignore_kskflag, bool keyset_kskonly,
1978 void (*report)(const char *, ...)) {
1979 const char *keydesc = (secroots == NULL ? "self-signed" : "trusted");
1980 isc_result_t result, vresult = ISC_R_UNSET;
1981 vctx_t vctx;
1982
1983 result = vctx_init(&vctx, mctx, zone, db, ver, origin, secroots);
1984 if (result != ISC_R_SUCCESS) {
1985 return (result);
1986 }
1987
1988 result = check_apex_rrsets(&vctx);
1989 if (result != ISC_R_SUCCESS) {
1990 goto done;
1991 }
1992
1993 result = check_dnskey(&vctx);
1994 if (result != ISC_R_SUCCESS) {
1995 goto done;
1996 }
1997
1998 if (ignore_kskflag) {
1999 if (!vctx.goodksk && !vctx.goodzsk) {
2000 zoneverify_log_error(&vctx, "No %s DNSKEY found",
2001 keydesc);
2002 result = ISC_R_FAILURE;
2003 goto done;
2004 }
2005 } else if (!vctx.goodksk) {
2006 zoneverify_log_error(&vctx, "No %s KSK DNSKEY found", keydesc);
2007 result = ISC_R_FAILURE;
2008 goto done;
2009 }
2010
2011 determine_active_algorithms(&vctx, ignore_kskflag, keyset_kskonly,
2012 report);
2013
2014 result = verify_nodes(&vctx, &vresult);
2015 if (result != ISC_R_SUCCESS) {
2016 goto done;
2017 }
2018
2019 result = verify_nsec3_chains(&vctx, mctx);
2020 if (vresult == ISC_R_UNSET) {
2021 vresult = ISC_R_SUCCESS;
2022 }
2023 if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS) {
2024 vresult = result;
2025 }
2026
2027 result = check_bad_algorithms(&vctx, report);
2028 if (result != ISC_R_SUCCESS) {
2029 report("DNSSEC completeness test failed.\n");
2030 goto done;
2031 }
2032
2033 result = vresult;
2034 if (result != ISC_R_SUCCESS) {
2035 report("DNSSEC completeness test failed (%s).\n",
2036 dns_result_totext(result));
2037 goto done;
2038 }
2039
2040 if (vctx.goodksk || ignore_kskflag) {
2041 print_summary(&vctx, keyset_kskonly, report);
2042 }
2043
2044 done:
2045 vctx_destroy(&vctx);
2046
2047 return (result);
2048 }
2049