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