Home | History | Annotate | Line # | Download | only in dnssec
dnssectool.c revision 1.1
      1 /*	$NetBSD: dnssectool.c,v 1.1 2018/08/12 12:07:19 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