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