etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / dnssec / dnssectool.c
blobd965f64422088173a821d07ee3b8d398583652a2
1 /* $NetBSD: dnssectool.c,v 1.9 2015/07/08 17:28:55 christos Exp $ */
3 /*
4 * Copyright (C) 2004, 2005, 2007, 2009-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /*! \file */
22 /*%
23 * DNSSEC Support Routines.
26 #include <config.h>
28 #include <stdlib.h>
30 #include <isc/base32.h>
31 #include <isc/buffer.h>
32 #include <isc/dir.h>
33 #include <isc/entropy.h>
34 #include <isc/heap.h>
35 #include <isc/list.h>
36 #include <isc/mem.h>
37 #include <isc/string.h>
38 #include <isc/time.h>
39 #include <isc/util.h>
40 #include <isc/print.h>
42 #include <dns/db.h>
43 #include <dns/dbiterator.h>
44 #include <dns/dnssec.h>
45 #include <dns/fixedname.h>
46 #include <dns/keyvalues.h>
47 #include <dns/log.h>
48 #include <dns/name.h>
49 #include <dns/nsec.h>
50 #include <dns/nsec3.h>
51 #include <dns/rdatastruct.h>
52 #include <dns/rdataclass.h>
53 #include <dns/rdataset.h>
54 #include <dns/rdatasetiter.h>
55 #include <dns/rdatatype.h>
56 #include <dns/result.h>
57 #include <dns/secalg.h>
58 #include <dns/time.h>
60 #include "dnssectool.h"
62 static isc_heap_t *expected_chains, *found_chains;
64 struct nsec3_chain_fixed {
65 isc_uint8_t hash;
66 isc_uint8_t salt_length;
67 isc_uint8_t next_length;
68 isc_uint16_t iterations;
69 /* unsigned char salt[0]; */
70 /* unsigned char owner[0]; */
71 /* unsigned char next[0]; */
74 extern int verbose;
75 extern const char *program;
77 typedef struct entropysource entropysource_t;
79 struct entropysource {
80 isc_entropysource_t *source;
81 isc_mem_t *mctx;
82 ISC_LINK(entropysource_t) link;
85 static ISC_LIST(entropysource_t) sources;
86 static fatalcallback_t *fatalcallback = NULL;
88 void
89 fatal(const char *format, ...) {
90 va_list args;
92 fprintf(stderr, "%s: fatal: ", program);
93 va_start(args, format);
94 vfprintf(stderr, format, args);
95 va_end(args);
96 fprintf(stderr, "\n");
97 if (fatalcallback != NULL)
98 (*fatalcallback)();
99 exit(1);
102 void
103 setfatalcallback(fatalcallback_t *callback) {
104 fatalcallback = callback;
107 void
108 check_result(isc_result_t result, const char *message) {
109 if (result != ISC_R_SUCCESS)
110 fatal("%s: %s", message, isc_result_totext(result));
113 void
114 vbprintf(int level, const char *fmt, ...) {
115 va_list ap;
116 if (level > verbose)
117 return;
118 va_start(ap, fmt);
119 fprintf(stderr, "%s: ", program);
120 vfprintf(stderr, fmt, ap);
121 va_end(ap);
124 void
125 version(const char *name) {
126 fprintf(stderr, "%s %s\n", name, VERSION);
127 exit(0);
130 void
131 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
132 isc_buffer_t b;
133 isc_region_t r;
134 isc_result_t result;
136 isc_buffer_init(&b, cp, size - 1);
137 result = dns_rdatatype_totext(type, &b);
138 check_result(result, "dns_rdatatype_totext()");
139 isc_buffer_usedregion(&b, &r);
140 r.base[r.length] = 0;
143 void
144 sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) {
145 char namestr[DNS_NAME_FORMATSIZE];
146 char algstr[DNS_NAME_FORMATSIZE];
148 dns_name_format(&sig->signer, namestr, sizeof(namestr));
149 dns_secalg_format(sig->algorithm, algstr, sizeof(algstr));
150 snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
153 void
154 setup_logging(isc_mem_t *mctx, isc_log_t **logp) {
155 isc_result_t result;
156 isc_logdestination_t destination;
157 isc_logconfig_t *logconfig = NULL;
158 isc_log_t *log = NULL;
159 int level;
161 if (verbose < 0)
162 verbose = 0;
163 switch (verbose) {
164 case 0:
166 * We want to see warnings about things like out-of-zone
167 * data in the master file even when not verbose.
169 level = ISC_LOG_WARNING;
170 break;
171 case 1:
172 level = ISC_LOG_INFO;
173 break;
174 default:
175 level = ISC_LOG_DEBUG(verbose - 2 + 1);
176 break;
179 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
180 isc_log_setcontext(log);
181 dns_log_init(log);
182 dns_log_setcontext(log);
184 RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
187 * Set up a channel similar to default_stderr except:
188 * - the logging level is passed in
189 * - the program name and logging level are printed
190 * - no time stamp is printed
192 destination.file.stream = stderr;
193 destination.file.name = NULL;
194 destination.file.versions = ISC_LOG_ROLLNEVER;
195 destination.file.maximum_size = 0;
196 result = isc_log_createchannel(logconfig, "stderr",
197 ISC_LOG_TOFILEDESC,
198 level,
199 &destination,
200 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
201 check_result(result, "isc_log_createchannel()");
203 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
204 NULL, NULL) == ISC_R_SUCCESS);
206 *logp = log;
209 void
210 cleanup_logging(isc_log_t **logp) {
211 isc_log_t *log;
213 REQUIRE(logp != NULL);
215 log = *logp;
216 if (log == NULL)
217 return;
218 isc_log_destroy(&log);
219 isc_log_setcontext(NULL);
220 dns_log_setcontext(NULL);
221 logp = NULL;
224 void
225 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
226 isc_result_t result;
227 isc_entropysource_t *source = NULL;
228 entropysource_t *elt;
229 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
231 REQUIRE(ectx != NULL);
233 if (*ectx == NULL) {
234 result = isc_entropy_create(mctx, ectx);
235 if (result != ISC_R_SUCCESS)
236 fatal("could not create entropy object");
237 ISC_LIST_INIT(sources);
240 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
241 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
242 randomfile = NULL;
245 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
246 usekeyboard);
248 if (result != ISC_R_SUCCESS)
249 fatal("could not initialize entropy source: %s",
250 isc_result_totext(result));
252 if (source != NULL) {
253 elt = isc_mem_get(mctx, sizeof(*elt));
254 if (elt == NULL)
255 fatal("out of memory");
256 elt->source = source;
257 elt->mctx = mctx;
258 ISC_LINK_INIT(elt, link);
259 ISC_LIST_APPEND(sources, elt, link);
263 void
264 cleanup_entropy(isc_entropy_t **ectx) {
265 entropysource_t *source;
266 while (!ISC_LIST_EMPTY(sources)) {
267 source = ISC_LIST_HEAD(sources);
268 ISC_LIST_UNLINK(sources, source, link);
269 isc_entropy_destroysource(&source->source);
270 isc_mem_put(source->mctx, source, sizeof(*source));
272 isc_entropy_detach(ectx);
275 static isc_stdtime_t
276 time_units(isc_stdtime_t offset, char *suffix, const char *str) {
277 switch (suffix[0]) {
278 case 'Y': case 'y':
279 return (offset * (365 * 24 * 3600));
280 case 'M': case 'm':
281 switch (suffix[1]) {
282 case 'O': case 'o':
283 return (offset * (30 * 24 * 3600));
284 case 'I': case 'i':
285 return (offset * 60);
286 case '\0':
287 fatal("'%s' ambiguous: use 'mi' for minutes "
288 "or 'mo' for months", str);
289 default:
290 fatal("time value %s is invalid", str);
292 /* NOTREACHED */
293 break;
294 case 'W': case 'w':
295 return (offset * (7 * 24 * 3600));
296 case 'D': case 'd':
297 return (offset * (24 * 3600));
298 case 'H': case 'h':
299 return (offset * 3600);
300 case 'S': case 's': case '\0':
301 return (offset);
302 default:
303 fatal("time value %s is invalid", str);
305 /* NOTREACHED */
306 return(0); /* silence compiler warning */
309 static inline isc_boolean_t
310 isnone(const char *str) {
311 return (ISC_TF((strcasecmp(str, "none") == 0) ||
312 (strcasecmp(str, "never") == 0)));
315 dns_ttl_t
316 strtottl(const char *str) {
317 const char *orig = str;
318 dns_ttl_t ttl;
319 char *endp;
321 if (isnone(str))
322 return ((dns_ttl_t) 0);
324 ttl = strtol(str, &endp, 0);
325 if (ttl == 0 && endp == str)
326 fatal("TTL must be numeric");
327 ttl = time_units(ttl, endp, orig);
328 return (ttl);
331 isc_stdtime_t
332 strtotime(const char *str, isc_int64_t now, isc_int64_t base,
333 isc_boolean_t *setp)
335 isc_int64_t val, offset;
336 isc_result_t result;
337 const char *orig = str;
338 char *endp;
339 size_t n;
341 if (isnone(str)) {
342 if (setp != NULL)
343 *setp = ISC_FALSE;
344 return ((isc_stdtime_t) 0);
347 if (setp != NULL)
348 *setp = ISC_TRUE;
350 if ((str[0] == '0' || str[0] == '-') && str[1] == '\0')
351 return ((isc_stdtime_t) 0);
354 * We accept times in the following formats:
355 * now([+-]offset)
356 * YYYYMMDD([+-]offset)
357 * YYYYMMDDhhmmss([+-]offset)
358 * [+-]offset
360 n = strspn(str, "0123456789");
361 if ((n == 8u || n == 14u) &&
362 (str[n] == '\0' || str[n] == '-' || str[n] == '+'))
364 char timestr[15];
366 strlcpy(timestr, str, sizeof(timestr));
367 timestr[n] = 0;
368 if (n == 8u)
369 strlcat(timestr, "000000", sizeof(timestr));
370 result = dns_time64_fromtext(timestr, &val);
371 if (result != ISC_R_SUCCESS)
372 fatal("time value %s is invalid: %s", orig,
373 isc_result_totext(result));
374 base = val;
375 str += n;
376 } else if (strncmp(str, "now", 3) == 0) {
377 base = now;
378 str += 3;
381 if (str[0] == '\0')
382 return ((isc_stdtime_t) base);
383 else if (str[0] == '+') {
384 offset = strtol(str + 1, &endp, 0);
385 offset = time_units((isc_stdtime_t) offset, endp, orig);
386 val = base + offset;
387 } else if (str[0] == '-') {
388 offset = strtol(str + 1, &endp, 0);
389 offset = time_units((isc_stdtime_t) offset, endp, orig);
390 val = base - offset;
391 } else
392 fatal("time value %s is invalid", orig);
394 return ((isc_stdtime_t) val);
397 dns_rdataclass_t
398 strtoclass(const char *str) {
399 isc_textregion_t r;
400 dns_rdataclass_t rdclass;
401 isc_result_t ret;
403 if (str == NULL)
404 return dns_rdataclass_in;
405 DE_CONST(str, r.base);
406 r.length = strlen(str);
407 ret = dns_rdataclass_fromtext(&rdclass, &r);
408 if (ret != ISC_R_SUCCESS)
409 fatal("unknown class %s", str);
410 return (rdclass);
413 isc_result_t
414 try_dir(const char *dirname) {
415 isc_result_t result;
416 isc_dir_t d;
418 isc_dir_init(&d);
419 result = isc_dir_open(&d, dirname);
420 if (result == ISC_R_SUCCESS) {
421 isc_dir_close(&d);
423 return (result);
427 * Check private key version compatibility.
429 void
430 check_keyversion(dst_key_t *key, char *keystr) {
431 int major, minor;
432 dst_key_getprivateformat(key, &major, &minor);
433 INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */
435 if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
436 fatal("Key %s has incompatible format version %d.%d, "
437 "use -f to force upgrade to new version.",
438 keystr, major, minor);
439 if (minor > DST_MINOR_VERSION)
440 fatal("Key %s has incompatible format version %d.%d, "
441 "use -f to force downgrade to current version.",
442 keystr, major, minor);
445 void
446 set_keyversion(dst_key_t *key) {
447 int major, minor;
448 dst_key_getprivateformat(key, &major, &minor);
449 INSIST(major <= DST_MAJOR_VERSION);
451 if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION)
452 dst_key_setprivateformat(key, DST_MAJOR_VERSION,
453 DST_MINOR_VERSION);
456 * If the key is from a version older than 1.3, set
457 * set the creation date
459 if (major < 1 || (major == 1 && minor <= 2)) {
460 isc_stdtime_t now;
461 isc_stdtime_get(&now);
462 dst_key_settime(key, DST_TIME_CREATED, now);
466 isc_boolean_t
467 key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
468 isc_mem_t *mctx, isc_boolean_t *exact)
470 isc_result_t result;
471 isc_boolean_t conflict = ISC_FALSE;
472 dns_dnsseckeylist_t matchkeys;
473 dns_dnsseckey_t *key = NULL;
474 isc_uint16_t id, oldid;
475 isc_uint32_t rid, roldid;
476 dns_secalg_t alg;
478 if (exact != NULL)
479 *exact = ISC_FALSE;
481 id = dst_key_id(dstkey);
482 rid = dst_key_rid(dstkey);
483 alg = dst_key_alg(dstkey);
485 ISC_LIST_INIT(matchkeys);
486 result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys);
487 if (result == ISC_R_NOTFOUND)
488 return (ISC_FALSE);
490 while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
491 key = ISC_LIST_HEAD(matchkeys);
492 if (dst_key_alg(key->key) != alg)
493 goto next;
495 oldid = dst_key_id(key->key);
496 roldid = dst_key_rid(key->key);
498 if (oldid == rid || roldid == id || id == oldid) {
499 conflict = ISC_TRUE;
500 if (id != oldid) {
501 if (verbose > 1)
502 fprintf(stderr, "Key ID %d could "
503 "collide with %d\n",
504 id, oldid);
505 } else {
506 if (exact != NULL)
507 *exact = ISC_TRUE;
508 if (verbose > 1)
509 fprintf(stderr, "Key ID %d exists\n",
510 id);
514 next:
515 ISC_LIST_UNLINK(matchkeys, key, link);
516 dns_dnsseckey_destroy(mctx, &key);
519 /* Finish freeing the list */
520 while (!ISC_LIST_EMPTY(matchkeys)) {
521 key = ISC_LIST_HEAD(matchkeys);
522 ISC_LIST_UNLINK(matchkeys, key, link);
523 dns_dnsseckey_destroy(mctx, &key);
526 return (conflict);
529 isc_boolean_t
530 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
531 dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp)
533 dns_rdataset_t nsset;
534 isc_result_t result;
536 if (dns_name_equal(name, origin))
537 return (ISC_FALSE);
539 dns_rdataset_init(&nsset);
540 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns,
541 0, 0, &nsset, NULL);
542 if (dns_rdataset_isassociated(&nsset)) {
543 if (ttlp != NULL)
544 *ttlp = nsset.ttl;
545 dns_rdataset_disassociate(&nsset);
548 return (ISC_TF(result == ISC_R_SUCCESS));
551 static isc_boolean_t
552 goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name,
553 dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx)
555 dns_rdata_dnskey_t key;
556 dns_rdata_rrsig_t sig;
557 dst_key_t *dstkey = NULL;
558 isc_result_t result;
560 result = dns_rdata_tostruct(sigrdata, &sig, NULL);
561 check_result(result, "dns_rdata_tostruct()");
563 for (result = dns_rdataset_first(keyrdataset);
564 result == ISC_R_SUCCESS;
565 result = dns_rdataset_next(keyrdataset)) {
566 dns_rdata_t rdata = DNS_RDATA_INIT;
567 dns_rdataset_current(keyrdataset, &rdata);
568 result = dns_rdata_tostruct(&rdata, &key, NULL);
569 check_result(result, "dns_rdata_tostruct()");
570 result = dns_dnssec_keyfromrdata(origin, &rdata, mctx,
571 &dstkey);
572 if (result != ISC_R_SUCCESS)
573 return (ISC_FALSE);
574 if (sig.algorithm != key.algorithm ||
575 sig.keyid != dst_key_id(dstkey) ||
576 !dns_name_equal(&sig.signer, origin)) {
577 dst_key_free(&dstkey);
578 continue;
580 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
581 mctx, sigrdata);
582 dst_key_free(&dstkey);
583 if (result == ISC_R_SUCCESS)
584 return(ISC_TRUE);
586 return (ISC_FALSE);
589 static isc_result_t
590 verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
591 dns_dbnode_t *node, dns_name_t *nextname)
593 unsigned char buffer[DNS_NSEC_BUFFERSIZE];
594 char namebuf[DNS_NAME_FORMATSIZE];
595 char nextbuf[DNS_NAME_FORMATSIZE];
596 char found[DNS_NAME_FORMATSIZE];
597 dns_rdataset_t rdataset;
598 dns_rdata_t rdata = DNS_RDATA_INIT;
599 dns_rdata_t tmprdata = DNS_RDATA_INIT;
600 dns_rdata_nsec_t nsec;
601 isc_result_t result;
603 dns_rdataset_init(&rdataset);
604 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
605 0, 0, &rdataset, NULL);
606 if (result != ISC_R_SUCCESS) {
607 dns_name_format(name, namebuf, sizeof(namebuf));
608 fprintf(stderr, "Missing NSEC record for %s\n", namebuf);
609 goto failure;
612 result = dns_rdataset_first(&rdataset);
613 check_result(result, "dns_rdataset_first()");
615 dns_rdataset_current(&rdataset, &rdata);
616 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
617 check_result(result, "dns_rdata_tostruct()");
618 /* Check bit next name is consistent */
619 if (!dns_name_equal(&nsec.next, nextname)) {
620 dns_name_format(name, namebuf, sizeof(namebuf));
621 dns_name_format(nextname, nextbuf, sizeof(nextbuf));
622 dns_name_format(&nsec.next, found, sizeof(found));
623 fprintf(stderr, "Bad NSEC record for %s, next name "
624 "mismatch (expected:%s, found:%s)\n", namebuf,
625 nextbuf, found);
626 goto failure;
628 /* Check bit map is consistent */
629 result = dns_nsec_buildrdata(db, ver, node, nextname, buffer,
630 &tmprdata);
631 check_result(result, "dns_nsec_buildrdata()");
632 if (dns_rdata_compare(&rdata, &tmprdata) != 0) {
633 dns_name_format(name, namebuf, sizeof(namebuf));
634 fprintf(stderr, "Bad NSEC record for %s, bit map "
635 "mismatch\n", namebuf);
636 goto failure;
638 result = dns_rdataset_next(&rdataset);
639 if (result != ISC_R_NOMORE) {
640 dns_name_format(name, namebuf, sizeof(namebuf));
641 fprintf(stderr, "Multipe NSEC records for %s\n", namebuf);
642 goto failure;
645 dns_rdataset_disassociate(&rdataset);
646 return (ISC_R_SUCCESS);
647 failure:
648 if (dns_rdataset_isassociated(&rdataset))
649 dns_rdataset_disassociate(&rdataset);
650 return (ISC_R_FAILURE);
653 static void
654 check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset,
655 dns_name_t *name, dns_dbnode_t *node)
657 char namebuf[DNS_NAME_FORMATSIZE];
658 char typebuf[80];
659 dns_rdataset_t sigrdataset;
660 dns_rdatasetiter_t *rdsiter = NULL;
661 isc_result_t result;
663 dns_rdataset_init(&sigrdataset);
664 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
665 check_result(result, "dns_db_allrdatasets()");
666 for (result = dns_rdatasetiter_first(rdsiter);
667 result == ISC_R_SUCCESS;
668 result = dns_rdatasetiter_next(rdsiter)) {
669 dns_rdatasetiter_current(rdsiter, &sigrdataset);
670 if (sigrdataset.type == dns_rdatatype_rrsig &&
671 sigrdataset.covers == rdataset->type)
672 break;
673 dns_rdataset_disassociate(&sigrdataset);
675 if (result == ISC_R_SUCCESS) {
676 dns_name_format(name, namebuf, sizeof(namebuf));
677 type_format(rdataset->type, typebuf, sizeof(typebuf));
678 fprintf(stderr, "Warning: Found unexpected signatures for "
679 "%s/%s\n", namebuf, typebuf);
681 if (dns_rdataset_isassociated(&sigrdataset))
682 dns_rdataset_disassociate(&sigrdataset);
683 dns_rdatasetiter_destroy(&rdsiter);
686 static isc_boolean_t
687 chain_compare(void *arg1, void *arg2) {
688 struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
689 size_t len;
692 * Do each element in turn to get a stable sort.
694 if (e1->hash < e2->hash)
695 return (ISC_TRUE);
696 if (e1->hash > e2->hash)
697 return (ISC_FALSE);
698 if (e1->iterations < e2->iterations)
699 return (ISC_TRUE);
700 if (e1->iterations > e2->iterations)
701 return (ISC_FALSE);
702 if (e1->salt_length < e2->salt_length)
703 return (ISC_TRUE);
704 if (e1->salt_length > e2->salt_length)
705 return (ISC_FALSE);
706 if (e1->next_length < e2->next_length)
707 return (ISC_TRUE);
708 if (e1->next_length > e2->next_length)
709 return (ISC_FALSE);
710 len = e1->salt_length + 2 * e1->next_length;
711 if (memcmp(e1 + 1, e2 + 1, len) < 0)
712 return (ISC_TRUE);
713 return (ISC_FALSE);
716 static isc_boolean_t
717 chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) {
718 size_t len;
720 if (e1->hash != e2->hash)
721 return (ISC_FALSE);
722 if (e1->iterations != e2->iterations)
723 return (ISC_FALSE);
724 if (e1->salt_length != e2->salt_length)
725 return (ISC_FALSE);
726 if (e1->next_length != e2->next_length)
727 return (ISC_FALSE);
728 len = e1->salt_length + 2 * e1->next_length;
729 if (memcmp(e1 + 1, e2 + 1, len) != 0)
730 return (ISC_FALSE);
731 return (ISC_TRUE);
734 static isc_result_t
735 record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3,
736 isc_mem_t *mctx, isc_heap_t *chains)
738 struct nsec3_chain_fixed *element;
739 size_t len;
740 unsigned char *cp;
741 isc_result_t result;
743 len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
745 element = isc_mem_get(mctx, len);
746 if (element == NULL)
747 return (ISC_R_NOMEMORY);
748 memset(element, 0, len);
749 element->hash = nsec3->hash;
750 element->salt_length = nsec3->salt_length;
751 element->next_length = nsec3->next_length;
752 element->iterations = nsec3->iterations;
753 cp = (unsigned char *)(element + 1);
754 memmove(cp, nsec3->salt, nsec3->salt_length);
755 cp += nsec3->salt_length;
756 memmove(cp, rawhash, nsec3->next_length);
757 cp += nsec3->next_length;
758 memmove(cp, nsec3->next, nsec3->next_length);
759 result = isc_heap_insert(chains, element);
760 if (result != ISC_R_SUCCESS) {
761 fprintf(stderr, "isc_heap_insert failed: %s\n",
762 isc_result_totext(result));
763 isc_mem_put(mctx, element, len);
765 return (result);
768 static isc_result_t
769 match_nsec3(dns_name_t *name, isc_mem_t *mctx,
770 dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset,
771 unsigned char types[8192], unsigned int maxtype,
772 unsigned char *rawhash, size_t rhsize)
774 unsigned char cbm[8244];
775 char namebuf[DNS_NAME_FORMATSIZE];
776 dns_rdata_nsec3_t nsec3;
777 isc_result_t result;
778 unsigned int len;
781 * Find matching NSEC3 record.
783 for (result = dns_rdataset_first(rdataset);
784 result == ISC_R_SUCCESS;
785 result = dns_rdataset_next(rdataset)) {
786 dns_rdata_t rdata = DNS_RDATA_INIT;
787 dns_rdataset_current(rdataset, &rdata);
788 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
789 check_result(result, "dns_rdata_tostruct()");
790 if (nsec3.hash == nsec3param->hash &&
791 nsec3.next_length == rhsize &&
792 nsec3.iterations == nsec3param->iterations &&
793 nsec3.salt_length == nsec3param->salt_length &&
794 memcmp(nsec3.salt, nsec3param->salt,
795 nsec3param->salt_length) == 0)
796 break;
798 if (result != ISC_R_SUCCESS) {
799 dns_name_format(name, namebuf, sizeof(namebuf));
800 fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf);
801 return (result);
805 * Check the type list.
807 len = dns_nsec_compressbitmap(cbm, types, maxtype);
808 if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) {
809 dns_name_format(name, namebuf, sizeof(namebuf));
810 fprintf(stderr, "Bad NSEC3 record for %s, bit map "
811 "mismatch\n", namebuf);
812 return (ISC_R_FAILURE);
816 * Record chain.
818 result = record_nsec3(rawhash, &nsec3, mctx, expected_chains);
819 check_result(result, "record_nsec3()");
822 * Make sure there is only one NSEC3 record with this set of
823 * parameters.
825 for (result = dns_rdataset_next(rdataset);
826 result == ISC_R_SUCCESS;
827 result = dns_rdataset_next(rdataset)) {
828 dns_rdata_t rdata = DNS_RDATA_INIT;
829 dns_rdataset_current(rdataset, &rdata);
830 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
831 check_result(result, "dns_rdata_tostruct()");
832 if (nsec3.hash == nsec3param->hash &&
833 nsec3.iterations == nsec3param->iterations &&
834 nsec3.salt_length == nsec3param->salt_length &&
835 memcmp(nsec3.salt, nsec3param->salt,
836 nsec3.salt_length) == 0) {
837 dns_name_format(name, namebuf, sizeof(namebuf));
838 fprintf(stderr, "Multiple NSEC3 records with the "
839 "same parameter set for %s", namebuf);
840 result = DNS_R_DUPLICATE;
841 break;
844 if (result != ISC_R_NOMORE)
845 return (result);
847 result = ISC_R_SUCCESS;
848 return (result);
851 static isc_boolean_t
852 innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
853 dns_rdata_nsec3param_t nsec3param;
854 isc_result_t result;
856 for (result = dns_rdataset_first(nsec3paramset);
857 result == ISC_R_SUCCESS;
858 result = dns_rdataset_next(nsec3paramset)) {
859 dns_rdata_t rdata = DNS_RDATA_INIT;
861 dns_rdataset_current(nsec3paramset, &rdata);
862 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
863 check_result(result, "dns_rdata_tostruct()");
864 if (nsec3param.flags == 0 &&
865 nsec3param.hash == nsec3->hash &&
866 nsec3param.iterations == nsec3->iterations &&
867 nsec3param.salt_length == nsec3->salt_length &&
868 memcmp(nsec3param.salt, nsec3->salt,
869 nsec3->salt_length) == 0)
870 return (ISC_TRUE);
872 return (ISC_FALSE);
875 static isc_result_t
876 record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
877 dns_name_t *name, dns_dbnode_t *node,
878 dns_rdataset_t *nsec3paramset)
880 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
881 dns_rdata_nsec3_t nsec3;
882 dns_rdataset_t rdataset;
883 dns_label_t hashlabel;
884 isc_buffer_t b;
885 isc_result_t result;
887 if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
888 return (ISC_R_SUCCESS);
890 dns_rdataset_init(&rdataset);
891 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
892 0, 0, &rdataset, NULL);
893 if (result != ISC_R_SUCCESS)
894 return (ISC_R_SUCCESS);
896 dns_name_getlabel(name, 0, &hashlabel);
897 isc_region_consume(&hashlabel, 1);
898 isc_buffer_init(&b, owner, sizeof(owner));
899 result = isc_base32hex_decoderegion(&hashlabel, &b);
900 if (result != ISC_R_SUCCESS)
901 goto cleanup;
903 for (result = dns_rdataset_first(&rdataset);
904 result == ISC_R_SUCCESS;
905 result = dns_rdataset_next(&rdataset)) {
906 dns_rdata_t rdata = DNS_RDATA_INIT;
907 dns_rdataset_current(&rdataset, &rdata);
908 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
909 check_result(result, "dns_rdata_tostruct()");
910 if (nsec3.next_length != isc_buffer_usedlength(&b))
911 continue;
913 * We only care about NSEC3 records that match a NSEC3PARAM
914 * record.
916 if (!innsec3params(&nsec3, nsec3paramset))
917 continue;
920 * Record chain.
922 result = record_nsec3(owner, &nsec3, mctx, found_chains);
923 check_result(result, "record_nsec3()");
926 cleanup:
927 dns_rdataset_disassociate(&rdataset);
928 return (ISC_R_SUCCESS);
931 static isc_boolean_t
932 isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
933 dns_rdata_t *nsec3rdata)
935 dns_rdataset_t rdataset;
936 dns_rdata_t rdata = DNS_RDATA_INIT;
937 dns_rdata_nsec3_t nsec3;
938 dns_rdata_nsec3param_t nsec3param;
939 dns_fixedname_t fixed;
940 dns_name_t *hashname;
941 isc_result_t result;
942 dns_dbnode_t *node = NULL;
943 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
944 size_t rhsize = sizeof(rawhash);
945 isc_boolean_t ret;
947 result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL);
948 check_result(result, "dns_rdata_tostruct()");
950 dns_fixedname_init(&fixed);
951 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, origin, origin,
952 nsec3param.hash, nsec3param.iterations,
953 nsec3param.salt, nsec3param.salt_length);
954 check_result(result, "dns_nsec3_hashname()");
956 dns_rdataset_init(&rdataset);
957 hashname = dns_fixedname_name(&fixed);
958 result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node);
959 if (result == ISC_R_SUCCESS)
960 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
961 0, 0, &rdataset, NULL);
962 if (result != ISC_R_SUCCESS)
963 return (ISC_FALSE);
965 result = dns_rdataset_first(&rdataset);
966 check_result(result, "dns_rdataset_first()");
968 dns_rdataset_current(&rdataset, &rdata);
970 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
971 if (result != ISC_R_SUCCESS)
972 ret = ISC_FALSE;
973 else
974 ret = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
976 if (dns_rdataset_isassociated(&rdataset))
977 dns_rdataset_disassociate(&rdataset);
978 if (node != NULL)
979 dns_db_detachnode(db, &node);
981 return (ret);
984 static isc_result_t
985 verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
986 isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata,
987 isc_boolean_t delegation, isc_boolean_t empty,
988 unsigned char types[8192], unsigned int maxtype)
990 char namebuf[DNS_NAME_FORMATSIZE];
991 char hashbuf[DNS_NAME_FORMATSIZE];
992 dns_rdataset_t rdataset;
993 dns_rdata_nsec3param_t nsec3param;
994 dns_fixedname_t fixed;
995 dns_name_t *hashname;
996 isc_result_t result;
997 dns_dbnode_t *node = NULL;
998 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
999 size_t rhsize = sizeof(rawhash);
1000 isc_boolean_t optout;
1002 result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
1003 check_result(result, "dns_rdata_tostruct()");
1005 if (nsec3param.flags != 0)
1006 return (ISC_R_SUCCESS);
1008 if (!dns_nsec3_supportedhash(nsec3param.hash))
1009 return (ISC_R_SUCCESS);
1011 optout = isoptout(db, ver, origin, rdata);
1013 dns_fixedname_init(&fixed);
1014 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin,
1015 nsec3param.hash, nsec3param.iterations,
1016 nsec3param.salt, nsec3param.salt_length);
1017 check_result(result, "dns_nsec3_hashname()");
1020 * We don't use dns_db_find() here as it works with the choosen
1021 * nsec3 chain and we may also be called with uncommitted data
1022 * from dnssec-signzone so the secure status of the zone may not
1023 * be up to date.
1025 dns_rdataset_init(&rdataset);
1026 hashname = dns_fixedname_name(&fixed);
1027 result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node);
1028 if (result == ISC_R_SUCCESS)
1029 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
1030 0, 0, &rdataset, NULL);
1031 if (result != ISC_R_SUCCESS &&
1032 (!delegation || (empty && !optout) ||
1033 (!empty && dns_nsec_isset(types, dns_rdatatype_ds))))
1035 dns_name_format(name, namebuf, sizeof(namebuf));
1036 dns_name_format(hashname, hashbuf, sizeof(hashbuf));
1037 fprintf(stderr, "Missing NSEC3 record for %s (%s)\n",
1038 namebuf, hashbuf);
1039 } else if (result == ISC_R_NOTFOUND &&
1040 delegation && (!empty || optout))
1042 result = ISC_R_SUCCESS;
1043 } else if (result == ISC_R_SUCCESS) {
1044 result = match_nsec3(name, mctx, &nsec3param, &rdataset,
1045 types, maxtype, rawhash, rhsize);
1048 if (dns_rdataset_isassociated(&rdataset))
1049 dns_rdataset_disassociate(&rdataset);
1050 if (node != NULL)
1051 dns_db_detachnode(db, &node);
1053 return (result);
1056 static isc_result_t
1057 verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1058 isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset,
1059 isc_boolean_t delegation, isc_boolean_t empty,
1060 unsigned char types[8192], unsigned int maxtype)
1062 isc_result_t result;
1064 for (result = dns_rdataset_first(nsec3paramset);
1065 result == ISC_R_SUCCESS;
1066 result = dns_rdataset_next(nsec3paramset)) {
1067 dns_rdata_t rdata = DNS_RDATA_INIT;
1069 dns_rdataset_current(nsec3paramset, &rdata);
1070 result = verifynsec3(db, ver, origin, mctx, name, &rdata,
1071 delegation, empty, types, maxtype);
1072 if (result != ISC_R_SUCCESS)
1073 break;
1075 if (result == ISC_R_NOMORE)
1076 result = ISC_R_SUCCESS;
1077 return (result);
1080 static void
1081 verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1082 isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name,
1083 dns_dbnode_t *node, dns_rdataset_t *keyrdataset,
1084 unsigned char *act_algorithms, unsigned char *bad_algorithms)
1086 unsigned char set_algorithms[256];
1087 char namebuf[DNS_NAME_FORMATSIZE];
1088 char algbuf[80];
1089 char typebuf[80];
1090 dns_rdataset_t sigrdataset;
1091 dns_rdatasetiter_t *rdsiter = NULL;
1092 isc_result_t result;
1093 int i;
1095 dns_rdataset_init(&sigrdataset);
1096 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1097 check_result(result, "dns_db_allrdatasets()");
1098 for (result = dns_rdatasetiter_first(rdsiter);
1099 result == ISC_R_SUCCESS;
1100 result = dns_rdatasetiter_next(rdsiter)) {
1101 dns_rdatasetiter_current(rdsiter, &sigrdataset);
1102 if (sigrdataset.type == dns_rdatatype_rrsig &&
1103 sigrdataset.covers == rdataset->type)
1104 break;
1105 dns_rdataset_disassociate(&sigrdataset);
1107 if (result != ISC_R_SUCCESS) {
1108 dns_name_format(name, namebuf, sizeof(namebuf));
1109 type_format(rdataset->type, typebuf, sizeof(typebuf));
1110 fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf);
1111 for (i = 0; i < 256; i++)
1112 if (act_algorithms[i] != 0)
1113 bad_algorithms[i] = 1;
1114 dns_rdatasetiter_destroy(&rdsiter);
1115 return;
1118 memset(set_algorithms, 0, sizeof(set_algorithms));
1119 for (result = dns_rdataset_first(&sigrdataset);
1120 result == ISC_R_SUCCESS;
1121 result = dns_rdataset_next(&sigrdataset)) {
1122 dns_rdata_t rdata = DNS_RDATA_INIT;
1123 dns_rdata_rrsig_t sig;
1125 dns_rdataset_current(&sigrdataset, &rdata);
1126 result = dns_rdata_tostruct(&rdata, &sig, NULL);
1127 check_result(result, "dns_rdata_tostruct()");
1128 if (rdataset->ttl != sig.originalttl) {
1129 dns_name_format(name, namebuf, sizeof(namebuf));
1130 type_format(rdataset->type, typebuf, sizeof(typebuf));
1131 fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
1132 namebuf, typebuf, sig.keyid);
1133 continue;
1135 if ((set_algorithms[sig.algorithm] != 0) ||
1136 (act_algorithms[sig.algorithm] == 0))
1137 continue;
1138 if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx))
1139 set_algorithms[sig.algorithm] = 1;
1141 dns_rdatasetiter_destroy(&rdsiter);
1142 if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) {
1143 dns_name_format(name, namebuf, sizeof(namebuf));
1144 type_format(rdataset->type, typebuf, sizeof(typebuf));
1145 for (i = 0; i < 256; i++)
1146 if ((act_algorithms[i] != 0) &&
1147 (set_algorithms[i] == 0)) {
1148 dns_secalg_format(i, algbuf, sizeof(algbuf));
1149 fprintf(stderr, "No correct %s signature for "
1150 "%s %s\n", algbuf, namebuf, typebuf);
1151 bad_algorithms[i] = 1;
1154 dns_rdataset_disassociate(&sigrdataset);
1157 static isc_result_t
1158 verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1159 isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node,
1160 isc_boolean_t delegation, dns_rdataset_t *keyrdataset,
1161 unsigned char *act_algorithms, unsigned char *bad_algorithms,
1162 dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
1163 dns_name_t *nextname)
1165 unsigned char types[8192];
1166 unsigned int maxtype = 0;
1167 dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL;
1168 isc_result_t result, tresult;
1170 memset(types, 0, sizeof(types));
1171 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1172 check_result(result, "dns_db_allrdatasets()");
1173 result = dns_rdatasetiter_first(rdsiter);
1174 dns_rdataset_init(&rdataset);
1175 while (result == ISC_R_SUCCESS) {
1176 dns_rdatasetiter_current(rdsiter, &rdataset);
1178 * If we are not at a delegation then everything should be
1179 * signed. If we are at a delegation then only the DS set
1180 * is signed. The NS set is not signed at a delegation but
1181 * its existance is recorded in the bit map. Anything else
1182 * other than NSEC and DS is not signed at a delegation.
1184 if (rdataset.type != dns_rdatatype_rrsig &&
1185 rdataset.type != dns_rdatatype_dnskey &&
1186 (!delegation || rdataset.type == dns_rdatatype_ds ||
1187 rdataset.type == dns_rdatatype_nsec)) {
1188 verifyset(db, ver, origin, mctx, &rdataset,
1189 name, node, keyrdataset,
1190 act_algorithms, bad_algorithms);
1191 dns_nsec_setbit(types, rdataset.type, 1);
1192 if (rdataset.type > maxtype)
1193 maxtype = rdataset.type;
1194 } else if (rdataset.type != dns_rdatatype_rrsig &&
1195 rdataset.type != dns_rdatatype_dnskey) {
1196 if (rdataset.type == dns_rdatatype_ns)
1197 dns_nsec_setbit(types, rdataset.type, 1);
1198 check_no_rrsig(db, ver, &rdataset, name, node);
1199 } else
1200 dns_nsec_setbit(types, rdataset.type, 1);
1201 dns_rdataset_disassociate(&rdataset);
1202 result = dns_rdatasetiter_next(rdsiter);
1204 if (result != ISC_R_NOMORE)
1205 fatal("rdataset iteration failed: %s",
1206 isc_result_totext(result));
1207 dns_rdatasetiter_destroy(&rdsiter);
1209 result = ISC_R_SUCCESS;
1211 if (nsecset != NULL && dns_rdataset_isassociated(nsecset))
1212 result = verifynsec(db, ver, name, node, nextname);
1214 if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
1215 tresult = verifynsec3s(db, ver, origin, mctx, name,
1216 nsec3paramset, delegation, ISC_FALSE,
1217 types, maxtype);
1218 if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS)
1219 result = tresult;
1221 return (result);
1224 static isc_boolean_t
1225 is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
1226 dns_rdatasetiter_t *rdsiter = NULL;
1227 isc_result_t result;
1229 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1230 check_result(result, "dns_db_allrdatasets()");
1231 result = dns_rdatasetiter_first(rdsiter);
1232 dns_rdatasetiter_destroy(&rdsiter);
1233 if (result == ISC_R_NOMORE)
1234 return (ISC_TRUE);
1235 return (ISC_FALSE);
1238 static void
1239 check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db,
1240 dns_dbversion_t *ver)
1242 dns_rdataset_t rdataset;
1243 isc_result_t result;
1245 dns_rdataset_init(&rdataset);
1246 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
1247 0, 0, &rdataset, NULL);
1248 if (result != ISC_R_NOTFOUND) {
1249 char namebuf[DNS_NAME_FORMATSIZE];
1250 dns_name_format(name, namebuf, sizeof(namebuf));
1251 fatal("unexpected NSEC RRset at %s\n", namebuf);
1254 if (dns_rdataset_isassociated(&rdataset))
1255 dns_rdataset_disassociate(&rdataset);
1258 static isc_boolean_t
1259 newchain(const struct nsec3_chain_fixed *first,
1260 const struct nsec3_chain_fixed *e)
1262 if (first->hash != e->hash ||
1263 first->iterations != e->iterations ||
1264 first->salt_length != e->salt_length ||
1265 first->next_length != e->next_length ||
1266 memcmp(first + 1, e + 1, first->salt_length) != 0)
1267 return (ISC_TRUE);
1268 return (ISC_FALSE);
1271 static void
1272 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
1273 size_t len;
1275 len = sizeof(*e) + e->salt_length + 2 * e->next_length;
1276 isc_mem_put(mctx, e, len);
1279 static isc_boolean_t
1280 checknext(const struct nsec3_chain_fixed *first,
1281 const struct nsec3_chain_fixed *e)
1283 char buf[512];
1284 const unsigned char *d1 = (const unsigned char *)(first + 1);
1285 const unsigned char *d2 = (const unsigned char *)(e + 1);
1286 isc_buffer_t b;
1287 isc_region_t sr;
1289 d1 += first->salt_length + first->next_length;
1290 d2 += e->salt_length;
1292 if (memcmp(d1, d2, first->next_length) == 0)
1293 return (ISC_TRUE);
1295 DE_CONST(d1 - first->next_length, sr.base);
1296 sr.length = first->next_length;
1297 isc_buffer_init(&b, buf, sizeof(buf));
1298 isc_base32hex_totext(&sr, 1, "", &b);
1299 fprintf(stderr, "Break in NSEC3 chain at: %.*s\n",
1300 (int) isc_buffer_usedlength(&b), buf);
1302 DE_CONST(d1, sr.base);
1303 sr.length = first->next_length;
1304 isc_buffer_init(&b, buf, sizeof(buf));
1305 isc_base32hex_totext(&sr, 1, "", &b);
1306 fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b),
1307 buf);
1309 DE_CONST(d2, sr.base);
1310 sr.length = first->next_length;
1311 isc_buffer_init(&b, buf, sizeof(buf));
1312 isc_base32hex_totext(&sr, 1, "", &b);
1313 fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf);
1315 return (ISC_FALSE);
1318 #define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n"
1320 static isc_result_t
1321 verify_nsec3_chains(isc_mem_t *mctx) {
1322 isc_result_t result = ISC_R_SUCCESS;
1323 struct nsec3_chain_fixed *e, *f = NULL;
1324 struct nsec3_chain_fixed *first = NULL, *prev = NULL;
1326 while ((e = isc_heap_element(expected_chains, 1)) != NULL) {
1327 isc_heap_delete(expected_chains, 1);
1328 if (f == NULL)
1329 f = isc_heap_element(found_chains, 1);
1330 if (f != NULL) {
1331 isc_heap_delete(found_chains, 1);
1334 * Check that they match.
1336 if (chain_equal(e, f)) {
1337 free_element(mctx, f);
1338 f = NULL;
1339 } else {
1340 if (result == ISC_R_SUCCESS)
1341 fprintf(stderr, EXPECTEDANDFOUND);
1342 result = ISC_R_FAILURE;
1344 * Attempt to resync found_chain.
1346 while (f != NULL && !chain_compare(e, f)) {
1347 free_element(mctx, f);
1348 f = isc_heap_element(found_chains, 1);
1349 if (f != NULL)
1350 isc_heap_delete(found_chains, 1);
1351 if (f != NULL && chain_equal(e, f)) {
1352 free_element(mctx, f);
1353 f = NULL;
1354 break;
1358 } else if (result == ISC_R_SUCCESS) {
1359 fprintf(stderr, EXPECTEDANDFOUND);
1360 result = ISC_R_FAILURE;
1362 if (first == NULL || newchain(first, e)) {
1363 if (prev != NULL) {
1364 if (!checknext(prev, first))
1365 result = ISC_R_FAILURE;
1366 if (prev != first)
1367 free_element(mctx, prev);
1369 if (first != NULL)
1370 free_element(mctx, first);
1371 prev = first = e;
1372 continue;
1374 if (!checknext(prev, e))
1375 result = ISC_R_FAILURE;
1376 if (prev != first)
1377 free_element(mctx, prev);
1378 prev = e;
1380 if (prev != NULL) {
1381 if (!checknext(prev, first))
1382 result = ISC_R_FAILURE;
1383 if (prev != first)
1384 free_element(mctx, prev);
1386 if (first != NULL)
1387 free_element(mctx, first);
1388 do {
1389 if (f != NULL) {
1390 if (result == ISC_R_SUCCESS) {
1391 fprintf(stderr, EXPECTEDANDFOUND);
1392 result = ISC_R_FAILURE;
1394 free_element(mctx, f);
1396 f = isc_heap_element(found_chains, 1);
1397 if (f != NULL)
1398 isc_heap_delete(found_chains, 1);
1399 } while (f != NULL);
1401 return (result);
1404 static isc_result_t
1405 verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1406 isc_mem_t *mctx, dns_name_t *name, dns_name_t *prevname,
1407 isc_boolean_t isdelegation, dns_rdataset_t *nsec3paramset)
1409 dns_namereln_t reln;
1410 int order;
1411 unsigned int labels, nlabels, i;
1412 dns_name_t suffix;
1413 isc_result_t result = ISC_R_SUCCESS, tresult;
1415 reln = dns_name_fullcompare(prevname, name, &order, &labels);
1416 if (order >= 0)
1417 return (result);
1419 nlabels = dns_name_countlabels(name);
1421 if (reln == dns_namereln_commonancestor ||
1422 reln == dns_namereln_contains) {
1423 dns_name_init(&suffix, NULL);
1424 for (i = labels + 1; i < nlabels; i++) {
1425 dns_name_getlabelsequence(name, nlabels - i, i,
1426 &suffix);
1427 if (nsec3paramset != NULL &&
1428 dns_rdataset_isassociated(nsec3paramset)) {
1429 tresult = verifynsec3s(db, ver, origin, mctx,
1430 &suffix, nsec3paramset,
1431 isdelegation, ISC_TRUE,
1432 NULL, 0);
1433 if (result == ISC_R_SUCCESS &&
1434 tresult != ISC_R_SUCCESS)
1435 result = tresult;
1439 return (result);
1443 * Verify that certain things are sane:
1445 * The apex has a DNSKEY record with at least one KSK, and at least
1446 * one ZSK if the -x flag was not used.
1448 * The DNSKEY record was signed with at least one of the KSKs in this
1449 * set.
1451 * The rest of the zone was signed with at least one of the ZSKs
1452 * present in the DNSKEY RRSET.
1454 void
1455 verifyzone(dns_db_t *db, dns_dbversion_t *ver,
1456 dns_name_t *origin, isc_mem_t *mctx,
1457 isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly)
1459 char algbuf[80];
1460 dns_dbiterator_t *dbiter = NULL;
1461 dns_dbnode_t *node = NULL, *nextnode = NULL;
1462 dns_fixedname_t fname, fnextname, fprevname, fzonecut;
1463 dns_name_t *name, *nextname, *prevname, *zonecut;
1464 dns_rdata_dnskey_t dnskey;
1465 dns_rdata_t rdata = DNS_RDATA_INIT;
1466 dns_rdataset_t keyset, soaset;
1467 dns_rdataset_t keysigs, soasigs;
1468 dns_rdataset_t nsecset, nsecsigs;
1469 dns_rdataset_t nsec3paramset, nsec3paramsigs;
1470 int i;
1471 isc_boolean_t done = ISC_FALSE;
1472 isc_boolean_t first = ISC_TRUE;
1473 isc_boolean_t goodksk = ISC_FALSE;
1474 isc_boolean_t goodzsk = ISC_FALSE;
1475 isc_result_t result, vresult = ISC_R_UNSET;
1476 unsigned char revoked_ksk[256];
1477 unsigned char revoked_zsk[256];
1478 unsigned char standby_ksk[256];
1479 unsigned char standby_zsk[256];
1480 unsigned char ksk_algorithms[256];
1481 unsigned char zsk_algorithms[256];
1482 unsigned char bad_algorithms[256];
1483 unsigned char act_algorithms[256];
1485 result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1486 &expected_chains);
1487 check_result(result, "isc_heap_create()");
1488 result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1489 &found_chains);
1490 check_result(result, "isc_heap_create()");
1492 result = dns_db_findnode(db, origin, ISC_FALSE, &node);
1493 if (result != ISC_R_SUCCESS)
1494 fatal("failed to find the zone's origin: %s",
1495 isc_result_totext(result));
1497 dns_rdataset_init(&keyset);
1498 dns_rdataset_init(&keysigs);
1499 dns_rdataset_init(&soaset);
1500 dns_rdataset_init(&soasigs);
1501 dns_rdataset_init(&nsecset);
1502 dns_rdataset_init(&nsecsigs);
1503 dns_rdataset_init(&nsec3paramset);
1504 dns_rdataset_init(&nsec3paramsigs);
1505 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
1506 0, 0, &keyset, &keysigs);
1507 if (result != ISC_R_SUCCESS)
1508 fatal("Zone contains no DNSSEC keys\n");
1510 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
1511 0, 0, &soaset, &soasigs);
1512 if (result != ISC_R_SUCCESS)
1513 fatal("Zone contains no SOA record\n");
1515 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
1516 0, 0, &nsecset, &nsecsigs);
1517 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1518 fatal("NSEC lookup failed\n");
1520 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
1521 0, 0, &nsec3paramset, &nsec3paramsigs);
1522 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1523 fatal("NSEC3PARAM lookup failed\n");
1525 if (!dns_rdataset_isassociated(&keysigs))
1526 fatal("DNSKEY is not signed (keys offline or inactive?)\n");
1528 if (!dns_rdataset_isassociated(&soasigs))
1529 fatal("SOA is not signed (keys offline or inactive?)\n");
1531 if (dns_rdataset_isassociated(&nsecset) &&
1532 !dns_rdataset_isassociated(&nsecsigs))
1533 fatal("NSEC is not signed (keys offline or inactive?)\n");
1535 if (dns_rdataset_isassociated(&nsec3paramset) &&
1536 !dns_rdataset_isassociated(&nsec3paramsigs))
1537 fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n");
1539 if (!dns_rdataset_isassociated(&nsecset) &&
1540 !dns_rdataset_isassociated(&nsec3paramset))
1541 fatal("No valid NSEC/NSEC3 chain for testing\n");
1543 dns_db_detachnode(db, &node);
1545 memset(revoked_ksk, 0, sizeof(revoked_ksk));
1546 memset(revoked_zsk, 0, sizeof(revoked_zsk));
1547 memset(standby_ksk, 0, sizeof(standby_ksk));
1548 memset(standby_zsk, 0, sizeof(standby_zsk));
1549 memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1550 memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1551 memset(bad_algorithms, 0, sizeof(bad_algorithms));
1552 memset(act_algorithms, 0, sizeof(act_algorithms));
1555 * Check that the DNSKEY RR has at least one self signing KSK
1556 * and one ZSK per algorithm in it (or, if -x was used, one
1557 * self-signing KSK).
1559 for (result = dns_rdataset_first(&keyset);
1560 result == ISC_R_SUCCESS;
1561 result = dns_rdataset_next(&keyset)) {
1562 dns_rdataset_current(&keyset, &rdata);
1563 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1564 check_result(result, "dns_rdata_tostruct");
1566 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1568 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1569 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1570 !dns_dnssec_selfsigns(&rdata, origin, &keyset,
1571 &keysigs, ISC_FALSE,
1572 mctx)) {
1573 char namebuf[DNS_NAME_FORMATSIZE];
1574 char buffer[1024];
1575 isc_buffer_t buf;
1577 dns_name_format(origin, namebuf,
1578 sizeof(namebuf));
1579 isc_buffer_init(&buf, buffer, sizeof(buffer));
1580 result = dns_rdata_totext(&rdata, NULL, &buf);
1581 check_result(result, "dns_rdata_totext");
1582 fatal("revoked KSK is not self signed:\n"
1583 "%s DNSKEY %.*s", namebuf,
1584 (int)isc_buffer_usedlength(&buf), buffer);
1586 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1587 revoked_ksk[dnskey.algorithm] != 255)
1588 revoked_ksk[dnskey.algorithm]++;
1589 else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1590 revoked_zsk[dnskey.algorithm] != 255)
1591 revoked_zsk[dnskey.algorithm]++;
1592 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1593 if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
1594 &keysigs, ISC_FALSE, mctx)) {
1595 if (ksk_algorithms[dnskey.algorithm] != 255)
1596 ksk_algorithms[dnskey.algorithm]++;
1597 goodksk = ISC_TRUE;
1598 } else {
1599 if (standby_ksk[dnskey.algorithm] != 255)
1600 standby_ksk[dnskey.algorithm]++;
1602 } else if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
1603 &keysigs, ISC_FALSE, mctx)) {
1604 if (zsk_algorithms[dnskey.algorithm] != 255)
1605 zsk_algorithms[dnskey.algorithm]++;
1606 goodzsk = ISC_TRUE;
1607 } else if (dns_dnssec_signs(&rdata, origin, &soaset,
1608 &soasigs, ISC_FALSE, mctx)) {
1609 if (zsk_algorithms[dnskey.algorithm] != 255)
1610 zsk_algorithms[dnskey.algorithm]++;
1611 } else {
1612 if (standby_zsk[dnskey.algorithm] != 255)
1613 standby_zsk[dnskey.algorithm]++;
1615 dns_rdata_freestruct(&dnskey);
1616 dns_rdata_reset(&rdata);
1618 dns_rdataset_disassociate(&keysigs);
1619 dns_rdataset_disassociate(&soaset);
1620 dns_rdataset_disassociate(&soasigs);
1621 if (dns_rdataset_isassociated(&nsecsigs))
1622 dns_rdataset_disassociate(&nsecsigs);
1623 if (dns_rdataset_isassociated(&nsec3paramsigs))
1624 dns_rdataset_disassociate(&nsec3paramsigs);
1626 if (ignore_kskflag ) {
1627 if (!goodksk && !goodzsk)
1628 fatal("No self-signed DNSKEY found.");
1629 } else if (!goodksk)
1630 fatal("No self-signed KSK DNSKEY found. Supply an active\n"
1631 "key with the KSK flag set, or use '-P'.");
1633 fprintf(stderr, "Verifying the zone using the following algorithms:");
1634 for (i = 0; i < 256; i++) {
1635 if (ignore_kskflag)
1636 act_algorithms[i] = (ksk_algorithms[i] != 0 ||
1637 zsk_algorithms[i] != 0) ? 1 : 0;
1638 else
1639 act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0;
1640 if (act_algorithms[i] != 0) {
1641 dns_secalg_format(i, algbuf, sizeof(algbuf));
1642 fprintf(stderr, " %s", algbuf);
1645 fprintf(stderr, ".\n");
1647 if (!ignore_kskflag && !keyset_kskonly) {
1648 for (i = 0; i < 256; i++) {
1650 * The counts should both be zero or both be non-zero.
1651 * Mark the algorithm as bad if this is not met.
1653 if ((ksk_algorithms[i] != 0) ==
1654 (zsk_algorithms[i] != 0))
1655 continue;
1656 dns_secalg_format(i, algbuf, sizeof(algbuf));
1657 fprintf(stderr, "Missing %s for algorithm %s\n",
1658 (ksk_algorithms[i] != 0)
1659 ? "ZSK"
1660 : "self-signed KSK",
1661 algbuf);
1662 bad_algorithms[i] = 1;
1667 * Check that all the other records were signed by keys that are
1668 * present in the DNSKEY RRSET.
1671 dns_fixedname_init(&fname);
1672 name = dns_fixedname_name(&fname);
1673 dns_fixedname_init(&fnextname);
1674 nextname = dns_fixedname_name(&fnextname);
1675 dns_fixedname_init(&fprevname);
1676 prevname = NULL;
1677 dns_fixedname_init(&fzonecut);
1678 zonecut = NULL;
1680 result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter);
1681 check_result(result, "dns_db_createiterator()");
1683 result = dns_dbiterator_first(dbiter);
1684 check_result(result, "dns_dbiterator_first()");
1686 while (!done) {
1687 isc_boolean_t isdelegation = ISC_FALSE;
1689 result = dns_dbiterator_current(dbiter, &node, name);
1690 check_dns_dbiterator_current(result);
1691 if (!dns_name_issubdomain(name, origin)) {
1692 check_no_nsec(name, node, db, ver);
1693 dns_db_detachnode(db, &node);
1694 result = dns_dbiterator_next(dbiter);
1695 if (result == ISC_R_NOMORE)
1696 done = ISC_TRUE;
1697 else
1698 check_result(result, "dns_dbiterator_next()");
1699 continue;
1701 if (is_delegation(db, ver, origin, name, node, NULL)) {
1702 zonecut = dns_fixedname_name(&fzonecut);
1703 dns_name_copy(name, zonecut, NULL);
1704 isdelegation = ISC_TRUE;
1706 nextnode = NULL;
1707 result = dns_dbiterator_next(dbiter);
1708 while (result == ISC_R_SUCCESS) {
1709 result = dns_dbiterator_current(dbiter, &nextnode,
1710 nextname);
1711 check_dns_dbiterator_current(result);
1712 if (!dns_name_issubdomain(nextname, origin) ||
1713 (zonecut != NULL &&
1714 dns_name_issubdomain(nextname, zonecut)))
1716 check_no_nsec(nextname, nextnode, db, ver);
1717 dns_db_detachnode(db, &nextnode);
1718 result = dns_dbiterator_next(dbiter);
1719 continue;
1721 if (is_empty(db, ver, nextnode)) {
1722 dns_db_detachnode(db, &nextnode);
1723 result = dns_dbiterator_next(dbiter);
1724 continue;
1726 dns_db_detachnode(db, &nextnode);
1727 break;
1729 if (result == ISC_R_NOMORE) {
1730 done = ISC_TRUE;
1731 nextname = origin;
1732 } else if (result != ISC_R_SUCCESS)
1733 fatal("iterating through the database failed: %s",
1734 isc_result_totext(result));
1735 result = verifynode(db, ver, origin, mctx, name, node,
1736 isdelegation, &keyset, act_algorithms,
1737 bad_algorithms, &nsecset, &nsec3paramset,
1738 nextname);
1739 if (vresult == ISC_R_UNSET)
1740 vresult = ISC_R_SUCCESS;
1741 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1742 vresult = result;
1743 if (prevname != NULL) {
1744 result = verifyemptynodes(db, ver, origin, mctx, name,
1745 prevname, isdelegation,
1746 &nsec3paramset);
1747 } else
1748 prevname = dns_fixedname_name(&fprevname);
1749 dns_name_copy(name, prevname, NULL);
1750 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1751 vresult = result;
1752 dns_db_detachnode(db, &node);
1755 dns_dbiterator_destroy(&dbiter);
1757 result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter);
1758 check_result(result, "dns_db_createiterator()");
1760 for (result = dns_dbiterator_first(dbiter);
1761 result == ISC_R_SUCCESS;
1762 result = dns_dbiterator_next(dbiter) ) {
1763 result = dns_dbiterator_current(dbiter, &node, name);
1764 check_dns_dbiterator_current(result);
1765 result = verifynode(db, ver, origin, mctx, name, node,
1766 ISC_FALSE, &keyset, act_algorithms,
1767 bad_algorithms, NULL, NULL, NULL);
1768 check_result(result, "verifynode");
1769 record_found(db, ver, mctx, name, node, &nsec3paramset);
1770 dns_db_detachnode(db, &node);
1772 dns_dbiterator_destroy(&dbiter);
1774 dns_rdataset_disassociate(&keyset);
1775 if (dns_rdataset_isassociated(&nsecset))
1776 dns_rdataset_disassociate(&nsecset);
1777 if (dns_rdataset_isassociated(&nsec3paramset))
1778 dns_rdataset_disassociate(&nsec3paramset);
1780 result = verify_nsec3_chains(mctx);
1781 if (vresult == ISC_R_UNSET)
1782 vresult = ISC_R_SUCCESS;
1783 if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS)
1784 vresult = result;
1785 isc_heap_destroy(&expected_chains);
1786 isc_heap_destroy(&found_chains);
1789 * If we made it this far, we have what we consider a properly signed
1790 * zone. Set the good flag.
1792 for (i = 0; i < 256; i++) {
1793 if (bad_algorithms[i] != 0) {
1794 if (first)
1795 fprintf(stderr, "The zone is not fully signed "
1796 "for the following algorithms:");
1797 dns_secalg_format(i, algbuf, sizeof(algbuf));
1798 fprintf(stderr, " %s", algbuf);
1799 first = ISC_FALSE;
1802 if (!first) {
1803 fprintf(stderr, ".\n");
1804 fatal("DNSSEC completeness test failed.");
1807 if (vresult != ISC_R_SUCCESS)
1808 fatal("DNSSEC completeness test failed (%s).",
1809 dns_result_totext(vresult));
1811 if (goodksk || ignore_kskflag) {
1813 * Print the success summary.
1815 fprintf(stderr, "Zone fully signed:\n");
1816 for (i = 0; i < 256; i++) {
1817 if ((ksk_algorithms[i] != 0) ||
1818 (standby_ksk[i] != 0) ||
1819 (revoked_zsk[i] != 0) ||
1820 (zsk_algorithms[i] != 0) ||
1821 (standby_zsk[i] != 0) ||
1822 (revoked_zsk[i] != 0)) {
1823 dns_secalg_format(i, algbuf, sizeof(algbuf));
1824 fprintf(stderr, "Algorithm: %s: KSKs: "
1825 "%u active, %u stand-by, %u revoked\n",
1826 algbuf, ksk_algorithms[i],
1827 standby_ksk[i], revoked_ksk[i]);
1828 fprintf(stderr, "%*sZSKs: "
1829 "%u active, %u %s, %u revoked\n",
1830 (int) strlen(algbuf) + 13, "",
1831 zsk_algorithms[i],
1832 standby_zsk[i],
1833 keyset_kskonly ? "present" : "stand-by",
1834 revoked_zsk[i]);