]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/bin/dnssec/dnssectool.c
MFV 262445:
[FreeBSD/stable/9.git] / contrib / bind9 / bin / dnssec / dnssectool.c
1 /*
2  * Copyright (C) 2004, 2005, 2007, 2009-2014  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
4  *
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.
8  *
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.
16  */
17
18 /* $Id: dnssectool.c,v 1.63 2011/10/21 03:55:33 marka Exp $ */
19
20 /*! \file */
21
22 /*%
23  * DNSSEC Support Routines.
24  */
25
26 #include <config.h>
27
28 #include <stdlib.h>
29
30 #include <isc/base32.h>
31 #include <isc/buffer.h>
32 #include <isc/dir.h>
33 #include <isc/entropy.h>
34 #include <isc/heap.h>
35 #include <isc/list.h>
36 #include <isc/mem.h>
37 #include <isc/string.h>
38 #include <isc/time.h>
39 #include <isc/util.h>
40 #include <isc/print.h>
41
42 #include <dns/db.h>
43 #include <dns/dbiterator.h>
44 #include <dns/dnssec.h>
45 #include <dns/fixedname.h>
46 #include <dns/keyvalues.h>
47 #include <dns/log.h>
48 #include <dns/name.h>
49 #include <dns/nsec.h>
50 #include <dns/nsec3.h>
51 #include <dns/rdatastruct.h>
52 #include <dns/rdataclass.h>
53 #include <dns/rdataset.h>
54 #include <dns/rdatasetiter.h>
55 #include <dns/rdatatype.h>
56 #include <dns/result.h>
57 #include <dns/secalg.h>
58 #include <dns/time.h>
59
60 #include "dnssectool.h"
61
62 static isc_heap_t *expected_chains, *found_chains;
63
64 struct nsec3_chain_fixed {
65         isc_uint8_t     hash;
66         isc_uint8_t     salt_length;
67         isc_uint8_t     next_length;
68         isc_uint16_t    iterations;
69         /* unsigned char salt[0]; */
70         /* unsigned char owner[0]; */
71         /* unsigned char next[0]; */
72 };
73
74 extern int verbose;
75 extern const char *program;
76
77 typedef struct entropysource entropysource_t;
78
79 struct entropysource {
80         isc_entropysource_t *source;
81         isc_mem_t *mctx;
82         ISC_LINK(entropysource_t) link;
83 };
84
85 static ISC_LIST(entropysource_t) sources;
86 static fatalcallback_t *fatalcallback = NULL;
87
88 void
89 fatal(const char *format, ...) {
90         va_list args;
91
92         fprintf(stderr, "%s: fatal: ", program);
93         va_start(args, format);
94         vfprintf(stderr, format, args);
95         va_end(args);
96         fprintf(stderr, "\n");
97         if (fatalcallback != NULL)
98                 (*fatalcallback)();
99         exit(1);
100 }
101
102 void
103 setfatalcallback(fatalcallback_t *callback) {
104         fatalcallback = callback;
105 }
106
107 void
108 check_result(isc_result_t result, const char *message) {
109         if (result != ISC_R_SUCCESS)
110                 fatal("%s: %s", message, isc_result_totext(result));
111 }
112
113 void
114 vbprintf(int level, const char *fmt, ...) {
115         va_list ap;
116         if (level > verbose)
117                 return;
118         va_start(ap, fmt);
119         fprintf(stderr, "%s: ", program);
120         vfprintf(stderr, fmt, ap);
121         va_end(ap);
122 }
123
124 void
125 type_format(const dns_rdatatype_t type, char *cp, unsigned int size) {
126         isc_buffer_t b;
127         isc_region_t r;
128         isc_result_t result;
129
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;
135 }
136
137 void
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];
141
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);
145 }
146
147 void
148 setup_logging(int verbose, isc_mem_t *mctx, isc_log_t **logp) {
149         isc_result_t result;
150         isc_logdestination_t destination;
151         isc_logconfig_t *logconfig = NULL;
152         isc_log_t *log = NULL;
153         int level;
154
155         if (verbose < 0)
156                 verbose = 0;
157         switch (verbose) {
158         case 0:
159                 /*
160                  * We want to see warnings about things like out-of-zone
161                  * data in the master file even when not verbose.
162                  */
163                 level = ISC_LOG_WARNING;
164                 break;
165         case 1:
166                 level = ISC_LOG_INFO;
167                 break;
168         default:
169                 level = ISC_LOG_DEBUG(verbose - 2 + 1);
170                 break;
171         }
172
173         RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
174         isc_log_setcontext(log);
175         dns_log_init(log);
176         dns_log_setcontext(log);
177
178         RUNTIME_CHECK(isc_log_settag(logconfig, program) == ISC_R_SUCCESS);
179
180         /*
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
185          */
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",
191                                        ISC_LOG_TOFILEDESC,
192                                        level,
193                                        &destination,
194                                        ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL);
195         check_result(result, "isc_log_createchannel()");
196
197         RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
198                                          NULL, NULL) == ISC_R_SUCCESS);
199
200         *logp = log;
201 }
202
203 void
204 cleanup_logging(isc_log_t **logp) {
205         isc_log_t *log;
206
207         REQUIRE(logp != NULL);
208
209         log = *logp;
210         if (log == NULL)
211                 return;
212         isc_log_destroy(&log);
213         isc_log_setcontext(NULL);
214         dns_log_setcontext(NULL);
215         logp = NULL;
216 }
217
218 void
219 setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) {
220         isc_result_t result;
221         isc_entropysource_t *source = NULL;
222         entropysource_t *elt;
223         int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE;
224
225         REQUIRE(ectx != NULL);
226
227         if (*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);
232         }
233
234         if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) {
235                 usekeyboard = ISC_ENTROPY_KEYBOARDYES;
236                 randomfile = NULL;
237         }
238
239         result = isc_entropy_usebestsource(*ectx, &source, randomfile,
240                                            usekeyboard);
241
242         if (result != ISC_R_SUCCESS)
243                 fatal("could not initialize entropy source: %s",
244                       isc_result_totext(result));
245
246         if (source != NULL) {
247                 elt = isc_mem_get(mctx, sizeof(*elt));
248                 if (elt == NULL)
249                         fatal("out of memory");
250                 elt->source = source;
251                 elt->mctx = mctx;
252                 ISC_LINK_INIT(elt, link);
253                 ISC_LIST_APPEND(sources, elt, link);
254         }
255 }
256
257 void
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));
265         }
266         isc_entropy_detach(ectx);
267 }
268
269 static isc_stdtime_t
270 time_units(isc_stdtime_t offset, char *suffix, const char *str) {
271         switch (suffix[0]) {
272             case 'Y': case 'y':
273                 return (offset * (365 * 24 * 3600));
274             case 'M': case 'm':
275                 switch (suffix[1]) {
276                     case 'O': case 'o':
277                         return (offset * (30 * 24 * 3600));
278                     case 'I': case 'i':
279                         return (offset * 60);
280                     case '\0':
281                         fatal("'%s' ambiguous: use 'mi' for minutes "
282                               "or 'mo' for months", str);
283                     default:
284                         fatal("time value %s is invalid", str);
285                 }
286                 /* NOTREACHED */
287                 break;
288             case 'W': case 'w':
289                 return (offset * (7 * 24 * 3600));
290             case 'D': case 'd':
291                 return (offset * (24 * 3600));
292             case 'H': case 'h':
293                 return (offset * 3600);
294             case 'S': case 's': case '\0':
295                 return (offset);
296             default:
297                 fatal("time value %s is invalid", str);
298         }
299         /* NOTREACHED */
300         return(0); /* silence compiler warning */
301 }
302
303 dns_ttl_t
304 strtottl(const char *str) {
305         const char *orig = str;
306         dns_ttl_t ttl;
307         char *endp;
308
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);
313         return (ttl);
314 }
315
316 isc_stdtime_t
317 strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
318         isc_int64_t val, offset;
319         isc_result_t result;
320         const char *orig = str;
321         char *endp;
322         int n;
323
324         if ((str[0] == '0' || str[0] == '-') && str[1] == '\0')
325                 return ((isc_stdtime_t) 0);
326
327         /*
328          * We accept times in the following formats:
329          *   now([+-]offset)
330          *   YYYYMMDD([+-]offset)
331          *   YYYYMMDDhhmmss([+-]offset)
332          *   [+-]offset
333          */
334         n = strspn(str, "0123456789");
335         if ((n == 8 || n == 14) &&
336             (str[n] == '\0' || str[n] == '-' || str[n] == '+'))
337         {
338                 char timestr[15];
339
340                 strlcpy(timestr, str, sizeof(timestr));
341                 timestr[n] = 0;
342                 if (n == 8)
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));
348                 base = val;
349                 str += n;
350         } else if (strncmp(str, "now", 3) == 0) {
351                 base = now;
352                 str += 3;
353         }
354
355         if (str[0] == '\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);
360                 val = base + offset;
361         } else if (str[0] == '-') {
362                 offset = strtol(str + 1, &endp, 0);
363                 offset = time_units((isc_stdtime_t) offset, endp, orig);
364                 val = base - offset;
365         } else
366                 fatal("time value %s is invalid", orig);
367
368         return ((isc_stdtime_t) val);
369 }
370
371 dns_rdataclass_t
372 strtoclass(const char *str) {
373         isc_textregion_t r;
374         dns_rdataclass_t rdclass;
375         isc_result_t ret;
376
377         if (str == NULL)
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);
384         return (rdclass);
385 }
386
387 isc_result_t
388 try_dir(const char *dirname) {
389         isc_result_t result;
390         isc_dir_t d;
391
392         isc_dir_init(&d);
393         result = isc_dir_open(&d, dirname);
394         if (result == ISC_R_SUCCESS) {
395                 isc_dir_close(&d);
396         }
397         return (result);
398 }
399
400 /*
401  * Check private key version compatibility.
402  */
403 void
404 check_keyversion(dst_key_t *key, char *keystr) {
405         int major, minor;
406         dst_key_getprivateformat(key, &major, &minor);
407         INSIST(major <= DST_MAJOR_VERSION); /* invalid private key */
408
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);
417 }
418
419 void
420 set_keyversion(dst_key_t *key) {
421         int major, minor;
422         dst_key_getprivateformat(key, &major, &minor);
423         INSIST(major <= DST_MAJOR_VERSION);
424
425         if (major != DST_MAJOR_VERSION || minor != DST_MINOR_VERSION)
426                 dst_key_setprivateformat(key, DST_MAJOR_VERSION,
427                                          DST_MINOR_VERSION);
428
429         /*
430          * If the key is from a version older than 1.3, set
431          * set the creation date
432          */
433         if (major < 1 || (major == 1 && minor <= 2)) {
434                 isc_stdtime_t now;
435                 isc_stdtime_get(&now);
436                 dst_key_settime(key, DST_TIME_CREATED, now);
437         }
438 }
439
440 isc_boolean_t
441 key_collision(dst_key_t *dstkey, dns_name_t *name, const char *dir,
442               isc_mem_t *mctx, isc_boolean_t *exact)
443 {
444         isc_result_t result;
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;
450         dns_secalg_t alg;
451
452         if (exact != NULL)
453                 *exact = ISC_FALSE;
454
455         id = dst_key_id(dstkey);
456         rid = dst_key_rid(dstkey);
457         alg = dst_key_alg(dstkey);
458
459         ISC_LIST_INIT(matchkeys);
460         result = dns_dnssec_findmatchingkeys(name, dir, mctx, &matchkeys);
461         if (result == ISC_R_NOTFOUND)
462                 return (ISC_FALSE);
463
464         while (!ISC_LIST_EMPTY(matchkeys) && !conflict) {
465                 key = ISC_LIST_HEAD(matchkeys);
466                 if (dst_key_alg(key->key) != alg)
467                         goto next;
468
469                 oldid = dst_key_id(key->key);
470                 roldid = dst_key_rid(key->key);
471
472                 if (oldid == rid || roldid == id || id == oldid) {
473                         conflict = ISC_TRUE;
474                         if (id != oldid) {
475                                 if (verbose > 1)
476                                         fprintf(stderr, "Key ID %d could "
477                                                 "collide with %d\n",
478                                                 id, oldid);
479                         } else {
480                                 if (exact != NULL)
481                                         *exact = ISC_TRUE;
482                                 if (verbose > 1)
483                                         fprintf(stderr, "Key ID %d exists\n",
484                                                 id);
485                         }
486                 }
487
488  next:
489                 ISC_LIST_UNLINK(matchkeys, key, link);
490                 dns_dnsseckey_destroy(mctx, &key);
491         }
492
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);
498         }
499
500         return (conflict);
501 }
502
503 isc_boolean_t
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)
506 {
507         dns_rdataset_t nsset;
508         isc_result_t result;
509
510         if (dns_name_equal(name, origin))
511                 return (ISC_FALSE);
512
513         dns_rdataset_init(&nsset);
514         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_ns,
515                                      0, 0, &nsset, NULL);
516         if (dns_rdataset_isassociated(&nsset)) {
517                 if (ttlp != NULL)
518                         *ttlp = nsset.ttl;
519                 dns_rdataset_disassociate(&nsset);
520         }
521
522         return (ISC_TF(result == ISC_R_SUCCESS));
523 }
524
525 static isc_boolean_t
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)
528 {
529         dns_rdata_dnskey_t key;
530         dns_rdata_rrsig_t sig;
531         dst_key_t *dstkey = NULL;
532         isc_result_t result;
533
534         result = dns_rdata_tostruct(sigrdata, &sig, NULL);
535         check_result(result, "dns_rdata_tostruct()");
536
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,
545                                                  &dstkey);
546                 if (result != ISC_R_SUCCESS)
547                         return (ISC_FALSE);
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);
552                         continue;
553                 }
554                 result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
555                                            mctx, sigrdata);
556                 dst_key_free(&dstkey);
557                 if (result == ISC_R_SUCCESS)
558                         return(ISC_TRUE);
559         }
560         return (ISC_FALSE);
561 }
562
563 static isc_result_t
564 verifynsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
565            dns_dbnode_t *node, dns_name_t *nextname)
566 {
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;
575         isc_result_t result;
576
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);
583                 goto failure;
584         }
585
586         result = dns_rdataset_first(&rdataset);
587         check_result(result, "dns_rdataset_first()");
588
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,
599                                 nextbuf, found);
600                 goto failure;
601         }
602         /* Check bit map is consistent */
603         result = dns_nsec_buildrdata(db, ver, node, nextname, buffer,
604                                      &tmprdata);
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);
610                 goto failure;
611         }
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);
616                 goto failure;
617
618         }
619         dns_rdataset_disassociate(&rdataset);
620         return (ISC_R_SUCCESS);
621  failure:
622         if (dns_rdataset_isassociated(&rdataset))
623                 dns_rdataset_disassociate(&rdataset);
624         return (ISC_R_FAILURE);
625 }
626
627 static void
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)
630 {
631         char namebuf[DNS_NAME_FORMATSIZE];
632         char typebuf[80];
633         dns_rdataset_t sigrdataset;
634         dns_rdatasetiter_t *rdsiter = NULL;
635         isc_result_t result;
636
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)
646                         break;
647                 dns_rdataset_disassociate(&sigrdataset);
648         }
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);
654         }
655         if (dns_rdataset_isassociated(&sigrdataset))
656                 dns_rdataset_disassociate(&sigrdataset);
657         dns_rdatasetiter_destroy(&rdsiter);
658 }
659
660 static isc_boolean_t
661 chain_compare(void *arg1, void *arg2) {
662         struct nsec3_chain_fixed *e1 = arg1, *e2 = arg2;
663         size_t len;
664
665         /*
666          * Do each element in turn to get a stable sort.
667          */
668         if (e1->hash < e2->hash)
669                 return (ISC_TRUE);
670         if (e1->hash > e2->hash)
671                 return (ISC_FALSE);
672         if (e1->iterations < e2->iterations)
673                 return (ISC_TRUE);
674         if (e1->iterations > e2->iterations)
675                 return (ISC_FALSE);
676         if (e1->salt_length < e2->salt_length)
677                 return (ISC_TRUE);
678         if (e1->salt_length > e2->salt_length)
679                 return (ISC_FALSE);
680         if (e1->next_length < e2->next_length)
681                 return (ISC_TRUE);
682         if (e1->next_length > e2->next_length)
683                 return (ISC_FALSE);
684         len = e1->salt_length + 2 * e1->next_length;
685         if (memcmp(e1 + 1, e2 + 1, len) < 0)
686                 return (ISC_TRUE);
687         return (ISC_FALSE);
688 }
689
690 static isc_boolean_t
691 chain_equal(struct nsec3_chain_fixed *e1, struct nsec3_chain_fixed *e2) {
692         size_t len;
693
694         if (e1->hash != e2->hash)
695                 return (ISC_FALSE);
696         if (e1->iterations != e2->iterations)
697                 return (ISC_FALSE);
698         if (e1->salt_length != e2->salt_length)
699                 return (ISC_FALSE);
700         if (e1->next_length != e2->next_length)
701                 return (ISC_FALSE);
702         len = e1->salt_length + 2 * e1->next_length;
703         if (memcmp(e1 + 1, e2 + 1, len) != 0)
704                 return (ISC_FALSE);
705         return (ISC_TRUE);
706 }
707
708 static isc_result_t
709 record_nsec3(const unsigned char *rawhash, const dns_rdata_nsec3_t *nsec3,
710              isc_mem_t *mctx, isc_heap_t *chains)
711 {
712         struct nsec3_chain_fixed *element;
713         size_t len;
714         unsigned char *cp;
715         isc_result_t result;
716
717         len = sizeof(*element) + nsec3->next_length * 2 + nsec3->salt_length;
718
719         element = isc_mem_get(mctx, len);
720         if (element == NULL)
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);
738         }
739         return (result);
740 }
741
742 static isc_result_t
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)
747 {
748         unsigned char cbm[8244];
749         char namebuf[DNS_NAME_FORMATSIZE];
750         dns_rdata_nsec3_t nsec3;
751         isc_result_t result;
752         unsigned int len;
753
754         /*
755          * Find matching NSEC3 record.
756          */
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)
770                         break;
771         }
772         if (result != ISC_R_SUCCESS) {
773                 dns_name_format(name, namebuf, sizeof(namebuf));
774                 fprintf(stderr, "Missing NSEC3 record for %s\n", namebuf);
775                 return (result);
776         }
777
778         /*
779          * Check the type list.
780          */
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);
787         }
788
789         /*
790          * Record chain.
791          */
792         result = record_nsec3(rawhash, &nsec3, mctx, expected_chains);
793         check_result(result, "record_nsec3()");
794
795         /*
796          * Make sure there is only one NSEC3 record with this set of
797          * parameters.
798          */
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;
815                         break;
816                 }
817         }
818         if (result != ISC_R_NOMORE)
819                 return (result);
820
821         result = ISC_R_SUCCESS;
822         return (result);
823 }
824
825 static isc_boolean_t
826 innsec3params(dns_rdata_nsec3_t *nsec3, dns_rdataset_t *nsec3paramset) {
827         dns_rdata_nsec3param_t nsec3param;
828         isc_result_t result;
829
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;
834
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)
844                         return (ISC_TRUE);
845         }
846         return (ISC_FALSE);
847 }
848
849 static isc_result_t
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)
853 {
854         unsigned char owner[NSEC3_MAX_HASH_LENGTH];
855         dns_rdata_nsec3_t nsec3;
856         dns_rdataset_t rdataset;
857         dns_label_t hashlabel;
858         isc_buffer_t b;
859         isc_result_t result;
860
861         if (nsec3paramset == NULL || !dns_rdataset_isassociated(nsec3paramset))
862                 return (ISC_R_SUCCESS);
863
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);
869
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)
875                 goto cleanup;
876
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))
885                         continue;
886                 /*
887                  * We only care about NSEC3 records that match a NSEC3PARAM
888                  * record.
889                  */
890                 if (!innsec3params(&nsec3, nsec3paramset))
891                         continue;
892
893                 /*
894                  * Record chain.
895                  */
896                 result = record_nsec3(owner, &nsec3, mctx, found_chains);
897                 check_result(result, "record_nsec3()");
898         }
899
900  cleanup:
901         dns_rdataset_disassociate(&rdataset);
902         return (ISC_R_SUCCESS);
903 }
904
905 static isc_boolean_t
906 isoptout(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin,
907          dns_rdata_t *nsec3rdata)
908 {
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;
915         isc_result_t result;
916         dns_dbnode_t *node = NULL;
917         unsigned char rawhash[NSEC3_MAX_HASH_LENGTH];
918         size_t rhsize = sizeof(rawhash);
919         isc_boolean_t ret;
920
921         result = dns_rdata_tostruct(nsec3rdata, &nsec3param, NULL);
922         check_result(result, "dns_rdata_tostruct()");
923
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()");
929
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)
937                 return (ISC_FALSE);
938
939         result = dns_rdataset_first(&rdataset);
940         check_result(result, "dns_rdataset_first()");
941
942         dns_rdataset_current(&rdataset, &rdata);
943
944         result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
945         if (result != ISC_R_SUCCESS)
946                 ret = ISC_FALSE;
947         else
948                 ret = ISC_TF((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0);
949
950         if (dns_rdataset_isassociated(&rdataset))
951                 dns_rdataset_disassociate(&rdataset);
952         if (node != NULL)
953                 dns_db_detachnode(db, &node);
954
955         return (ret);
956 }
957
958 static isc_result_t
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)
963 {
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;
970         isc_result_t result;
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;
975
976         result = dns_rdata_tostruct(rdata, &nsec3param, NULL);
977         check_result(result, "dns_rdata_tostruct()");
978
979         if (nsec3param.flags != 0)
980                 return (ISC_R_SUCCESS);
981
982         if (!dns_nsec3_supportedhash(nsec3param.hash))
983                 return (ISC_R_SUCCESS);
984
985         optout = isoptout(db, ver, origin, rdata);
986
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()");
992
993         /*
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
997          * be up to date.
998          */
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))))
1008         {
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",
1012                         namebuf, hashbuf);
1013         } else if (result == ISC_R_NOTFOUND &&
1014                    delegation && (!empty || optout))
1015         {
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);
1020         }
1021
1022         if (dns_rdataset_isassociated(&rdataset))
1023                 dns_rdataset_disassociate(&rdataset);
1024         if (node != NULL)
1025                 dns_db_detachnode(db, &node);
1026
1027         return (result);
1028 }
1029
1030 static isc_result_t
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)
1035 {
1036         isc_result_t result;
1037
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;
1042
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)
1047                         break;
1048         }
1049         if (result == ISC_R_NOMORE)
1050                 result = ISC_R_SUCCESS;
1051         return (result);
1052 }
1053
1054 static void
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)
1059 {
1060         unsigned char set_algorithms[256];
1061         char namebuf[DNS_NAME_FORMATSIZE];
1062         char algbuf[80];
1063         char typebuf[80];
1064         dns_rdataset_t sigrdataset;
1065         dns_rdatasetiter_t *rdsiter = NULL;
1066         isc_result_t result;
1067         int i;
1068
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)
1078                         break;
1079                 dns_rdataset_disassociate(&sigrdataset);
1080         }
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);
1089                 return;
1090         }
1091
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;
1098
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);
1107                         continue;
1108                 }
1109                 if ((set_algorithms[sig.algorithm] != 0) ||
1110                     (act_algorithms[sig.algorithm] == 0))
1111                         continue;
1112                 if (goodsig(origin, &rdata, name, keyrdataset, rdataset, mctx))
1113                         set_algorithms[sig.algorithm] = 1;
1114         }
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;
1126                         }
1127         }
1128         dns_rdataset_disassociate(&sigrdataset);
1129 }
1130
1131 static isc_result_t
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)
1138 {
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;
1143
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);
1151                 /*
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.
1157                  */
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);
1173                 } else
1174                         dns_nsec_setbit(types, rdataset.type, 1);
1175                 dns_rdataset_disassociate(&rdataset);
1176                 result = dns_rdatasetiter_next(rdsiter);
1177         }
1178         if (result != ISC_R_NOMORE)
1179                 fatal("rdataset iteration failed: %s",
1180                       isc_result_totext(result));
1181         dns_rdatasetiter_destroy(&rdsiter);
1182
1183         result = ISC_R_SUCCESS;
1184
1185         if (nsecset != NULL && dns_rdataset_isassociated(nsecset))
1186                 result = verifynsec(db, ver, name, node, nextname);
1187
1188         if (nsec3paramset != NULL && dns_rdataset_isassociated(nsec3paramset)) {
1189                 tresult = verifynsec3s(db, ver, origin, mctx, name,
1190                                        nsec3paramset, delegation, ISC_FALSE,
1191                                        types, maxtype);
1192                 if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS)
1193                         result = tresult;
1194         }
1195         return (result);
1196 }
1197
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;
1202
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)
1208                 return (ISC_TRUE);
1209         return (ISC_FALSE);
1210 }
1211
1212 static void
1213 check_no_nsec(dns_name_t *name, dns_dbnode_t *node, dns_db_t *db,
1214               dns_dbversion_t *ver)
1215 {
1216         dns_rdataset_t rdataset;
1217         isc_result_t result;
1218
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);
1226         }
1227
1228         if (dns_rdataset_isassociated(&rdataset))
1229                 dns_rdataset_disassociate(&rdataset);
1230 }
1231
1232 static isc_boolean_t
1233 newchain(const struct nsec3_chain_fixed *first,
1234          const struct nsec3_chain_fixed *e)
1235 {
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)
1241                 return (ISC_TRUE);
1242         return (ISC_FALSE);
1243 }
1244
1245 static void
1246 free_element(isc_mem_t *mctx, struct nsec3_chain_fixed *e) {
1247         size_t len;
1248
1249         len = sizeof(*e) + e->salt_length + 2 * e->next_length;
1250         isc_mem_put(mctx, e, len);
1251 }
1252
1253 static isc_boolean_t
1254 checknext(const struct nsec3_chain_fixed *first,
1255           const struct nsec3_chain_fixed *e)
1256 {
1257         char buf[512];
1258         const unsigned char *d1 = (const unsigned char *)(first + 1);
1259         const unsigned char *d2 = (const unsigned char *)(e + 1);
1260         isc_buffer_t b;
1261         isc_region_t sr;
1262
1263         d1 += first->salt_length + first->next_length;
1264         d2 += e->salt_length;
1265
1266         if (memcmp(d1, d2, first->next_length) == 0)
1267                 return (ISC_TRUE);
1268
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);
1275
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),
1281                 buf);
1282
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);
1288
1289         return (ISC_FALSE);
1290 }
1291
1292 #define EXPECTEDANDFOUND "Expected and found NSEC3 chains not equal\n"
1293
1294 static isc_result_t
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;
1299
1300         while ((e = isc_heap_element(expected_chains, 1)) != NULL) {
1301                 isc_heap_delete(expected_chains, 1);
1302                 if (f == NULL)
1303                         f = isc_heap_element(found_chains, 1);
1304                 if (f != NULL) {
1305                         isc_heap_delete(found_chains, 1);
1306
1307                         /*
1308                          * Check that they match.
1309                          */
1310                         if (chain_equal(e, f)) {
1311                                 free_element(mctx, f);
1312                                 f = NULL;
1313                         } else {
1314                                 if (result == ISC_R_SUCCESS)
1315                                         fprintf(stderr, EXPECTEDANDFOUND);
1316                                 result = ISC_R_FAILURE;
1317                                 /*
1318                                  * Attempt to resync found_chain.
1319                                  */
1320                                 while (f != NULL && !chain_compare(e, f)) {
1321                                         free_element(mctx, f);
1322                                         f = isc_heap_element(found_chains, 1);
1323                                         if (f != NULL)
1324                                                 isc_heap_delete(found_chains, 1);
1325                                         if (f != NULL && chain_equal(e, f)) {
1326                                                 free_element(mctx, f);
1327                                                 f = NULL;
1328                                                 break;
1329                                         }
1330                                 }
1331                         }
1332                 } else if (result == ISC_R_SUCCESS) {
1333                         fprintf(stderr, EXPECTEDANDFOUND);
1334                         result = ISC_R_FAILURE;
1335                 }
1336                 if (first == NULL || newchain(first, e)) {
1337                         if (prev != NULL) {
1338                                 if (!checknext(prev, first))
1339                                         result = ISC_R_FAILURE;
1340                                 if (prev != first)
1341                                         free_element(mctx, prev);
1342                         }
1343                         if (first != NULL)
1344                                 free_element(mctx, first);
1345                         prev = first = e;
1346                         continue;
1347                 }
1348                 if (!checknext(prev, e))
1349                         result = ISC_R_FAILURE;
1350                 if (prev != first)
1351                         free_element(mctx, prev);
1352                 prev = e;
1353         }
1354         if (prev != NULL) {
1355                 if (!checknext(prev, first))
1356                         result = ISC_R_FAILURE;
1357                 if (prev != first)
1358                         free_element(mctx, prev);
1359         }
1360         if (first != NULL)
1361                 free_element(mctx, first);
1362         do {
1363                 if (f != NULL) {
1364                         if (result == ISC_R_SUCCESS) {
1365                                 fprintf(stderr, EXPECTEDANDFOUND);
1366                                 result = ISC_R_FAILURE;
1367                         }
1368                         free_element(mctx, f);
1369                 }
1370                 f = isc_heap_element(found_chains, 1);
1371                 if (f != NULL)
1372                         isc_heap_delete(found_chains, 1);
1373         } while (f != NULL);
1374
1375         return (result);
1376 }
1377
1378 static isc_result_t
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)
1382 {
1383         dns_namereln_t reln;
1384         int order;
1385         unsigned int labels, nlabels, i;
1386         dns_name_t suffix;
1387         isc_result_t result = ISC_R_SUCCESS, tresult;
1388
1389         reln = dns_name_fullcompare(prevname, name, &order, &labels);
1390         if (order >= 0)
1391                 return (result);
1392
1393         nlabels = dns_name_countlabels(name);
1394
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,
1400                                                   &suffix);
1401                         if (nsec3paramset != NULL &&
1402                              dns_rdataset_isassociated(nsec3paramset)) {
1403                                 tresult = verifynsec3s(db, ver, origin, mctx,
1404                                                        &suffix, nsec3paramset,
1405                                                        isdelegation, ISC_TRUE,
1406                                                        NULL, 0);
1407                                 if (result == ISC_R_SUCCESS &&
1408                                     tresult != ISC_R_SUCCESS)
1409                                         result = tresult;
1410                         }
1411                 }
1412         }
1413         return (result);
1414 }
1415
1416 /*%
1417  * Verify that certain things are sane:
1418  *
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.
1421  *
1422  *   The DNSKEY record was signed with at least one of the KSKs in this
1423  *   set.
1424  *
1425  *   The rest of the zone was signed with at least one of the ZSKs
1426  *   present in the DNSKEY RRSET.
1427  */
1428 void
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)
1432 {
1433         char algbuf[80];
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;
1444         int i;
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];
1458
1459         result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1460                                  &expected_chains);
1461         check_result(result, "isc_heap_create()");
1462         result = isc_heap_create(mctx, chain_compare, NULL, 1024,
1463                                  &found_chains);
1464         check_result(result, "isc_heap_create()");
1465
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));
1470
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");
1483
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");
1488
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");
1493
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");
1498
1499         if (!dns_rdataset_isassociated(&keysigs))
1500                 fatal("DNSKEY is not signed (keys offline or inactive?)\n");
1501
1502         if (!dns_rdataset_isassociated(&soasigs))
1503                 fatal("SOA is not signed (keys offline or inactive?)\n");
1504
1505         if (dns_rdataset_isassociated(&nsecset) &&
1506             !dns_rdataset_isassociated(&nsecsigs))
1507                 fatal("NSEC is not signed (keys offline or inactive?)\n");
1508
1509         if (dns_rdataset_isassociated(&nsec3paramset) &&
1510             !dns_rdataset_isassociated(&nsec3paramsigs))
1511                 fatal("NSEC3PARAM is not signed (keys offline or inactive?)\n");
1512
1513         if (!dns_rdataset_isassociated(&nsecset) &&
1514             !dns_rdataset_isassociated(&nsec3paramset))
1515                 fatal("No valid NSEC/NSEC3 chain for testing\n");
1516
1517         dns_db_detachnode(db, &node);
1518
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));
1527
1528         /*
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).
1532          */
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");
1539
1540                 if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1541                         ;
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,
1546                                                   mctx)) {
1547                                 char namebuf[DNS_NAME_FORMATSIZE];
1548                                 char buffer[1024];
1549                                 isc_buffer_t buf;
1550
1551                                 dns_name_format(origin, namebuf,
1552                                                 sizeof(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);
1559                         }
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]++;
1571                                 goodksk = ISC_TRUE;
1572                         } else {
1573                                 if (standby_ksk[dnskey.algorithm] != 255)
1574                                         standby_ksk[dnskey.algorithm]++;
1575                         }
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]++;
1580                         goodzsk = ISC_TRUE;
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]++;
1585                 } else {
1586                         if (standby_zsk[dnskey.algorithm] != 255)
1587                                 standby_zsk[dnskey.algorithm]++;
1588                 }
1589                 dns_rdata_freestruct(&dnskey);
1590                 dns_rdata_reset(&rdata);
1591         }
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);
1599
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'.");
1606
1607         fprintf(stderr, "Verifying the zone using the following algorithms:");
1608         for (i = 0; i < 256; i++) {
1609                 if (ignore_kskflag)
1610                         act_algorithms[i] = (ksk_algorithms[i] != 0 ||
1611                                              zsk_algorithms[i] != 0) ? 1 : 0;
1612                 else
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);
1617                 }
1618         }
1619         fprintf(stderr, ".\n");
1620
1621         if (!ignore_kskflag && !keyset_kskonly) {
1622                 for (i = 0; i < 256; i++) {
1623                         /*
1624                          * The counts should both be zero or both be non-zero.
1625                          * Mark the algorithm as bad if this is not met.
1626                          */
1627                         if ((ksk_algorithms[i] != 0) ==
1628                             (zsk_algorithms[i] != 0))
1629                                 continue;
1630                         dns_secalg_format(i, algbuf, sizeof(algbuf));
1631                         fprintf(stderr, "Missing %s for algorithm %s\n",
1632                                 (ksk_algorithms[i] != 0)
1633                                    ? "ZSK"
1634                                    : "self-signed KSK",
1635                                 algbuf);
1636                         bad_algorithms[i] = 1;
1637                 }
1638         }
1639
1640         /*
1641          * Check that all the other records were signed by keys that are
1642          * present in the DNSKEY RRSET.
1643          */
1644
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);
1650         prevname = NULL;
1651         dns_fixedname_init(&fzonecut);
1652         zonecut = NULL;
1653
1654         result = dns_db_createiterator(db, DNS_DB_NONSEC3, &dbiter);
1655         check_result(result, "dns_db_createiterator()");
1656
1657         result = dns_dbiterator_first(dbiter);
1658         check_result(result, "dns_dbiterator_first()");
1659
1660         while (!done) {
1661                 isc_boolean_t isdelegation = ISC_FALSE;
1662
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)
1670                                 done = ISC_TRUE;
1671                         else
1672                                 check_result(result, "dns_dbiterator_next()");
1673                         continue;
1674                 }
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;
1679                 }
1680                 nextnode = NULL;
1681                 result = dns_dbiterator_next(dbiter);
1682                 while (result == ISC_R_SUCCESS) {
1683                         result = dns_dbiterator_current(dbiter, &nextnode,
1684                                                         nextname);
1685                         check_dns_dbiterator_current(result);
1686                         if (!dns_name_issubdomain(nextname, origin) ||
1687                             (zonecut != NULL &&
1688                              dns_name_issubdomain(nextname, zonecut)))
1689                         {
1690                                 check_no_nsec(nextname, nextnode, db, ver);
1691                                 dns_db_detachnode(db, &nextnode);
1692                                 result = dns_dbiterator_next(dbiter);
1693                                 continue;
1694                         }
1695                         if (is_empty(db, ver, nextnode)) {
1696                                 dns_db_detachnode(db, &nextnode);
1697                                 result = dns_dbiterator_next(dbiter);
1698                                 continue;
1699                         }
1700                         dns_db_detachnode(db, &nextnode);
1701                         break;
1702                 }
1703                 if (result == ISC_R_NOMORE) {
1704                         done = ISC_TRUE;
1705                         nextname = origin;
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,
1712                                     nextname);
1713                 if (vresult == ISC_R_UNSET)
1714                         vresult = ISC_R_SUCCESS;
1715                 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1716                         vresult = result;
1717                 if (prevname != NULL) {
1718                         result = verifyemptynodes(db, ver, origin, mctx, name,
1719                                                   prevname, isdelegation,
1720                                                   &nsec3paramset);
1721                 } else
1722                         prevname = dns_fixedname_name(&fprevname);
1723                 dns_name_copy(name, prevname, NULL);
1724                 if (vresult == ISC_R_SUCCESS && result != ISC_R_SUCCESS)
1725                         vresult = result;
1726                 dns_db_detachnode(db, &node);
1727         }
1728
1729         dns_dbiterator_destroy(&dbiter);
1730
1731         result = dns_db_createiterator(db, DNS_DB_NSEC3ONLY, &dbiter);
1732         check_result(result, "dns_db_createiterator()");
1733
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);
1745         }
1746         dns_dbiterator_destroy(&dbiter);
1747
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);
1753
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)
1758                 vresult = result;
1759         isc_heap_destroy(&expected_chains);
1760         isc_heap_destroy(&found_chains);
1761
1762         /*
1763          * If we made it this far, we have what we consider a properly signed
1764          * zone.  Set the good flag.
1765          */
1766         for (i = 0; i < 256; i++) {
1767                 if (bad_algorithms[i] != 0) {
1768                         if (first)
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);
1773                         first = ISC_FALSE;
1774                 }
1775         }
1776         if (!first) {
1777                 fprintf(stderr, ".\n");
1778                 fatal("DNSSEC completeness test failed.");
1779         }
1780
1781         if (vresult != ISC_R_SUCCESS)
1782                 fatal("DNSSEC completeness test failed (%s).",
1783                       dns_result_totext(vresult));
1784
1785         if (goodksk || ignore_kskflag) {
1786                 /*
1787                  * Print the success summary.
1788                  */
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, "",
1805                                         zsk_algorithms[i],
1806                                         standby_zsk[i],
1807                                         keyset_kskonly ? "present" : "stand-by",
1808                                         revoked_zsk[i]);
1809                         }
1810                 }
1811         }
1812 }