2 * Copyright (C) 2004, 2005, 2007, 2009-2014 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: dnssectool.c,v 1.63 2011/10/21 03:55:33 marka Exp $ */
23 * DNSSEC Support Routines.
30 #include <isc/base32.h>
31 #include <isc/buffer.h>
33 #include <isc/entropy.h>
37 #include <isc/string.h>
40 #include <isc/print.h>
43 #include <dns/dbiterator.h>
44 #include <dns/dnssec.h>
45 #include <dns/fixedname.h>
46 #include <dns/keyvalues.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>
60 #include "dnssectool.h"
62 static isc_heap_t *expected_chains, *found_chains;
64 struct nsec3_chain_fixed {
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]; */
75 extern const char *program;
77 typedef struct entropysource entropysource_t;
79 struct entropysource {
80 isc_entropysource_t *source;
82 ISC_LINK(entropysource_t) link;
85 static ISC_LIST(entropysource_t) sources;
86 static fatalcallback_t *fatalcallback = NULL;
89 fatal(const char *format, ...) {
92 fprintf(stderr, "%s: fatal: ", program);
93 va_start(args, format);
94 vfprintf(stderr, format, args);
96 fprintf(stderr, "\n");
97 if (fatalcallback != NULL)
103 setfatalcallback(fatalcallback_t *callback) {
104 fatalcallback = callback;
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));
114 vbprintf(int level, const char *fmt, ...) {
119 fprintf(stderr, "%s: ", program);
120 vfprintf(stderr, fmt, ap);
125 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
130 isc_buffer_init(&b, cp, size - 1);
131 result = dns_rdatatype_totext(type, &b);
132 check_result(result, "dns_rdatatype_totext()");
133 isc_buffer_usedregion(&b, &r);
134 r.base[r.length] = 0;
138 sig_format(dns_rdata_rrsig_t *sig, char *cp, unsigned int size) {
139 char namestr[DNS_NAME_FORMATSIZE];
140 char algstr[DNS_NAME_FORMATSIZE];
142 dns_name_format(&sig->signer, namestr, sizeof(namestr));
143 dns_secalg_format(sig->algorithm, algstr, sizeof(algstr));
144 snprintf(cp, size, "%s/%s/%d", namestr, algstr, sig->keyid);
148 setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) {
150 isc_logdestination_t destination;
151 isc_logconfig_t *logconfig = NULL;
152 isc_log_t *log = NULL;
160 * We want to see warnings about things like out-of-zone
161 * data in the master file even when not verbose.
163 level = ISC_LOG_WARNING;
166 level = ISC_LOG_INFO;
169 level = ISC_LOG_DEBUG(verbose - 2 + 1);
173 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
174 isc_log_setcontext(log);
176 dns_log_setcontext(log);
178 RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
181 * Set up a channel similar to default_stderr except:
182 * - the logging level is passed in
183 * - the program name and logging level are printed
184 * - no time stamp is printed
186 destination.file.stream = stderr;
187 destination.file.name = NULL;
188 destination.file.versions = ISC_LOG_ROLLNEVER;
189 destination.file.maximum_size = 0;
190 result = isc_log_createchannel(logconfig, "stderr",
194 ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
195 check_result(result, "isc_log_createchannel()");
197 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
198 NULL, NULL) == ISC_R_SUCCESS);
204 cleanup_logging(isc_log_t **logp) {
207 REQUIRE(logp != NULL);
212 isc_log_destroy(&log);
213 isc_log_setcontext(NULL);
214 dns_log_setcontext(NULL);
219 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
221 isc_entropysource_t *source = NULL;
222 entropysource_t *elt;
223 int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
225 REQUIRE(ectx != NULL);
228 result = isc_entropy_create(mctx, ectx);
229 if (result != ISC_R_SUCCESS)
230 fatal("could not create entropy object");
231 ISC_LIST_INIT(sources);
234 if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
235 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
239 result = isc_entropy_usebestsource(*ectx, &source, randomfile,
242 if (result != ISC_R_SUCCESS)
243 fatal("could not initialize entropy source: %s",
244 isc_result_totext(result));
246 if (source != NULL) {
247 elt = isc_mem_get(mctx, sizeof(*elt));
249 fatal("out of memory");
250 elt->source = source;
252 ISC_LINK_INIT(elt, link);
253 ISC_LIST_APPEND(sources, elt, link);
258 cleanup_entropy(isc_entropy_t **ectx) {
259 entropysource_t *source;
260 while (!ISC_LIST_EMPTY(sources)) {
261 source = ISC_LIST_HEAD(sources);
262 ISC_LIST_UNLINK(sources, source, link);
263 isc_entropy_destroysource(&source->source);
264 isc_mem_put(source->mctx, source, sizeof(*source));
266 isc_entropy_detach(ectx);
270 time_units(isc_stdtime_t offset, char *suffix, const char *str) {
273 return (offset * (365 * 24 * 3600));
277 return (offset * (30 * 24 * 3600));
279 return (offset * 60);
281 fatal("'%s' ambiguous: use 'mi' for minutes "
282 "or 'mo' for months", str);
284 fatal("time value %s is invalid", str);
289 return (offset * (7 * 24 * 3600));
291 return (offset * (24 * 3600));
293 return (offset * 3600);
294 case 'S': case 's': case '\0':
297 fatal("time value %s is invalid", str);
300 return(0); /* silence compiler warning */
304 strtottl(const char *str) {
305 const char *orig = str;
309 ttl = strtol(str, &endp, 0);
310 if (ttl == 0 && endp == str)
311 fatal("TTL must be numeric");
312 ttl = time_units(ttl, endp, orig);
317 strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
318 isc_int64_t val, offset;
320 const char *orig = str;
324 if ((str[0] == '0' || str[0] == '-') && str[1] == '\0')
325 return ((isc_stdtime_t) 0);
328 * We accept times in the following formats:
330 * YYYYMMDD([+-]offset)
331 * YYYYMMDDhhmmss([+-]offset)
334 n = strspn(str, "0123456789");
335 if ((n == 8 || n == 14) &&
336 (str[n] == '\0' || str[n] == '-' || str[n] == '+'))
340 strlcpy(timestr, str, sizeof(timestr));
343 strlcat(timestr, "000000", sizeof(timestr));
344 result = dns_time64_fromtext(timestr, &val);
345 if (result != ISC_R_SUCCESS)
346 fatal("time value %s is invalid: %s", orig,
347 isc_result_totext(result));
350 } else if (strncmp(str, "now", 3) == 0) {
356 return ((isc_stdtime_t) base);
357 else if (str[0] == '+') {
358 offset = strtol(str + 1, &endp, 0);
359 offset = time_units((isc_stdtime_t) offset, endp, orig);
361 } else if (str[0] == '-') {
362 offset = strtol(str + 1, &endp, 0);
363 offset = time_units((isc_stdtime_t) offset, endp, orig);
366 fatal("time value %s is invalid", orig);
368 return ((isc_stdtime_t) val);
372 strtoclass(const char *str) {
374 dns_rdataclass_t rdclass;
378 return dns_rdataclass_in;
379 DE_CONST(str, r.base);
380 r.length = strlen(str);
381 ret = dns_rdataclass_fromtext(&rdclass, &r);
382 if (ret != ISC_R_SUCCESS)
383 fatal("unknown class %s", str);
388 try_dir(const char *dirname) {
393 result = isc_dir_open(&d, dirname);
394 if (result == ISC_R_SUCCESS) {
401 * Check private key version compatibility.
404 check_keyversion(dst_key_t *key, char *keystr) {
406 dst_key_getprivateformat(key, &major, &minor);
407 INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */
409 if (major < DST_MAJOR_VERSION || minor < DST_MINOR_VERSION)
410 fatal("Key %s has incompatible format version %d.%d, "
411 "use -f to force upgrade to new version.",
412 keystr, major, minor);
413 if (minor > DST_MINOR_VERSION)
414 fatal("Key %s has incompatible format version %d.%d, "
415 "use -f to force downgrade to current version.",
416 keystr, major, minor);
420 set_keyversion(dst_key_t *key) {
422 dst_key_getprivateformat(key, &major, &minor);
423 INSIST(major <= DST_MAJOR_VERSION);
425 if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION)
426 dst_key_setprivateformat(key, DST_MAJOR_VERSION,
430 * If the key is from a version older than 1.3, set
431 * set the creation date
433 if (major < 1 || (major == 1 && minor <= 2)) {
435 isc_stdtime_get(&now);
436 dst_key_settime(key, DST_TIME_CREATED, now);
441 key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
442 isc_mem_t *mctx, isc_boolean_t *exact)
445 isc_boolean_t conflict = ISC_FALSE;
446 dns_dnsseckeylist_t matchkeys;
447 dns_dnsseckey_t *key = NULL;
448 isc_uint16_t id, oldid;
449 isc_uint32_t rid, roldid;
455 id = dst_key_id(dstkey);
456 rid = dst_key_rid(dstkey);
457 alg = dst_key_alg(dstkey);
459 ISC_LIST_INIT(matchkeys);
460 result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys);
461 if (result == ISC_R_NOTFOUND)
464 while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
465 key = ISC_LIST_HEAD(matchkeys);
466 if (dst_key_alg(key->key) != alg)
469 oldid = dst_key_id(key->key);
470 roldid = dst_key_rid(key->key);
472 if (oldid == rid || roldid == id || id == oldid) {
476 fprintf(stderr, "Key ID %d could "
483 fprintf(stderr, "Key ID %d exists\n",
489 ISC_LIST_UNLINK(matchkeys, key, link);
490 dns_dnsseckey_destroy(mctx, &key);
493 /* Finish freeing the list */
494 while (!ISC_LIST_EMPTY(matchkeys)) {
495 key = ISC_LIST_HEAD(matchkeys);
496 ISC_LIST_UNLINK(matchkeys, key, link);
497 dns_dnsseckey_destroy(mctx, &key);
504 is_delegation(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
505 dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp)
507 dns_rdataset_t nsset;
510 if (dns_name_equal(name, origin))
513 dns_rdataset_init(&nsset);
514 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns,
516 if (dns_rdataset_isassociated(&nsset)) {
519 dns_rdataset_disassociate(&nsset);
522 return (ISC_TF(result == ISC_R_SUCCESS));
526 goodsig(dns_name_t *origin, dns_rdata_t *sigrdata, dns_name_t *name,
527 dns_rdataset_t *keyrdataset, dns_rdataset_t *rdataset, isc_mem_t *mctx)
529 dns_rdata_dnskey_t key;
530 dns_rdata_rrsig_t sig;
531 dst_key_t *dstkey = NULL;
534 result = dns_rdata_tostruct(sigrdata, &sig, NULL);
535 check_result(result, "dns_rdata_tostruct()");
537 for (result = dns_rdataset_first(keyrdataset);
538 result == ISC_R_SUCCESS;
539 result = dns_rdataset_next(keyrdataset)) {
540 dns_rdata_t rdata = DNS_RDATA_INIT;
541 dns_rdataset_current(keyrdataset, &rdata);
542 result = dns_rdata_tostruct(&rdata, &key, NULL);
543 check_result(result, "dns_rdata_tostruct()");
544 result = dns_dnssec_keyfromrdata(origin, &rdata, mctx,
546 if (result != ISC_R_SUCCESS)
548 if (sig.algorithm != key.algorithm ||
549 sig.keyid != dst_key_id(dstkey) ||
550 !dns_name_equal(&sig.signer, origin)) {
551 dst_key_free(&dstkey);
554 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
556 dst_key_free(&dstkey);
557 if (result == ISC_R_SUCCESS)
564 verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
565 dns_dbnode_t *node, dns_name_t *nextname)
567 unsigned char buffer[DNS_NSEC_BUFFERSIZE];
568 char namebuf[DNS_NAME_FORMATSIZE];
569 char nextbuf[DNS_NAME_FORMATSIZE];
570 char found[DNS_NAME_FORMATSIZE];
571 dns_rdataset_t rdataset;
572 dns_rdata_t rdata = DNS_RDATA_INIT;
573 dns_rdata_t tmprdata = DNS_RDATA_INIT;
574 dns_rdata_nsec_t nsec;
577 dns_rdataset_init(&rdataset);
578 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
579 0, 0, &rdataset, NULL);
580 if (result != ISC_R_SUCCESS) {
581 dns_name_format(name, namebuf, sizeof(namebuf));
582 fprintf(stderr, "Missing NSEC record for %s\n", namebuf);
586 result = dns_rdataset_first(&rdataset);
587 check_result(result, "dns_rdataset_first()");
589 dns_rdataset_current(&rdataset, &rdata);
590 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
591 check_result(result, "dns_rdata_tostruct()");
592 /* Check bit next name is consistent */
593 if (!dns_name_equal(&nsec.next, nextname)) {
594 dns_name_format(name, namebuf, sizeof(namebuf));
595 dns_name_format(nextname, nextbuf, sizeof(nextbuf));
596 dns_name_format(&nsec.next, found, sizeof(found));
597 fprintf(stderr, "Bad NSEC record for %s, next name "
598 "mismatch (expected:%s, found:%s)\n", namebuf,
602 /* Check bit map is consistent */
603 result = dns_nsec_buildrdata(db, ver, node, nextname, buffer,
605 check_result(result, "dns_nsec_buildrdata()");
606 if (dns_rdata_compare(&rdata, &tmprdata) != 0) {
607 dns_name_format(name, namebuf, sizeof(namebuf));
608 fprintf(stderr, "Bad NSEC record for %s, bit map "
609 "mismatch\n", namebuf);
612 result = dns_rdataset_next(&rdataset);
613 if (result != ISC_R_NOMORE) {
614 dns_name_format(name, namebuf, sizeof(namebuf));
615 fprintf(stderr, "Multipe NSEC records for %s\n", namebuf);
619 dns_rdataset_disassociate(&rdataset);
620 return (ISC_R_SUCCESS);
622 if (dns_rdataset_isassociated(&rdataset))
623 dns_rdataset_disassociate(&rdataset);
624 return (ISC_R_FAILURE);
628 check_no_rrsig(dns_db_t *db, dns_dbversion_t *ver, dns_rdataset_t *rdataset,
629 dns_name_t *name, dns_dbnode_t *node)
631 char namebuf[DNS_NAME_FORMATSIZE];
633 dns_rdataset_t sigrdataset;
634 dns_rdatasetiter_t *rdsiter = NULL;
637 dns_rdataset_init(&sigrdataset);
638 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
639 check_result(result, "dns_db_allrdatasets()");
640 for (result = dns_rdatasetiter_first(rdsiter);
641 result == ISC_R_SUCCESS;
642 result = dns_rdatasetiter_next(rdsiter)) {
643 dns_rdatasetiter_current(rdsiter, &sigrdataset);
644 if (sigrdataset.type == dns_rdatatype_rrsig &&
645 sigrdataset.covers == rdataset->type)
647 dns_rdataset_disassociate(&sigrdataset);
649 if (result == ISC_R_SUCCESS) {
650 dns_name_format(name, namebuf, sizeof(namebuf));
651 type_format(rdataset->type, typebuf, sizeof(typebuf));
652 fprintf(stderr, "Warning: Found unexpected signatures for "
653 "%s/%s\n", namebuf, typebuf);
655 if (dns_rdataset_isassociated(&sigrdataset))
656 dns_rdataset_disassociate(&sigrdataset);
657 dns_rdatasetiter_destroy(&rdsiter);
661 chain_compare(void *arg1, void *arg2) {
662 struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
666 * Do each element in turn to get a stable sort.
668 if (e1->hash < e2->hash)
670 if (e1->hash > e2->hash)
672 if (e1->iterations < e2->iterations)
674 if (e1->iterations > e2->iterations)
676 if (e1->salt_length < e2->salt_length)
678 if (e1->salt_length > e2->salt_length)
680 if (e1->next_length < e2->next_length)
682 if (e1->next_length > e2->next_length)
684 len = e1->salt_length + 2 * e1->next_length;
685 if (memcmp(e1 + 1, e2 + 1, len) < 0)
691 chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) {
694 if (e1->hash != e2->hash)
696 if (e1->iterations != e2->iterations)
698 if (e1->salt_length != e2->salt_length)
700 if (e1->next_length != e2->next_length)
702 len = e1->salt_length + 2 * e1->next_length;
703 if (memcmp(e1 + 1, e2 + 1, len) != 0)
709 record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3,
710 isc_mem_t *mctx, isc_heap_t *chains)
712 struct nsec3_chain_fixed *element;
717 len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
719 element = isc_mem_get(mctx, len);
721 return (ISC_R_NOMEMORY);
722 memset(element, 0, len);
723 element->hash = nsec3->hash;
724 element->salt_length = nsec3->salt_length;
725 element->next_length = nsec3->next_length;
726 element->iterations = nsec3->iterations;
727 cp = (unsigned char *)(element + 1);
728 memmove(cp, nsec3->salt, nsec3->salt_length);
729 cp += nsec3->salt_length;
730 memmove(cp, rawhash, nsec3->next_length);
731 cp += nsec3->next_length;
732 memmove(cp, nsec3->next, nsec3->next_length);
733 result = isc_heap_insert(chains, element);
734 if (result != ISC_R_SUCCESS) {
735 fprintf(stderr, "isc_heap_insert failed: %s\n",
736 isc_result_totext(result));
737 isc_mem_put(mctx, element, len);
743 match_nsec3(dns_name_t *name, isc_mem_t *mctx,
744 dns_rdata_nsec3param_t *nsec3param, dns_rdataset_t *rdataset,
745 unsigned char types[8192], unsigned int maxtype,
746 unsigned char *rawhash, size_t rhsize)
748 unsigned char cbm[8244];
749 char namebuf[DNS_NAME_FORMATSIZE];
750 dns_rdata_nsec3_t nsec3;
755 * Find matching NSEC3 record.
757 for (result = dns_rdataset_first(rdataset);
758 result == ISC_R_SUCCESS;
759 result = dns_rdataset_next(rdataset)) {
760 dns_rdata_t rdata = DNS_RDATA_INIT;
761 dns_rdataset_current(rdataset, &rdata);
762 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
763 check_result(result, "dns_rdata_tostruct()");
764 if (nsec3.hash == nsec3param->hash &&
765 nsec3.next_length == rhsize &&
766 nsec3.iterations == nsec3param->iterations &&
767 nsec3.salt_length == nsec3param->salt_length &&
768 memcmp(nsec3.salt, nsec3param->salt,
769 nsec3param->salt_length) == 0)
772 if (result != ISC_R_SUCCESS) {
773 dns_name_format(name, namebuf, sizeof(namebuf));
774 fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf);
779 * Check the type list.
781 len = dns_nsec_compressbitmap(cbm, types, maxtype);
782 if (nsec3.len != len || memcmp(cbm, nsec3.typebits, len) != 0) {
783 dns_name_format(name, namebuf, sizeof(namebuf));
784 fprintf(stderr, "Bad NSEC3 record for %s, bit map "
785 "mismatch\n", namebuf);
786 return (ISC_R_FAILURE);
792 result = record_nsec3(rawhash, &nsec3, mctx, expected_chains);
793 check_result(result, "record_nsec3()");
796 * Make sure there is only one NSEC3 record with this set of
799 for (result = dns_rdataset_next(rdataset);
800 result == ISC_R_SUCCESS;
801 result = dns_rdataset_next(rdataset)) {
802 dns_rdata_t rdata = DNS_RDATA_INIT;
803 dns_rdataset_current(rdataset, &rdata);
804 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
805 check_result(result, "dns_rdata_tostruct()");
806 if (nsec3.hash == nsec3param->hash &&
807 nsec3.iterations == nsec3param->iterations &&
808 nsec3.salt_length == nsec3param->salt_length &&
809 memcmp(nsec3.salt, nsec3param->salt,
810 nsec3.salt_length) == 0) {
811 dns_name_format(name, namebuf, sizeof(namebuf));
812 fprintf(stderr, "Multiple NSEC3 records with the "
813 "same parameter set for %s", namebuf);
814 result = DNS_R_DUPLICATE;
818 if (result != ISC_R_NOMORE)
821 result = ISC_R_SUCCESS;
826 innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
827 dns_rdata_nsec3param_t nsec3param;
830 for (result = dns_rdataset_first(nsec3paramset);
831 result == ISC_R_SUCCESS;
832 result = dns_rdataset_next(nsec3paramset)) {
833 dns_rdata_t rdata = DNS_RDATA_INIT;
835 dns_rdataset_current(nsec3paramset, &rdata);
836 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
837 check_result(result, "dns_rdata_tostruct()");
838 if (nsec3param.flags == 0 &&
839 nsec3param.hash == nsec3->hash &&
840 nsec3param.iterations == nsec3->iterations &&
841 nsec3param.salt_length == nsec3->salt_length &&
842 memcmp(nsec3param.salt, nsec3->salt,
843 nsec3->salt_length) == 0)
850 record_found(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
851 dns_name_t *name, dns_dbnode_t *node,
852 dns_rdataset_t *nsec3paramset)
854 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
855 dns_rdata_nsec3_t nsec3;
856 dns_rdataset_t rdataset;
857 dns_label_t hashlabel;
861 if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
862 return (ISC_R_SUCCESS);
864 dns_rdataset_init(&rdataset);
865 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
866 0, 0, &rdataset, NULL);
867 if (result != ISC_R_SUCCESS)
868 return (ISC_R_SUCCESS);
870 dns_name_getlabel(name, 0, &hashlabel);
871 isc_region_consume(&hashlabel, 1);
872 isc_buffer_init(&b, owner, sizeof(owner));
873 result = isc_base32hex_decoderegion(&hashlabel, &b);
874 if (result != ISC_R_SUCCESS)
877 for (result = dns_rdataset_first(&rdataset);
878 result == ISC_R_SUCCESS;
879 result = dns_rdataset_next(&rdataset)) {
880 dns_rdata_t rdata = DNS_RDATA_INIT;
881 dns_rdataset_current(&rdataset, &rdata);
882 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
883 check_result(result, "dns_rdata_tostruct()");
884 if (nsec3.next_length != isc_buffer_usedlength(&b))
887 * We only care about NSEC3 records that match a NSEC3PARAM
890 if (!innsec3params(&nsec3, nsec3paramset))
896 result = record_nsec3(owner, &nsec3, mctx, found_chains);
897 check_result(result, "record_nsec3()");
901 dns_rdataset_disassociate(&rdataset);
902 return (ISC_R_SUCCESS);
906 isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
907 dns_rdata_t *nsec3rdata)
909 dns_rdataset_t rdataset;
910 dns_rdata_t rdata = DNS_RDATA_INIT;
911 dns_rdata_nsec3_t nsec3;
912 dns_rdata_nsec3param_t nsec3param;
913 dns_fixedname_t fixed;
914 dns_name_t *hashname;
916 dns_dbnode_t *node = NULL;
917 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
918 size_t rhsize = sizeof(rawhash);
921 result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL);
922 check_result(result, "dns_rdata_tostruct()");
924 dns_fixedname_init(&fixed);
925 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, origin, origin,
926 nsec3param.hash, nsec3param.iterations,
927 nsec3param.salt, nsec3param.salt_length);
928 check_result(result, "dns_nsec3_hashname()");
930 dns_rdataset_init(&rdataset);
931 hashname = dns_fixedname_name(&fixed);
932 result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node);
933 if (result == ISC_R_SUCCESS)
934 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
935 0, 0, &rdataset, NULL);
936 if (result != ISC_R_SUCCESS)
939 result = dns_rdataset_first(&rdataset);
940 check_result(result, "dns_rdataset_first()");
942 dns_rdataset_current(&rdataset, &rdata);
944 result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
945 if (result != ISC_R_SUCCESS)
948 ret = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
950 if (dns_rdataset_isassociated(&rdataset))
951 dns_rdataset_disassociate(&rdataset);
953 dns_db_detachnode(db, &node);
959 verifynsec3(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
960 isc_mem_t *mctx, dns_name_t *name, dns_rdata_t *rdata,
961 isc_boolean_t delegation, isc_boolean_t empty,
962 unsigned char types[8192], unsigned int maxtype)
964 char namebuf[DNS_NAME_FORMATSIZE];
965 char hashbuf[DNS_NAME_FORMATSIZE];
966 dns_rdataset_t rdataset;
967 dns_rdata_nsec3param_t nsec3param;
968 dns_fixedname_t fixed;
969 dns_name_t *hashname;
971 dns_dbnode_t *node = NULL;
972 unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
973 size_t rhsize = sizeof(rawhash);
974 isc_boolean_t optout;
976 result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
977 check_result(result, "dns_rdata_tostruct()");
979 if (nsec3param.flags != 0)
980 return (ISC_R_SUCCESS);
982 if (!dns_nsec3_supportedhash(nsec3param.hash))
983 return (ISC_R_SUCCESS);
985 optout = isoptout(db, ver, origin, rdata);
987 dns_fixedname_init(&fixed);
988 result = dns_nsec3_hashname(&fixed, rawhash, &rhsize, name, origin,
989 nsec3param.hash, nsec3param.iterations,
990 nsec3param.salt, nsec3param.salt_length);
991 check_result(result, "dns_nsec3_hashname()");
994 * We don't use dns_db_find() here as it works with the choosen
995 * nsec3 chain and we may also be called with uncommitted data
996 * from dnssec-signzone so the secure status of the zone may not
999 dns_rdataset_init(&rdataset);
1000 hashname = dns_fixedname_name(&fixed);
1001 result = dns_db_findnsec3node(db, hashname, ISC_FALSE, &node);
1002 if (result == ISC_R_SUCCESS)
1003 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
1004 0, 0, &rdataset, NULL);
1005 if (result != ISC_R_SUCCESS &&
1006 (!delegation || (empty && !optout) ||
1007 (!empty && dns_nsec_isset(types, dns_rdatatype_ds))))
1009 dns_name_format(name, namebuf, sizeof(namebuf));
1010 dns_name_format(hashname, hashbuf, sizeof(hashbuf));
1011 fprintf(stderr, "Missing NSEC3 record for %s (%s)\n",
1013 } else if (result == ISC_R_NOTFOUND &&
1014 delegation && (!empty || optout))
1016 result = ISC_R_SUCCESS;
1017 } else if (result == ISC_R_SUCCESS) {
1018 result = match_nsec3(name, mctx, &nsec3param, &rdataset,
1019 types, maxtype, rawhash, rhsize);
1022 if (dns_rdataset_isassociated(&rdataset))
1023 dns_rdataset_disassociate(&rdataset);
1025 dns_db_detachnode(db, &node);
1031 verifynsec3s(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1032 isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *nsec3paramset,
1033 isc_boolean_t delegation, isc_boolean_t empty,
1034 unsigned char types[8192], unsigned int maxtype)
1036 isc_result_t result;
1038 for (result = dns_rdataset_first(nsec3paramset);
1039 result == ISC_R_SUCCESS;
1040 result = dns_rdataset_next(nsec3paramset)) {
1041 dns_rdata_t rdata = DNS_RDATA_INIT;
1043 dns_rdataset_current(nsec3paramset, &rdata);
1044 result = verifynsec3(db, ver, origin, mctx, name, &rdata,
1045 delegation, empty, types, maxtype);
1046 if (result != ISC_R_SUCCESS)
1049 if (result == ISC_R_NOMORE)
1050 result = ISC_R_SUCCESS;
1055 verifyset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1056 isc_mem_t *mctx, dns_rdataset_t *rdataset, dns_name_t *name,
1057 dns_dbnode_t *node, dns_rdataset_t *keyrdataset,
1058 unsigned char *act_algorithms, unsigned char *bad_algorithms)
1060 unsigned char set_algorithms[256];
1061 char namebuf[DNS_NAME_FORMATSIZE];
1064 dns_rdataset_t sigrdataset;
1065 dns_rdatasetiter_t *rdsiter = NULL;
1066 isc_result_t result;
1069 dns_rdataset_init(&sigrdataset);
1070 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1071 check_result(result, "dns_db_allrdatasets()");
1072 for (result = dns_rdatasetiter_first(rdsiter);
1073 result == ISC_R_SUCCESS;
1074 result = dns_rdatasetiter_next(rdsiter)) {
1075 dns_rdatasetiter_current(rdsiter, &sigrdataset);
1076 if (sigrdataset.type == dns_rdatatype_rrsig &&
1077 sigrdataset.covers == rdataset->type)
1079 dns_rdataset_disassociate(&sigrdataset);
1081 if (result != ISC_R_SUCCESS) {
1082 dns_name_format(name, namebuf, sizeof(namebuf));
1083 type_format(rdataset->type, typebuf, sizeof(typebuf));
1084 fprintf(stderr, "No signatures for %s/%s\n", namebuf, typebuf);
1085 for (i = 0; i < 256; i++)
1086 if (act_algorithms[i] != 0)
1087 bad_algorithms[i] = 1;
1088 dns_rdatasetiter_destroy(&rdsiter);
1092 memset(set_algorithms, 0, sizeof(set_algorithms));
1093 for (result = dns_rdataset_first(&sigrdataset);
1094 result == ISC_R_SUCCESS;
1095 result = dns_rdataset_next(&sigrdataset)) {
1096 dns_rdata_t rdata = DNS_RDATA_INIT;
1097 dns_rdata_rrsig_t sig;
1099 dns_rdataset_current(&sigrdataset, &rdata);
1100 result = dns_rdata_tostruct(&rdata, &sig, NULL);
1101 check_result(result, "dns_rdata_tostruct()");
1102 if (rdataset->ttl != sig.originalttl) {
1103 dns_name_format(name, namebuf, sizeof(namebuf));
1104 type_format(rdataset->type, typebuf, sizeof(typebuf));
1105 fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
1106 namebuf, typebuf, sig.keyid);
1109 if ((set_algorithms[sig.algorithm] != 0) ||
1110 (act_algorithms[sig.algorithm] == 0))
1112 if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx))
1113 set_algorithms[sig.algorithm] = 1;
1115 dns_rdatasetiter_destroy(&rdsiter);
1116 if (memcmp(set_algorithms, act_algorithms, sizeof(set_algorithms))) {
1117 dns_name_format(name, namebuf, sizeof(namebuf));
1118 type_format(rdataset->type, typebuf, sizeof(typebuf));
1119 for (i = 0; i < 256; i++)
1120 if ((act_algorithms[i] != 0) &&
1121 (set_algorithms[i] == 0)) {
1122 dns_secalg_format(i, algbuf, sizeof(algbuf));
1123 fprintf(stderr, "No correct %s signature for "
1124 "%s %s\n", algbuf, namebuf, typebuf);
1125 bad_algorithms[i] = 1;
1128 dns_rdataset_disassociate(&sigrdataset);
1132 verifynode(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1133 isc_mem_t *mctx, dns_name_t *name, dns_dbnode_t *node,
1134 isc_boolean_t delegation, dns_rdataset_t *keyrdataset,
1135 unsigned char *act_algorithms, unsigned char *bad_algorithms,
1136 dns_rdataset_t *nsecset, dns_rdataset_t *nsec3paramset,
1137 dns_name_t *nextname)
1139 unsigned char types[8192];
1140 unsigned int maxtype = 0;
1141 dns_rdataset_t rdataset; dns_rdatasetiter_t *rdsiter = NULL;
1142 isc_result_t result, tresult;
1144 memset(types, 0, sizeof(types));
1145 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1146 check_result(result, "dns_db_allrdatasets()");
1147 result = dns_rdatasetiter_first(rdsiter);
1148 dns_rdataset_init(&rdataset);
1149 while (result == ISC_R_SUCCESS) {
1150 dns_rdatasetiter_current(rdsiter, &rdataset);
1152 * If we are not at a delegation then everything should be
1153 * signed. If we are at a delegation then only the DS set
1154 * is signed. The NS set is not signed at a delegation but
1155 * its existance is recorded in the bit map. Anything else
1156 * other than NSEC and DS is not signed at a delegation.
1158 if (rdataset.type != dns_rdatatype_rrsig &&
1159 rdataset.type != dns_rdatatype_dnskey &&
1160 (!delegation || rdataset.type == dns_rdatatype_ds ||
1161 rdataset.type == dns_rdatatype_nsec)) {
1162 verifyset(db, ver, origin, mctx, &rdataset,
1163 name, node, keyrdataset,
1164 act_algorithms, bad_algorithms);
1165 dns_nsec_setbit(types, rdataset.type, 1);
1166 if (rdataset.type > maxtype)
1167 maxtype = rdataset.type;
1168 } else if (rdataset.type != dns_rdatatype_rrsig &&
1169 rdataset.type != dns_rdatatype_dnskey) {
1170 if (rdataset.type == dns_rdatatype_ns)
1171 dns_nsec_setbit(types, rdataset.type, 1);
1172 check_no_rrsig(db, ver, &rdataset, name, node);
1174 dns_nsec_setbit(types, rdataset.type, 1);
1175 dns_rdataset_disassociate(&rdataset);
1176 result = dns_rdatasetiter_next(rdsiter);
1178 if (result != ISC_R_NOMORE)
1179 fatal("rdataset iteration failed: %s",
1180 isc_result_totext(result));
1181 dns_rdatasetiter_destroy(&rdsiter);
1183 result = ISC_R_SUCCESS;
1185 if (nsecset != NULL && dns_rdataset_isassociated(nsecset))
1186 result = verifynsec(db, ver, name, node, nextname);
1188 if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
1189 tresult = verifynsec3s(db, ver, origin, mctx, name,
1190 nsec3paramset, delegation, ISC_FALSE,
1192 if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS)
1198 static isc_boolean_t
1199 is_empty(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node) {
1200 dns_rdatasetiter_t *rdsiter = NULL;
1201 isc_result_t result;
1203 result = dns_db_allrdatasets(db, node, ver, 0, &rdsiter);
1204 check_result(result, "dns_db_allrdatasets()");
1205 result = dns_rdatasetiter_first(rdsiter);
1206 dns_rdatasetiter_destroy(&rdsiter);
1207 if (result == ISC_R_NOMORE)
1213 check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db,
1214 dns_dbversion_t *ver)
1216 dns_rdataset_t rdataset;
1217 isc_result_t result;
1219 dns_rdataset_init(&rdataset);
1220 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
1221 0, 0, &rdataset, NULL);
1222 if (result != ISC_R_NOTFOUND) {
1223 char namebuf[DNS_NAME_FORMATSIZE];
1224 dns_name_format(name, namebuf, sizeof(namebuf));
1225 fatal("unexpected NSEC RRset at %s\n", namebuf);
1228 if (dns_rdataset_isassociated(&rdataset))
1229 dns_rdataset_disassociate(&rdataset);
1232 static isc_boolean_t
1233 newchain(const struct nsec3_chain_fixed *first,
1234 const struct nsec3_chain_fixed *e)
1236 if (first->hash != e->hash ||
1237 first->iterations != e->iterations ||
1238 first->salt_length != e->salt_length ||
1239 first->next_length != e->next_length ||
1240 memcmp(first + 1, e + 1, first->salt_length) != 0)
1246 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
1249 len = sizeof(*e) + e->salt_length + 2 * e->next_length;
1250 isc_mem_put(mctx, e, len);
1253 static isc_boolean_t
1254 checknext(const struct nsec3_chain_fixed *first,
1255 const struct nsec3_chain_fixed *e)
1258 const unsigned char *d1 = (const unsigned char *)(first + 1);
1259 const unsigned char *d2 = (const unsigned char *)(e + 1);
1263 d1 += first->salt_length + first->next_length;
1264 d2 += e->salt_length;
1266 if (memcmp(d1, d2, first->next_length) == 0)
1269 DE_CONST(d1 - first->next_length, sr.base);
1270 sr.length = first->next_length;
1271 isc_buffer_init(&b, buf, sizeof(buf));
1272 isc_base32hex_totext(&sr, 1, "", &b);
1273 fprintf(stderr, "Break in NSEC3 chain at: %.*s\n",
1274 (int) isc_buffer_usedlength(&b), buf);
1276 DE_CONST(d1, sr.base);
1277 sr.length = first->next_length;
1278 isc_buffer_init(&b, buf, sizeof(buf));
1279 isc_base32hex_totext(&sr, 1, "", &b);
1280 fprintf(stderr, "Expected: %.*s\n", (int) isc_buffer_usedlength(&b),
1283 DE_CONST(d2, sr.base);
1284 sr.length = first->next_length;
1285 isc_buffer_init(&b, buf, sizeof(buf));
1286 isc_base32hex_totext(&sr, 1, "", &b);
1287 fprintf(stderr, "Found: %.*s\n", (int) isc_buffer_usedlength(&b), buf);
1292 #define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n"
1295 verify_nsec3_chains(isc_mem_t *mctx) {
1296 isc_result_t result = ISC_R_SUCCESS;
1297 struct nsec3_chain_fixed *e, *f = NULL;
1298 struct nsec3_chain_fixed *first = NULL, *prev = NULL;
1300 while ((e = isc_heap_element(expected_chains, 1)) != NULL) {
1301 isc_heap_delete(expected_chains, 1);
1303 f = isc_heap_element(found_chains, 1);
1305 isc_heap_delete(found_chains, 1);
1308 * Check that they match.
1310 if (chain_equal(e, f)) {
1311 free_element(mctx, f);
1314 if (result == ISC_R_SUCCESS)
1315 fprintf(stderr, EXPECTEDANDFOUND);
1316 result = ISC_R_FAILURE;
1318 * Attempt to resync found_chain.
1320 while (f != NULL && !chain_compare(e, f)) {
1321 free_element(mctx, f);
1322 f = isc_heap_element(found_chains, 1);
1324 isc_heap_delete(found_chains, 1);
1325 if (f != NULL && chain_equal(e, f)) {
1326 free_element(mctx, f);
1332 } else if (result == ISC_R_SUCCESS) {
1333 fprintf(stderr, EXPECTEDANDFOUND);
1334 result = ISC_R_FAILURE;
1336 if (first == NULL || newchain(first, e)) {
1338 if (!checknext(prev, first))
1339 result = ISC_R_FAILURE;
1341 free_element(mctx, prev);
1344 free_element(mctx, first);
1348 if (!checknext(prev, e))
1349 result = ISC_R_FAILURE;
1351 free_element(mctx, prev);
1355 if (!checknext(prev, first))
1356 result = ISC_R_FAILURE;
1358 free_element(mctx, prev);
1361 free_element(mctx, first);
1364 if (result == ISC_R_SUCCESS) {
1365 fprintf(stderr, EXPECTEDANDFOUND);
1366 result = ISC_R_FAILURE;
1368 free_element(mctx, f);
1370 f = isc_heap_element(found_chains, 1);
1372 isc_heap_delete(found_chains, 1);
1373 } while (f != NULL);
1379 verifyemptynodes(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
1380 isc_mem_t *mctx, dns_name_t *name, dns_name_t *prevname,
1381 isc_boolean_t isdelegation, dns_rdataset_t *nsec3paramset)
1383 dns_namereln_t reln;
1385 unsigned int labels, nlabels, i;
1387 isc_result_t result = ISC_R_SUCCESS, tresult;
1389 reln = dns_name_fullcompare(prevname, name, &order, &labels);
1393 nlabels = dns_name_countlabels(name);
1395 if (reln == dns_namereln_commonancestor ||
1396 reln == dns_namereln_contains) {
1397 dns_name_init(&suffix, NULL);
1398 for (i = labels + 1; i < nlabels; i++) {
1399 dns_name_getlabelsequence(name, nlabels - i, i,
1401 if (nsec3paramset != NULL &&
1402 dns_rdataset_isassociated(nsec3paramset)) {
1403 tresult = verifynsec3s(db, ver, origin, mctx,
1404 &suffix, nsec3paramset,
1405 isdelegation, ISC_TRUE,
1407 if (result == ISC_R_SUCCESS &&
1408 tresult != ISC_R_SUCCESS)
1417 * Verify that certain things are sane:
1419 * The apex has a DNSKEY record with at least one KSK, and at least
1420 * one ZSK if the -x flag was not used.
1422 * The DNSKEY record was signed with at least one of the KSKs in this
1425 * The rest of the zone was signed with at least one of the ZSKs
1426 * present in the DNSKEY RRSET.
1429 verifyzone(dns_db_t *db, dns_dbversion_t *ver,
1430 dns_name_t *origin, isc_mem_t *mctx,
1431 isc_boolean_t ignore_kskflag, isc_boolean_t keyset_kskonly)
1434 dns_dbiterator_t *dbiter = NULL;
1435 dns_dbnode_t *node = NULL, *nextnode = NULL;
1436 dns_fixedname_t fname, fnextname, fprevname, fzonecut;
1437 dns_name_t *name, *nextname, *prevname, *zonecut;
1438 dns_rdata_dnskey_t dnskey;
1439 dns_rdata_t rdata = DNS_RDATA_INIT;
1440 dns_rdataset_t keyset, soaset;
1441 dns_rdataset_t keysigs, soasigs;
1442 dns_rdataset_t nsecset, nsecsigs;
1443 dns_rdataset_t nsec3paramset, nsec3paramsigs;
1445 isc_boolean_t done = ISC_FALSE;
1446 isc_boolean_t first = ISC_TRUE;
1447 isc_boolean_t goodksk = ISC_FALSE;
1448 isc_boolean_t goodzsk = ISC_FALSE;
1449 isc_result_t result, vresult = ISC_R_UNSET;
1450 unsigned char revoked_ksk[256];
1451 unsigned char revoked_zsk[256];
1452 unsigned char standby_ksk[256];
1453 unsigned char standby_zsk[256];
1454 unsigned char ksk_algorithms[256];
1455 unsigned char zsk_algorithms[256];
1456 unsigned char bad_algorithms[256];
1457 unsigned char act_algorithms[256];
1459 result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1461 check_result(result, "isc_heap_create()");
1462 result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1464 check_result(result, "isc_heap_create()");
1466 result = dns_db_findnode(db, origin, ISC_FALSE, &node);
1467 if (result != ISC_R_SUCCESS)
1468 fatal("failed to find the zone's origin: %s",
1469 isc_result_totext(result));
1471 dns_rdataset_init(&keyset);
1472 dns_rdataset_init(&keysigs);
1473 dns_rdataset_init(&soaset);
1474 dns_rdataset_init(&soasigs);
1475 dns_rdataset_init(&nsecset);
1476 dns_rdataset_init(&nsecsigs);
1477 dns_rdataset_init(&nsec3paramset);
1478 dns_rdataset_init(&nsec3paramsigs);
1479 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
1480 0, 0, &keyset, &keysigs);
1481 if (result != ISC_R_SUCCESS)
1482 fatal("Zone contains no DNSSEC keys\n");
1484 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
1485 0, 0, &soaset, &soasigs);
1486 if (result != ISC_R_SUCCESS)
1487 fatal("Zone contains no SOA record\n");
1489 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
1490 0, 0, &nsecset, &nsecsigs);
1491 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1492 fatal("NSEC lookup failed\n");
1494 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
1495 0, 0, &nsec3paramset, &nsec3paramsigs);
1496 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
1497 fatal("NSEC3PARAM lookup failed\n");
1499 if (!dns_rdataset_isassociated(&keysigs))
1500 fatal("DNSKEY is not signed (keys offline or inactive?)\n");
1502 if (!dns_rdataset_isassociated(&soasigs))
1503 fatal("SOA is not signed (keys offline or inactive?)\n");
1505 if (dns_rdataset_isassociated(&nsecset) &&
1506 !dns_rdataset_isassociated(&nsecsigs))
1507 fatal("NSEC is not signed (keys offline or inactive?)\n");
1509 if (dns_rdataset_isassociated(&nsec3paramset) &&
1510 !dns_rdataset_isassociated(&nsec3paramsigs))
1511 fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n");
1513 if (!dns_rdataset_isassociated(&nsecset) &&
1514 !dns_rdataset_isassociated(&nsec3paramset))
1515 fatal("No valid NSEC/NSEC3 chain for testing\n");
1517 dns_db_detachnode(db, &node);
1519 memset(revoked_ksk, 0, sizeof(revoked_ksk));
1520 memset(revoked_zsk, 0, sizeof(revoked_zsk));
1521 memset(standby_ksk, 0, sizeof(standby_ksk));
1522 memset(standby_zsk, 0, sizeof(standby_zsk));
1523 memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1524 memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1525 memset(bad_algorithms, 0, sizeof(bad_algorithms));
1526 memset(act_algorithms, 0, sizeof(act_algorithms));
1529 * Check that the DNSKEY RR has at least one self signing KSK
1530 * and one ZSK per algorithm in it (or, if -x was used, one
1531 * self-signing KSK).
1533 for (result = dns_rdataset_first(&keyset);
1534 result == ISC_R_SUCCESS;
1535 result = dns_rdataset_next(&keyset)) {
1536 dns_rdataset_current(&keyset, &rdata);
1537 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1538 check_result(result, "dns_rdata_tostruct");
1540 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1542 else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1543 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1544 !dns_dnssec_selfsigns(&rdata, origin, &keyset,
1545 &keysigs, ISC_FALSE,
1547 char namebuf[DNS_NAME_FORMATSIZE];
1551 dns_name_format(origin, namebuf,
1553 isc_buffer_init(&buf, buffer, sizeof(buffer));
1554 result = dns_rdata_totext(&rdata, NULL, &buf);
1555 check_result(result, "dns_rdata_totext");
1556 fatal("revoked KSK is not self signed:\n"
1557 "%s DNSKEY %.*s", namebuf,
1558 (int)isc_buffer_usedlength(&buf), buffer);
1560 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1561 revoked_ksk[dnskey.algorithm] != 255)
1562 revoked_ksk[dnskey.algorithm]++;
1563 else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1564 revoked_zsk[dnskey.algorithm] != 255)
1565 revoked_zsk[dnskey.algorithm]++;
1566 } else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1567 if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
1568 &keysigs, ISC_FALSE, mctx)) {
1569 if (ksk_algorithms[dnskey.algorithm] != 255)
1570 ksk_algorithms[dnskey.algorithm]++;
1573 if (standby_ksk[dnskey.algorithm] != 255)
1574 standby_ksk[dnskey.algorithm]++;
1576 } else if (dns_dnssec_selfsigns(&rdata, origin, &keyset,
1577 &keysigs, ISC_FALSE, mctx)) {
1578 if (zsk_algorithms[dnskey.algorithm] != 255)
1579 zsk_algorithms[dnskey.algorithm]++;
1581 } else if (dns_dnssec_signs(&rdata, origin, &soaset,
1582 &soasigs, ISC_FALSE, mctx)) {
1583 if (zsk_algorithms[dnskey.algorithm] != 255)
1584 zsk_algorithms[dnskey.algorithm]++;
1586 if (standby_zsk[dnskey.algorithm] != 255)
1587 standby_zsk[dnskey.algorithm]++;
1589 dns_rdata_freestruct(&dnskey);
1590 dns_rdata_reset(&rdata);
1592 dns_rdataset_disassociate(&keysigs);
1593 dns_rdataset_disassociate(&soaset);
1594 dns_rdataset_disassociate(&soasigs);
1595 if (dns_rdataset_isassociated(&nsecsigs))
1596 dns_rdataset_disassociate(&nsecsigs);
1597 if (dns_rdataset_isassociated(&nsec3paramsigs))
1598 dns_rdataset_disassociate(&nsec3paramsigs);
1600 if (ignore_kskflag ) {
1601 if (!goodksk && !goodzsk)
1602 fatal("No self-signed DNSKEY found.");
1603 } else if (!goodksk)
1604 fatal("No self-signed KSK DNSKEY found. Supply an active\n"
1605 "key with the KSK flag set, or use '-P'.");
1607 fprintf(stderr, "Verifying the zone using the following algorithms:");
1608 for (i = 0; i < 256; i++) {
1610 act_algorithms[i] = (ksk_algorithms[i] != 0 ||
1611 zsk_algorithms[i] != 0) ? 1 : 0;
1613 act_algorithms[i] = ksk_algorithms[i] != 0 ? 1 : 0;
1614 if (act_algorithms[i] != 0) {
1615 dns_secalg_format(i, algbuf, sizeof(algbuf));
1616 fprintf(stderr, " %s", algbuf);
1619 fprintf(stderr, ".\n");
1621 if (!ignore_kskflag && !keyset_kskonly) {
1622 for (i = 0; i < 256; i++) {
1624 * The counts should both be zero or both be non-zero.
1625 * Mark the algorithm as bad if this is not met.
1627 if ((ksk_algorithms[i] != 0) ==
1628 (zsk_algorithms[i] != 0))
1630 dns_secalg_format(i, algbuf, sizeof(algbuf));
1631 fprintf(stderr, "Missing %s for algorithm %s\n",
1632 (ksk_algorithms[i] != 0)
1634 : "self-signed KSK",
1636 bad_algorithms[i] = 1;
1641 * Check that all the other records were signed by keys that are
1642 * present in the DNSKEY RRSET.
1645 dns_fixedname_init(&fname);
1646 name = dns_fixedname_name(&fname);
1647 dns_fixedname_init(&fnextname);
1648 nextname = dns_fixedname_name(&fnextname);
1649 dns_fixedname_init(&fprevname);
1651 dns_fixedname_init(&fzonecut);
1654 result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter);
1655 check_result(result, "dns_db_createiterator()");
1657 result = dns_dbiterator_first(dbiter);
1658 check_result(result, "dns_dbiterator_first()");
1661 isc_boolean_t isdelegation = ISC_FALSE;
1663 result = dns_dbiterator_current(dbiter, &node, name);
1664 check_dns_dbiterator_current(result);
1665 if (!dns_name_issubdomain(name, origin)) {
1666 check_no_nsec(name, node, db, ver);
1667 dns_db_detachnode(db, &node);
1668 result = dns_dbiterator_next(dbiter);
1669 if (result == ISC_R_NOMORE)
1672 check_result(result, "dns_dbiterator_next()");
1675 if (is_delegation(db, ver, origin, name, node, NULL)) {
1676 zonecut = dns_fixedname_name(&fzonecut);
1677 dns_name_copy(name, zonecut, NULL);
1678 isdelegation = ISC_TRUE;
1681 result = dns_dbiterator_next(dbiter);
1682 while (result == ISC_R_SUCCESS) {
1683 result = dns_dbiterator_current(dbiter, &nextnode,
1685 check_dns_dbiterator_current(result);
1686 if (!dns_name_issubdomain(nextname, origin) ||
1688 dns_name_issubdomain(nextname, zonecut)))
1690 check_no_nsec(nextname, nextnode, db, ver);
1691 dns_db_detachnode(db, &nextnode);
1692 result = dns_dbiterator_next(dbiter);
1695 if (is_empty(db, ver, nextnode)) {
1696 dns_db_detachnode(db, &nextnode);
1697 result = dns_dbiterator_next(dbiter);
1700 dns_db_detachnode(db, &nextnode);
1703 if (result == ISC_R_NOMORE) {
1706 } else if (result != ISC_R_SUCCESS)
1707 fatal("iterating through the database failed: %s",
1708 isc_result_totext(result));
1709 result = verifynode(db, ver, origin, mctx, name, node,
1710 isdelegation, &keyset, act_algorithms,
1711 bad_algorithms, &nsecset, &nsec3paramset,
1713 if (vresult == ISC_R_UNSET)
1714 vresult = ISC_R_SUCCESS;
1715 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1717 if (prevname != NULL) {
1718 result = verifyemptynodes(db, ver, origin, mctx, name,
1719 prevname, isdelegation,
1722 prevname = dns_fixedname_name(&fprevname);
1723 dns_name_copy(name, prevname, NULL);
1724 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1726 dns_db_detachnode(db, &node);
1729 dns_dbiterator_destroy(&dbiter);
1731 result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter);
1732 check_result(result, "dns_db_createiterator()");
1734 for (result = dns_dbiterator_first(dbiter);
1735 result == ISC_R_SUCCESS;
1736 result = dns_dbiterator_next(dbiter) ) {
1737 result = dns_dbiterator_current(dbiter, &node, name);
1738 check_dns_dbiterator_current(result);
1739 result = verifynode(db, ver, origin, mctx, name, node,
1740 ISC_FALSE, &keyset, act_algorithms,
1741 bad_algorithms, NULL, NULL, NULL);
1742 check_result(result, "verifynode");
1743 record_found(db, ver, mctx, name, node, &nsec3paramset);
1744 dns_db_detachnode(db, &node);
1746 dns_dbiterator_destroy(&dbiter);
1748 dns_rdataset_disassociate(&keyset);
1749 if (dns_rdataset_isassociated(&nsecset))
1750 dns_rdataset_disassociate(&nsecset);
1751 if (dns_rdataset_isassociated(&nsec3paramset))
1752 dns_rdataset_disassociate(&nsec3paramset);
1754 result = verify_nsec3_chains(mctx);
1755 if (vresult == ISC_R_UNSET)
1756 vresult = ISC_R_SUCCESS;
1757 if (result != ISC_R_SUCCESS && vresult == ISC_R_SUCCESS)
1759 isc_heap_destroy(&expected_chains);
1760 isc_heap_destroy(&found_chains);
1763 * If we made it this far, we have what we consider a properly signed
1764 * zone. Set the good flag.
1766 for (i = 0; i < 256; i++) {
1767 if (bad_algorithms[i] != 0) {
1769 fprintf(stderr, "The zone is not fully signed "
1770 "for the following algorithms:");
1771 dns_secalg_format(i, algbuf, sizeof(algbuf));
1772 fprintf(stderr, " %s", algbuf);
1777 fprintf(stderr, ".\n");
1778 fatal("DNSSEC completeness test failed.");
1781 if (vresult != ISC_R_SUCCESS)
1782 fatal("DNSSEC completeness test failed (%s).",
1783 dns_result_totext(vresult));
1785 if (goodksk || ignore_kskflag) {
1787 * Print the success summary.
1789 fprintf(stderr, "Zone fully signed:\n");
1790 for (i = 0; i < 256; i++) {
1791 if ((ksk_algorithms[i] != 0) ||
1792 (standby_ksk[i] != 0) ||
1793 (revoked_zsk[i] != 0) ||
1794 (zsk_algorithms[i] != 0) ||
1795 (standby_zsk[i] != 0) ||
1796 (revoked_zsk[i] != 0)) {
1797 dns_secalg_format(i, algbuf, sizeof(algbuf));
1798 fprintf(stderr, "Algorithm: %s: KSKs: "
1799 "%u active, %u stand-by, %u revoked\n",
1800 algbuf, ksk_algorithms[i],
1801 standby_ksk[i], revoked_ksk[i]);
1802 fprintf(stderr, "%*sZSKs: "
1803 "%u active, %u %s, %u revoked\n",
1804 (int) strlen(algbuf) + 13, "",
1807 keyset_kskonly ? "present" : "stand-by",