1 /* $NetBSD: dnssectool.c,v 1.9 2015/07/08 17:28:55 christos Exp $ */
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.
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 version(const char *name
) {
126 fprintf(stderr
, "%s %s\n", name
, VERSION
);
131 type_format(const dns_rdatatype_t type
, char *cp
, unsigned int size
) {
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;
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
);
154 setup_logging(isc_mem_t
*mctx
, isc_log_t
**logp
) {
156 isc_logdestination_t destination
;
157 isc_logconfig_t
*logconfig
= NULL
;
158 isc_log_t
*log
= NULL
;
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
;
172 level
= ISC_LOG_INFO
;
175 level
= ISC_LOG_DEBUG(verbose
- 2 + 1);
179 RUNTIME_CHECK(isc_log_create(mctx
, &log
, &logconfig
) == ISC_R_SUCCESS
);
180 isc_log_setcontext(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",
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
);
210 cleanup_logging(isc_log_t
**logp
) {
213 REQUIRE(logp
!= NULL
);
218 isc_log_destroy(&log
);
219 isc_log_setcontext(NULL
);
220 dns_log_setcontext(NULL
);
225 setup_entropy(isc_mem_t
*mctx
, const char *randomfile
, isc_entropy_t
**ectx
) {
227 isc_entropysource_t
*source
= NULL
;
228 entropysource_t
*elt
;
229 int usekeyboard
= ISC_ENTROPY_KEYBOARDMAYBE
;
231 REQUIRE(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
;
245 result
= isc_entropy_usebestsource(*ectx
, &source
, randomfile
,
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
));
255 fatal("out of memory");
256 elt
->source
= source
;
258 ISC_LINK_INIT(elt
, link
);
259 ISC_LIST_APPEND(sources
, elt
, link
);
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
);
276 time_units(isc_stdtime_t offset
, char *suffix
, const char *str
) {
279 return (offset
* (365 * 24 * 3600));
283 return (offset
* (30 * 24 * 3600));
285 return (offset
* 60);
287 fatal("'%s' ambiguous: use 'mi' for minutes "
288 "or 'mo' for months", str
);
290 fatal("time value %s is invalid", str
);
295 return (offset
* (7 * 24 * 3600));
297 return (offset
* (24 * 3600));
299 return (offset
* 3600);
300 case 'S': case 's': case '\0':
303 fatal("time value %s is invalid", str
);
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)));
316 strtottl(const char *str
) {
317 const char *orig
= 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
);
332 strtotime(const char *str
, isc_int64_t now
, isc_int64_t base
,
335 isc_int64_t val
, offset
;
337 const char *orig
= str
;
344 return ((isc_stdtime_t
) 0);
350 if ((str
[0] == '0' || str
[0] == '-') && str
[1] == '\0')
351 return ((isc_stdtime_t
) 0);
354 * We accept times in the following formats:
356 * YYYYMMDD([+-]offset)
357 * YYYYMMDDhhmmss([+-]offset)
360 n
= strspn(str
, "0123456789");
361 if ((n
== 8u || n
== 14u) &&
362 (str
[n
] == '\0' || str
[n
] == '-' || str
[n
] == '+'))
366 strlcpy(timestr
, str
, sizeof(timestr
));
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
));
376 } else if (strncmp(str
, "now", 3) == 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
);
387 } else if (str
[0] == '-') {
388 offset
= strtol(str
+ 1, &endp
, 0);
389 offset
= time_units((isc_stdtime_t
) offset
, endp
, orig
);
392 fatal("time value %s is invalid", orig
);
394 return ((isc_stdtime_t
) val
);
398 strtoclass(const char *str
) {
400 dns_rdataclass_t rdclass
;
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
);
414 try_dir(const char *dirname
) {
419 result
= isc_dir_open(&d
, dirname
);
420 if (result
== ISC_R_SUCCESS
) {
427 * Check private key version compatibility.
430 check_keyversion(dst_key_t
*key
, char *keystr
) {
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
);
446 set_keyversion(dst_key_t
*key
) {
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
,
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)) {
461 isc_stdtime_get(&now
);
462 dst_key_settime(key
, DST_TIME_CREATED
, now
);
467 key_collision(dst_key_t
*dstkey
, dns_name_t
*name
, const char *dir
,
468 isc_mem_t
*mctx
, isc_boolean_t
*exact
)
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
;
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
)
490 while (!ISC_LIST_EMPTY(matchkeys
) && !conflict
) {
491 key
= ISC_LIST_HEAD(matchkeys
);
492 if (dst_key_alg(key
->key
) != alg
)
495 oldid
= dst_key_id(key
->key
);
496 roldid
= dst_key_rid(key
->key
);
498 if (oldid
== rid
|| roldid
== id
|| id
== oldid
) {
502 fprintf(stderr
, "Key ID %d could "
509 fprintf(stderr
, "Key ID %d exists\n",
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
);
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
;
536 if (dns_name_equal(name
, origin
))
539 dns_rdataset_init(&nsset
);
540 result
= dns_db_findrdataset(db
, node
, ver
, dns_rdatatype_ns
,
542 if (dns_rdataset_isassociated(&nsset
)) {
545 dns_rdataset_disassociate(&nsset
);
548 return (ISC_TF(result
== ISC_R_SUCCESS
));
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
;
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
,
572 if (result
!= ISC_R_SUCCESS
)
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
);
580 result
= dns_dnssec_verify(name
, rdataset
, dstkey
, ISC_FALSE
,
582 dst_key_free(&dstkey
);
583 if (result
== ISC_R_SUCCESS
)
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
;
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
);
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
,
628 /* Check bit map is consistent */
629 result
= dns_nsec_buildrdata(db
, ver
, node
, nextname
, buffer
,
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
);
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
);
645 dns_rdataset_disassociate(&rdataset
);
646 return (ISC_R_SUCCESS
);
648 if (dns_rdataset_isassociated(&rdataset
))
649 dns_rdataset_disassociate(&rdataset
);
650 return (ISC_R_FAILURE
);
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
];
659 dns_rdataset_t sigrdataset
;
660 dns_rdatasetiter_t
*rdsiter
= NULL
;
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
)
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
);
687 chain_compare(void *arg1
, void *arg2
) {
688 struct nsec3_chain_fixed
*e1
= arg1
, *e2
= arg2
;
692 * Do each element in turn to get a stable sort.
694 if (e1
->hash
< e2
->hash
)
696 if (e1
->hash
> e2
->hash
)
698 if (e1
->iterations
< e2
->iterations
)
700 if (e1
->iterations
> e2
->iterations
)
702 if (e1
->salt_length
< e2
->salt_length
)
704 if (e1
->salt_length
> e2
->salt_length
)
706 if (e1
->next_length
< e2
->next_length
)
708 if (e1
->next_length
> e2
->next_length
)
710 len
= e1
->salt_length
+ 2 * e1
->next_length
;
711 if (memcmp(e1
+ 1, e2
+ 1, len
) < 0)
717 chain_equal(struct nsec3_chain_fixed
*e1
, struct nsec3_chain_fixed
*e2
) {
720 if (e1
->hash
!= e2
->hash
)
722 if (e1
->iterations
!= e2
->iterations
)
724 if (e1
->salt_length
!= e2
->salt_length
)
726 if (e1
->next_length
!= e2
->next_length
)
728 len
= e1
->salt_length
+ 2 * e1
->next_length
;
729 if (memcmp(e1
+ 1, e2
+ 1, len
) != 0)
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
;
743 len
= sizeof(*element
) + nsec3
->next_length
* 2 + nsec3
->salt_length
;
745 element
= isc_mem_get(mctx
, len
);
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
);
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
;
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)
798 if (result
!= ISC_R_SUCCESS
) {
799 dns_name_format(name
, namebuf
, sizeof(namebuf
));
800 fprintf(stderr
, "Missing NSEC3 record for %s\n", namebuf
);
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
);
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
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
;
844 if (result
!= ISC_R_NOMORE
)
847 result
= ISC_R_SUCCESS
;
852 innsec3params(dns_rdata_nsec3_t
*nsec3
, dns_rdataset_t
*nsec3paramset
) {
853 dns_rdata_nsec3param_t nsec3param
;
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)
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
;
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
)
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
))
913 * We only care about NSEC3 records that match a NSEC3PARAM
916 if (!innsec3params(&nsec3
, nsec3paramset
))
922 result
= record_nsec3(owner
, &nsec3
, mctx
, found_chains
);
923 check_result(result
, "record_nsec3()");
927 dns_rdataset_disassociate(&rdataset
);
928 return (ISC_R_SUCCESS
);
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
;
942 dns_dbnode_t
*node
= NULL
;
943 unsigned char rawhash
[NSEC3_MAX_HASH_LENGTH
];
944 size_t rhsize
= sizeof(rawhash
);
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
)
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
)
974 ret
= ISC_TF((nsec3
.flags
& DNS_NSEC3FLAG_OPTOUT
) != 0);
976 if (dns_rdataset_isassociated(&rdataset
))
977 dns_rdataset_disassociate(&rdataset
);
979 dns_db_detachnode(db
, &node
);
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
;
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
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",
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
);
1051 dns_db_detachnode(db
, &node
);
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
)
1075 if (result
== ISC_R_NOMORE
)
1076 result
= ISC_R_SUCCESS
;
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
];
1090 dns_rdataset_t sigrdataset
;
1091 dns_rdatasetiter_t
*rdsiter
= NULL
;
1092 isc_result_t result
;
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
)
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
);
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
);
1135 if ((set_algorithms
[sig
.algorithm
] != 0) ||
1136 (act_algorithms
[sig
.algorithm
] == 0))
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
);
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
);
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
,
1218 if (result
== ISC_R_SUCCESS
&& tresult
!= ISC_R_SUCCESS
)
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
)
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)
1272 free_element(isc_mem_t
*mctx
, struct nsec3_chain_fixed
*e
) {
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
)
1284 const unsigned char *d1
= (const unsigned char *)(first
+ 1);
1285 const unsigned char *d2
= (const unsigned char *)(e
+ 1);
1289 d1
+= first
->salt_length
+ first
->next_length
;
1290 d2
+= e
->salt_length
;
1292 if (memcmp(d1
, d2
, first
->next_length
) == 0)
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
),
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
);
1318 #define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n"
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);
1329 f
= isc_heap_element(found_chains
, 1);
1331 isc_heap_delete(found_chains
, 1);
1334 * Check that they match.
1336 if (chain_equal(e
, f
)) {
1337 free_element(mctx
, f
);
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);
1350 isc_heap_delete(found_chains
, 1);
1351 if (f
!= NULL
&& chain_equal(e
, f
)) {
1352 free_element(mctx
, f
);
1358 } else if (result
== ISC_R_SUCCESS
) {
1359 fprintf(stderr
, EXPECTEDANDFOUND
);
1360 result
= ISC_R_FAILURE
;
1362 if (first
== NULL
|| newchain(first
, e
)) {
1364 if (!checknext(prev
, first
))
1365 result
= ISC_R_FAILURE
;
1367 free_element(mctx
, prev
);
1370 free_element(mctx
, first
);
1374 if (!checknext(prev
, e
))
1375 result
= ISC_R_FAILURE
;
1377 free_element(mctx
, prev
);
1381 if (!checknext(prev
, first
))
1382 result
= ISC_R_FAILURE
;
1384 free_element(mctx
, prev
);
1387 free_element(mctx
, first
);
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);
1398 isc_heap_delete(found_chains
, 1);
1399 } while (f
!= NULL
);
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
;
1411 unsigned int labels
, nlabels
, i
;
1413 isc_result_t result
= ISC_R_SUCCESS
, tresult
;
1415 reln
= dns_name_fullcompare(prevname
, name
, &order
, &labels
);
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
,
1427 if (nsec3paramset
!= NULL
&&
1428 dns_rdataset_isassociated(nsec3paramset
)) {
1429 tresult
= verifynsec3s(db
, ver
, origin
, mctx
,
1430 &suffix
, nsec3paramset
,
1431 isdelegation
, ISC_TRUE
,
1433 if (result
== ISC_R_SUCCESS
&&
1434 tresult
!= ISC_R_SUCCESS
)
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
1451 * The rest of the zone was signed with at least one of the ZSKs
1452 * present in the DNSKEY RRSET.
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
)
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
;
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,
1487 check_result(result
, "isc_heap_create()");
1488 result
= isc_heap_create(mctx
, chain_compare
, NULL
, 1024,
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
,
1573 char namebuf
[DNS_NAME_FORMATSIZE
];
1577 dns_name_format(origin
, 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
]++;
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
]++;
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
]++;
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
++) {
1636 act_algorithms
[i
] = (ksk_algorithms
[i
] != 0 ||
1637 zsk_algorithms
[i
] != 0) ? 1 : 0;
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))
1656 dns_secalg_format(i
, algbuf
, sizeof(algbuf
));
1657 fprintf(stderr
, "Missing %s for algorithm %s\n",
1658 (ksk_algorithms
[i
] != 0)
1660 : "self-signed KSK",
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
);
1677 dns_fixedname_init(&fzonecut
);
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()");
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
)
1698 check_result(result
, "dns_dbiterator_next()");
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
;
1707 result
= dns_dbiterator_next(dbiter
);
1708 while (result
== ISC_R_SUCCESS
) {
1709 result
= dns_dbiterator_current(dbiter
, &nextnode
,
1711 check_dns_dbiterator_current(result
);
1712 if (!dns_name_issubdomain(nextname
, origin
) ||
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
);
1721 if (is_empty(db
, ver
, nextnode
)) {
1722 dns_db_detachnode(db
, &nextnode
);
1723 result
= dns_dbiterator_next(dbiter
);
1726 dns_db_detachnode(db
, &nextnode
);
1729 if (result
== ISC_R_NOMORE
) {
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
,
1739 if (vresult
== ISC_R_UNSET
)
1740 vresult
= ISC_R_SUCCESS
;
1741 if (vresult
== ISC_R_SUCCESS
&& result
!= ISC_R_SUCCESS
)
1743 if (prevname
!= NULL
) {
1744 result
= verifyemptynodes(db
, ver
, origin
, mctx
, name
,
1745 prevname
, isdelegation
,
1748 prevname
= dns_fixedname_name(&fprevname
);
1749 dns_name_copy(name
, prevname
, NULL
);
1750 if (vresult
== ISC_R_SUCCESS
&& result
!= ISC_R_SUCCESS
)
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
)
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) {
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
);
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, "",
1833 keyset_kskonly
? "present" : "stand-by",