PageRenderTime 200ms CodeModel.GetById 100ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/bin/dnssec/dnssec-signzone.c

https://bitbucket.org/freebsd/freebsd-head/
C | 4016 lines | 3223 code | 459 blank | 334 comment | 808 complexity | 404c53089d2909dfe9ec7a88ec65b188 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * Portions Copyright (C) 2004-2011  Internet Systems Consortium, Inc. ("ISC")
   3 * Portions Copyright (C) 1999-2003  Internet Software Consortium.
   4 *
   5 * Permission to use, copy, modify, and/or distribute this software for any
   6 * purpose with or without fee is hereby granted, provided that the above
   7 * copyright notice and this permission notice appear in all copies.
   8 *
   9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
  10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11 * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
  12 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  15 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16 *
  17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
  18 *
  19 * Permission to use, copy, modify, and/or distribute this software for any
  20 * purpose with or without fee is hereby granted, provided that the above
  21 * copyright notice and this permission notice appear in all copies.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
  24 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  25 * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
  26 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  28 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  30 */
  31
  32/* $Id: dnssec-signzone.c,v 1.262.110.9 2011/07/19 23:47:12 tbox Exp $ */
  33
  34/*! \file */
  35
  36#include <config.h>
  37
  38#include <stdlib.h>
  39#include <time.h>
  40
  41#include <isc/app.h>
  42#include <isc/base32.h>
  43#include <isc/commandline.h>
  44#include <isc/entropy.h>
  45#include <isc/event.h>
  46#include <isc/file.h>
  47#include <isc/hash.h>
  48#include <isc/hex.h>
  49#include <isc/mem.h>
  50#include <isc/mutex.h>
  51#include <isc/os.h>
  52#include <isc/print.h>
  53#include <isc/random.h>
  54#include <isc/rwlock.h>
  55#include <isc/serial.h>
  56#include <isc/stdio.h>
  57#include <isc/stdlib.h>
  58#include <isc/string.h>
  59#include <isc/task.h>
  60#include <isc/time.h>
  61#include <isc/util.h>
  62
  63#include <dns/db.h>
  64#include <dns/dbiterator.h>
  65#include <dns/diff.h>
  66#include <dns/dnssec.h>
  67#include <dns/ds.h>
  68#include <dns/fixedname.h>
  69#include <dns/keyvalues.h>
  70#include <dns/log.h>
  71#include <dns/master.h>
  72#include <dns/masterdump.h>
  73#include <dns/nsec.h>
  74#include <dns/nsec3.h>
  75#include <dns/rdata.h>
  76#include <dns/rdatalist.h>
  77#include <dns/rdataset.h>
  78#include <dns/rdataclass.h>
  79#include <dns/rdatasetiter.h>
  80#include <dns/rdatastruct.h>
  81#include <dns/rdatatype.h>
  82#include <dns/result.h>
  83#include <dns/soa.h>
  84#include <dns/time.h>
  85
  86#include <dst/dst.h>
  87
  88#include "dnssectool.h"
  89
  90#ifndef PATH_MAX
  91#define PATH_MAX 1024   /* AIX, WIN32, and others don't define this. */
  92#endif
  93
  94const char *program = "dnssec-signzone";
  95int verbose;
  96
  97typedef struct hashlist hashlist_t;
  98
  99static int nsec_datatype = dns_rdatatype_nsec;
 100
 101#define IS_NSEC3	(nsec_datatype == dns_rdatatype_nsec3)
 102#define OPTOUT(x)	(((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
 103
 104#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
 105
 106#define BUFSIZE 2048
 107#define MAXDSKEYS 8
 108
 109#define SIGNER_EVENTCLASS	ISC_EVENTCLASS(0x4453)
 110#define SIGNER_EVENT_WRITE	(SIGNER_EVENTCLASS + 0)
 111#define SIGNER_EVENT_WORK	(SIGNER_EVENTCLASS + 1)
 112
 113#define SOA_SERIAL_KEEP		0
 114#define SOA_SERIAL_INCREMENT	1
 115#define SOA_SERIAL_UNIXTIME	2
 116
 117typedef struct signer_event sevent_t;
 118struct signer_event {
 119	ISC_EVENT_COMMON(sevent_t);
 120	dns_fixedname_t *fname;
 121	dns_dbnode_t *node;
 122};
 123
 124static dns_dnsseckeylist_t keylist;
 125static unsigned int keycount = 0;
 126isc_rwlock_t keylist_lock;
 127static isc_stdtime_t starttime = 0, endtime = 0, now;
 128static int cycle = -1;
 129static int jitter = 0;
 130static isc_boolean_t tryverify = ISC_FALSE;
 131static isc_boolean_t printstats = ISC_FALSE;
 132static isc_mem_t *mctx = NULL;
 133static isc_entropy_t *ectx = NULL;
 134static dns_ttl_t zone_soa_min_ttl;
 135static dns_ttl_t soa_ttl;
 136static FILE *fp;
 137static char *tempfile = NULL;
 138static const dns_master_style_t *masterstyle;
 139static dns_masterformat_t inputformat = dns_masterformat_text;
 140static dns_masterformat_t outputformat = dns_masterformat_text;
 141static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
 142static unsigned int nverified = 0, nverifyfailed = 0;
 143static const char *directory = NULL, *dsdir = NULL;
 144static isc_mutex_t namelock, statslock;
 145static isc_taskmgr_t *taskmgr = NULL;
 146static dns_db_t *gdb;			/* The database */
 147static dns_dbversion_t *gversion;	/* The database version */
 148static dns_dbiterator_t *gdbiter;	/* The database iterator */
 149static dns_rdataclass_t gclass;		/* The class */
 150static dns_name_t *gorigin;		/* The database origin */
 151static int nsec3flags = 0;
 152static dns_iterations_t nsec3iter = 10U;
 153static unsigned char saltbuf[255];
 154static unsigned char *salt = saltbuf;
 155static size_t salt_length = 0;
 156static isc_task_t *master = NULL;
 157static unsigned int ntasks = 0;
 158static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
 159static isc_boolean_t nokeys = ISC_FALSE;
 160static isc_boolean_t removefile = ISC_FALSE;
 161static isc_boolean_t generateds = ISC_FALSE;
 162static isc_boolean_t ignore_kskflag = ISC_FALSE;
 163static isc_boolean_t keyset_kskonly = ISC_FALSE;
 164static dns_name_t *dlv = NULL;
 165static dns_fixedname_t dlv_fixed;
 166static dns_master_style_t *dsstyle = NULL;
 167static unsigned int serialformat = SOA_SERIAL_KEEP;
 168static unsigned int hash_length = 0;
 169static isc_boolean_t unknownalg = ISC_FALSE;
 170static isc_boolean_t disable_zone_check = ISC_FALSE;
 171static isc_boolean_t update_chain = ISC_FALSE;
 172static isc_boolean_t set_keyttl = ISC_FALSE;
 173static dns_ttl_t keyttl;
 174
 175#define INCSTAT(counter)		\
 176	if (printstats) {		\
 177		LOCK(&statslock);	\
 178		counter++;		\
 179		UNLOCK(&statslock);	\
 180	}
 181
 182static void
 183sign(isc_task_t *task, isc_event_t *event);
 184
 185#define check_dns_dbiterator_current(result) \
 186	check_result((result == DNS_R_NEWORIGIN) ? ISC_R_SUCCESS : result, \
 187		     "dns_dbiterator_current()")
 188
 189static void
 190dumpnode(dns_name_t *name, dns_dbnode_t *node) {
 191	isc_result_t result;
 192
 193	if (outputformat != dns_masterformat_text)
 194		return;
 195	result = dns_master_dumpnodetostream(mctx, gdb, gversion, node, name,
 196					     masterstyle, fp);
 197	check_result(result, "dns_master_dumpnodetostream");
 198}
 199
 200/*%
 201 * Sign the given RRset with given key, and add the signature record to the
 202 * given tuple.
 203 */
 204static void
 205signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
 206	    dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
 207{
 208	isc_result_t result;
 209	isc_stdtime_t jendtime;
 210	char keystr[DST_KEY_FORMATSIZE];
 211	dns_rdata_t trdata = DNS_RDATA_INIT;
 212	unsigned char array[BUFSIZE];
 213	isc_buffer_t b;
 214	dns_difftuple_t *tuple;
 215
 216	dst_key_format(key, keystr, sizeof(keystr));
 217	vbprintf(1, "\t%s %s\n", logmsg, keystr);
 218
 219	jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
 220	isc_buffer_init(&b, array, sizeof(array));
 221	result = dns_dnssec_sign(name, rdataset, key, &starttime, &jendtime,
 222				 mctx, &b, &trdata);
 223	isc_entropy_stopcallbacksources(ectx);
 224	if (result != ISC_R_SUCCESS) {
 225		char keystr[DST_KEY_FORMATSIZE];
 226		dst_key_format(key, keystr, sizeof(keystr));
 227		fatal("dnskey '%s' failed to sign data: %s",
 228		      keystr, isc_result_totext(result));
 229	}
 230	INCSTAT(nsigned);
 231
 232	if (tryverify) {
 233		result = dns_dnssec_verify(name, rdataset, key,
 234					   ISC_TRUE, mctx, &trdata);
 235		if (result == ISC_R_SUCCESS) {
 236			vbprintf(3, "\tsignature verified\n");
 237			INCSTAT(nverified);
 238		} else {
 239			vbprintf(3, "\tsignature failed to verify\n");
 240			INCSTAT(nverifyfailed);
 241		}
 242	}
 243
 244	tuple = NULL;
 245	result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name, ttl, &trdata,
 246				      &tuple);
 247	check_result(result, "dns_difftuple_create");
 248	dns_diff_append(add, &tuple);
 249}
 250
 251static inline isc_boolean_t
 252issigningkey(dns_dnsseckey_t *key) {
 253	return (key->force_sign || key->hint_sign);
 254}
 255
 256static inline isc_boolean_t
 257iszonekey(dns_dnsseckey_t *key) {
 258	return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
 259		       dst_key_iszonekey(key->key)));
 260}
 261
 262static inline isc_boolean_t
 263isksk(dns_dnsseckey_t *key) {
 264	return (key->ksk);
 265}
 266
 267static inline isc_boolean_t
 268iszsk(dns_dnsseckey_t *key) {
 269	return (ignore_kskflag || !key->ksk);
 270}
 271
 272/*%
 273 * Find the key that generated an RRSIG, if it is in the key list.  If
 274 * so, return a pointer to it, otherwise return NULL.
 275 *
 276 * No locking is performed here, this must be done by the caller.
 277 */
 278static dns_dnsseckey_t *
 279keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
 280	dns_dnsseckey_t *key;
 281
 282	for (key = ISC_LIST_HEAD(keylist);
 283	     key != NULL;
 284	     key = ISC_LIST_NEXT(key, link)) {
 285		if (rrsig->keyid == dst_key_id(key->key) &&
 286		    rrsig->algorithm == dst_key_alg(key->key) &&
 287		    dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
 288			return (key);
 289	}
 290	return (NULL);
 291}
 292
 293/*%
 294 * Finds the key that generated a RRSIG, if possible.  First look at the keys
 295 * that we've loaded already, and then see if there's a key on disk.
 296 */
 297static dns_dnsseckey_t *
 298keythatsigned(dns_rdata_rrsig_t *rrsig) {
 299	isc_result_t result;
 300	dst_key_t *pubkey = NULL, *privkey = NULL;
 301	dns_dnsseckey_t *key = NULL;
 302
 303	isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
 304	key = keythatsigned_unlocked(rrsig);
 305	isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_read);
 306	if (key != NULL)
 307		return (key);
 308
 309	/*
 310	 * We did not find the key in our list.  Get a write lock now, since
 311	 * we may be modifying the bits.  We could do the tryupgrade() dance,
 312	 * but instead just get a write lock and check once again to see if
 313	 * it is on our list.  It's possible someone else may have added it
 314	 * after all.
 315	 */
 316	isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
 317	key = keythatsigned_unlocked(rrsig);
 318	if (key != NULL) {
 319		isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
 320		return (key);
 321	}
 322
 323	result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
 324				  rrsig->algorithm, DST_TYPE_PUBLIC,
 325				  directory, mctx, &pubkey);
 326	if (result != ISC_R_SUCCESS) {
 327		isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
 328		return (NULL);
 329	}
 330
 331	result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
 332				  rrsig->algorithm,
 333				  DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
 334				  directory, mctx, &privkey);
 335	if (result == ISC_R_SUCCESS) {
 336		dst_key_free(&pubkey);
 337		dns_dnsseckey_create(mctx, &privkey, &key);
 338	} else {
 339		dns_dnsseckey_create(mctx, &pubkey, &key);
 340	}
 341	key->force_publish = ISC_FALSE;
 342	key->force_sign = ISC_FALSE;
 343	ISC_LIST_APPEND(keylist, key, link);
 344
 345	isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
 346	return (key);
 347}
 348
 349/*%
 350 * Check to see if we expect to find a key at this name.  If we see a RRSIG
 351 * and can't find the signing key that we expect to find, we drop the rrsig.
 352 * I'm not sure if this is completely correct, but it seems to work.
 353 */
 354static isc_boolean_t
 355expecttofindkey(dns_name_t *name) {
 356	unsigned int options = DNS_DBFIND_NOWILD;
 357	dns_fixedname_t fname;
 358	isc_result_t result;
 359	char namestr[DNS_NAME_FORMATSIZE];
 360
 361	dns_fixedname_init(&fname);
 362	result = dns_db_find(gdb, name, gversion, dns_rdatatype_dnskey, options,
 363			     0, NULL, dns_fixedname_name(&fname), NULL, NULL);
 364	switch (result) {
 365	case ISC_R_SUCCESS:
 366	case DNS_R_NXDOMAIN:
 367	case DNS_R_NXRRSET:
 368		return (ISC_TRUE);
 369	case DNS_R_DELEGATION:
 370	case DNS_R_CNAME:
 371	case DNS_R_DNAME:
 372		return (ISC_FALSE);
 373	}
 374	dns_name_format(name, namestr, sizeof(namestr));
 375	fatal("failure looking for '%s DNSKEY' in database: %s",
 376	      namestr, isc_result_totext(result));
 377	/* NOTREACHED */
 378	return (ISC_FALSE); /* removes a warning */
 379}
 380
 381static inline isc_boolean_t
 382setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
 383	    dns_rdata_t *rrsig)
 384{
 385	isc_result_t result;
 386	result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
 387	if (result == ISC_R_SUCCESS) {
 388		INCSTAT(nverified);
 389		return (ISC_TRUE);
 390	} else {
 391		INCSTAT(nverifyfailed);
 392		return (ISC_FALSE);
 393	}
 394}
 395
 396/*%
 397 * Signs a set.  Goes through contortions to decide if each RRSIG should
 398 * be dropped or retained, and then determines if any new SIGs need to
 399 * be generated.
 400 */
 401static void
 402signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
 403	dns_rdataset_t *set)
 404{
 405	dns_rdataset_t sigset;
 406	dns_rdata_t sigrdata = DNS_RDATA_INIT;
 407	dns_rdata_rrsig_t rrsig;
 408	dns_dnsseckey_t *key;
 409	isc_result_t result;
 410	isc_boolean_t nosigs = ISC_FALSE;
 411	isc_boolean_t *wassignedby, *nowsignedby;
 412	int arraysize;
 413	dns_difftuple_t *tuple;
 414	dns_ttl_t ttl;
 415	int i;
 416	char namestr[DNS_NAME_FORMATSIZE];
 417	char typestr[TYPE_FORMATSIZE];
 418	char sigstr[SIG_FORMATSIZE];
 419
 420	dns_name_format(name, namestr, sizeof(namestr));
 421	type_format(set->type, typestr, sizeof(typestr));
 422
 423	ttl = ISC_MIN(set->ttl, endtime - starttime);
 424
 425	dns_rdataset_init(&sigset);
 426	result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_rrsig,
 427				     set->type, 0, &sigset, NULL);
 428	if (result == ISC_R_NOTFOUND) {
 429		result = ISC_R_SUCCESS;
 430		nosigs = ISC_TRUE;
 431	}
 432	if (result != ISC_R_SUCCESS)
 433		fatal("failed while looking for '%s RRSIG %s': %s",
 434		      namestr, typestr, isc_result_totext(result));
 435
 436	vbprintf(1, "%s/%s:\n", namestr, typestr);
 437
 438	arraysize = keycount;
 439	if (!nosigs)
 440		arraysize += dns_rdataset_count(&sigset);
 441	wassignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
 442	nowsignedby = isc_mem_get(mctx, arraysize * sizeof(isc_boolean_t));
 443	if (wassignedby == NULL || nowsignedby == NULL)
 444		fatal("out of memory");
 445
 446	for (i = 0; i < arraysize; i++)
 447		wassignedby[i] = nowsignedby[i] = ISC_FALSE;
 448
 449	if (nosigs)
 450		result = ISC_R_NOMORE;
 451	else
 452		result = dns_rdataset_first(&sigset);
 453
 454	while (result == ISC_R_SUCCESS) {
 455		isc_boolean_t expired, future;
 456		isc_boolean_t keep = ISC_FALSE, resign = ISC_FALSE;
 457
 458		dns_rdataset_current(&sigset, &sigrdata);
 459
 460		result = dns_rdata_tostruct(&sigrdata, &rrsig, NULL);
 461		check_result(result, "dns_rdata_tostruct");
 462
 463		future = isc_serial_lt(now, rrsig.timesigned);
 464
 465		key = keythatsigned(&rrsig);
 466		sig_format(&rrsig, sigstr, sizeof(sigstr));
 467		if (key != NULL && issigningkey(key))
 468			expired = isc_serial_gt(now + cycle, rrsig.timeexpire);
 469		else
 470			expired = isc_serial_gt(now, rrsig.timeexpire);
 471
 472		if (isc_serial_gt(rrsig.timesigned, rrsig.timeexpire)) {
 473			/* rrsig is dropped and not replaced */
 474			vbprintf(2, "\trrsig by %s dropped - "
 475				 "invalid validity period\n",
 476				 sigstr);
 477		} else if (key == NULL && !future &&
 478			   expecttofindkey(&rrsig.signer)) {
 479			/* rrsig is dropped and not replaced */
 480			vbprintf(2, "\trrsig by %s dropped - "
 481				 "private dnskey not found\n",
 482				 sigstr);
 483		} else if (key == NULL || future) {
 484			vbprintf(2, "\trrsig by %s %s - dnskey not found\n",
 485				 expired ? "retained" : "dropped", sigstr);
 486			if (!expired)
 487				keep = ISC_TRUE;
 488		} else if (issigningkey(key)) {
 489			if (!expired && rrsig.originalttl == set->ttl &&
 490			    setverifies(name, set, key->key, &sigrdata)) {
 491				vbprintf(2, "\trrsig by %s retained\n", sigstr);
 492				keep = ISC_TRUE;
 493				wassignedby[key->index] = ISC_TRUE;
 494				nowsignedby[key->index] = ISC_TRUE;
 495			} else {
 496				vbprintf(2, "\trrsig by %s dropped - %s\n",
 497					 sigstr, expired ? "expired" :
 498					 rrsig.originalttl != set->ttl ?
 499					 "ttl change" : "failed to verify");
 500				wassignedby[key->index] = ISC_TRUE;
 501				resign = ISC_TRUE;
 502			}
 503		} else if (iszonekey(key)) {
 504			if (!expired && rrsig.originalttl == set->ttl &&
 505			    setverifies(name, set, key->key, &sigrdata)) {
 506				vbprintf(2, "\trrsig by %s retained\n", sigstr);
 507				keep = ISC_TRUE;
 508				wassignedby[key->index] = ISC_TRUE;
 509				nowsignedby[key->index] = ISC_TRUE;
 510			} else {
 511				vbprintf(2, "\trrsig by %s dropped - %s\n",
 512					 sigstr, expired ? "expired" :
 513					 rrsig.originalttl != set->ttl ?
 514					 "ttl change" : "failed to verify");
 515				wassignedby[key->index] = ISC_TRUE;
 516			}
 517		} else if (!expired) {
 518			vbprintf(2, "\trrsig by %s retained\n", sigstr);
 519			keep = ISC_TRUE;
 520		} else {
 521			vbprintf(2, "\trrsig by %s expired\n", sigstr);
 522		}
 523
 524		if (keep) {
 525			if (key != NULL)
 526				nowsignedby[key->index] = ISC_TRUE;
 527			INCSTAT(nretained);
 528			if (sigset.ttl != ttl) {
 529				vbprintf(2, "\tfixing ttl %s\n", sigstr);
 530				tuple = NULL;
 531				result = dns_difftuple_create(mctx,
 532							      DNS_DIFFOP_DEL,
 533							      name, sigset.ttl,
 534							      &sigrdata,
 535							      &tuple);
 536				check_result(result, "dns_difftuple_create");
 537				dns_diff_append(del, &tuple);
 538				result = dns_difftuple_create(mctx,
 539							      DNS_DIFFOP_ADD,
 540							      name, ttl,
 541							      &sigrdata,
 542							      &tuple);
 543				check_result(result, "dns_difftuple_create");
 544				dns_diff_append(add, &tuple);
 545			}
 546		} else {
 547			tuple = NULL;
 548			result = dns_difftuple_create(mctx, DNS_DIFFOP_DEL,
 549						      name, sigset.ttl,
 550						      &sigrdata, &tuple);
 551			check_result(result, "dns_difftuple_create");
 552			dns_diff_append(del, &tuple);
 553			INCSTAT(ndropped);
 554		}
 555
 556		if (resign) {
 557			INSIST(!keep);
 558
 559			signwithkey(name, set, key->key, ttl, add,
 560				    "resigning with dnskey");
 561			nowsignedby[key->index] = ISC_TRUE;
 562		}
 563
 564		dns_rdata_reset(&sigrdata);
 565		dns_rdata_freestruct(&rrsig);
 566		result = dns_rdataset_next(&sigset);
 567	}
 568	if (result == ISC_R_NOMORE)
 569		result = ISC_R_SUCCESS;
 570
 571	check_result(result, "dns_rdataset_first/next");
 572	if (dns_rdataset_isassociated(&sigset))
 573		dns_rdataset_disassociate(&sigset);
 574
 575	for (key = ISC_LIST_HEAD(keylist);
 576	     key != NULL;
 577	     key = ISC_LIST_NEXT(key, link))
 578	{
 579		if (nowsignedby[key->index])
 580			continue;
 581
 582		if (!issigningkey(key))
 583			continue;
 584
 585		if (set->type == dns_rdatatype_dnskey &&
 586		     dns_name_equal(name, gorigin)) {
 587			isc_boolean_t have_ksk;
 588			dns_dnsseckey_t *tmpkey;
 589
 590			have_ksk = isksk(key);
 591			for (tmpkey = ISC_LIST_HEAD(keylist);
 592			     tmpkey != NULL;
 593			     tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
 594				if (dst_key_alg(key->key) !=
 595				    dst_key_alg(tmpkey->key))
 596					continue;
 597				if (REVOKE(tmpkey->key))
 598					continue;
 599				if (isksk(tmpkey))
 600					have_ksk = ISC_TRUE;
 601			}
 602			if (isksk(key) || !have_ksk ||
 603			    (iszsk(key) && !keyset_kskonly))
 604				signwithkey(name, set, key->key, ttl, add,
 605					    "signing with dnskey");
 606		} else if (iszsk(key)) {
 607			signwithkey(name, set, key->key, ttl, add,
 608				    "signing with dnskey");
 609		}
 610	}
 611
 612	isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
 613	isc_mem_put(mctx, nowsignedby, arraysize * sizeof(isc_boolean_t));
 614}
 615
 616struct hashlist {
 617	unsigned char *hashbuf;
 618	size_t entries;
 619	size_t size;
 620	size_t length;
 621};
 622
 623static void
 624hashlist_init(hashlist_t *l, unsigned int nodes, unsigned int length) {
 625
 626	l->entries = 0;
 627	l->length = length + 1;
 628
 629	if (nodes != 0) {
 630		l->size = nodes;
 631		l->hashbuf = malloc(l->size * l->length);
 632		if (l->hashbuf == NULL)
 633			l->size = 0;
 634	} else {
 635		l->size = 0;
 636		l->hashbuf = NULL;
 637	}
 638}
 639
 640static void
 641hashlist_add(hashlist_t *l, const unsigned char *hash, size_t len)
 642{
 643
 644	REQUIRE(len <= l->length);
 645
 646	if (l->entries == l->size) {
 647		l->size = l->size * 2 + 100;
 648		l->hashbuf = realloc(l->hashbuf, l->size * l->length);
 649	}
 650	memset(l->hashbuf + l->entries * l->length, 0, l->length);
 651	memcpy(l->hashbuf + l->entries * l->length, hash, len);
 652	l->entries++;
 653}
 654
 655static void
 656hashlist_add_dns_name(hashlist_t *l, /*const*/ dns_name_t *name,
 657		      unsigned int hashalg, unsigned int iterations,
 658		      const unsigned char *salt, size_t salt_length,
 659		      isc_boolean_t speculative)
 660{
 661	char nametext[DNS_NAME_FORMATSIZE];
 662	unsigned char hash[NSEC3_MAX_HASH_LENGTH + 1];
 663	unsigned int len;
 664	size_t i;
 665
 666	len = isc_iterated_hash(hash, hashalg, iterations, salt, salt_length,
 667				name->ndata, name->length);
 668	if (verbose) {
 669		dns_name_format(name, nametext, sizeof nametext);
 670		for (i = 0 ; i < len; i++)
 671			fprintf(stderr, "%02x", hash[i]);
 672		fprintf(stderr, " %s\n", nametext);
 673	}
 674	hash[len++] = speculative ? 1 : 0;
 675	hashlist_add(l, hash, len);
 676}
 677
 678static int
 679hashlist_comp(const void *a, const void *b) {
 680	return (memcmp(a, b, hash_length + 1));
 681}
 682
 683static void
 684hashlist_sort(hashlist_t *l) {
 685	qsort(l->hashbuf, l->entries, l->length, hashlist_comp);
 686}
 687
 688static isc_boolean_t
 689hashlist_hasdup(hashlist_t *l) {
 690	unsigned char *current;
 691	unsigned char *next = l->hashbuf;
 692	size_t entries = l->entries;
 693
 694	/*
 695	 * Skip initial speculative wild card hashs.
 696	 */
 697	while (entries > 0U && next[l->length-1] != 0U) {
 698		next += l->length;
 699		entries--;
 700	}
 701
 702	current = next;
 703	while (entries-- > 1U) {
 704		next += l->length;
 705		if (next[l->length-1] != 0)
 706			continue;
 707		if (memcmp(current, next, l->length - 1) == 0)
 708			return (ISC_TRUE);
 709		current = next;
 710	}
 711	return (ISC_FALSE);
 712}
 713
 714static const unsigned char *
 715hashlist_findnext(const hashlist_t *l,
 716		  const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
 717{
 718	unsigned int entries = l->entries;
 719	const unsigned char *next = bsearch(hash, l->hashbuf, l->entries,
 720					    l->length, hashlist_comp);
 721	INSIST(next != NULL);
 722
 723	do {
 724		if (next < l->hashbuf + (l->entries - 1) * l->length)
 725			next += l->length;
 726		else
 727			next = l->hashbuf;
 728		if (next[l->length - 1] == 0)
 729			break;
 730	} while (entries-- > 1);
 731	INSIST(entries != 0);
 732	return (next);
 733}
 734
 735static isc_boolean_t
 736hashlist_exists(const hashlist_t *l,
 737		const unsigned char hash[NSEC3_MAX_HASH_LENGTH])
 738{
 739	if (bsearch(hash, l->hashbuf, l->entries, l->length, hashlist_comp))
 740		return (ISC_TRUE);
 741	else
 742		return (ISC_FALSE);
 743}
 744
 745static void
 746addnowildcardhash(hashlist_t *l, /*const*/ dns_name_t *name,
 747		  unsigned int hashalg, unsigned int iterations,
 748		  const unsigned char *salt, size_t salt_length)
 749{
 750	dns_fixedname_t fixed;
 751	dns_name_t *wild;
 752	dns_dbnode_t *node = NULL;
 753	isc_result_t result;
 754	char namestr[DNS_NAME_FORMATSIZE];
 755
 756	dns_fixedname_init(&fixed);
 757	wild = dns_fixedname_name(&fixed);
 758
 759	result = dns_name_concatenate(dns_wildcardname, name, wild, NULL);
 760	if (result == ISC_R_NOSPACE)
 761		return;
 762	check_result(result,"addnowildcardhash: dns_name_concatenate()");
 763
 764	result = dns_db_findnode(gdb, wild, ISC_FALSE, &node);
 765	if (result == ISC_R_SUCCESS) {
 766		dns_db_detachnode(gdb, &node);
 767		return;
 768	}
 769
 770	if (verbose) {
 771		dns_name_format(wild, namestr, sizeof(namestr));
 772		fprintf(stderr, "adding no-wildcardhash for %s\n", namestr);
 773	}
 774
 775	hashlist_add_dns_name(l, wild, hashalg, iterations, salt, salt_length,
 776			      ISC_TRUE);
 777}
 778
 779static void
 780opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
 781       dns_db_t **dbp)
 782{
 783	char filename[PATH_MAX];
 784	isc_buffer_t b;
 785	isc_result_t result;
 786
 787	isc_buffer_init(&b, filename, sizeof(filename));
 788	if (dsdir != NULL) {
 789		/* allow room for a trailing slash */
 790		if (strlen(dsdir) >= isc_buffer_availablelength(&b))
 791			fatal("path '%s' is too long", dsdir);
 792		isc_buffer_putstr(&b, dsdir);
 793		if (dsdir[strlen(dsdir) - 1] != '/')
 794			isc_buffer_putstr(&b, "/");
 795	}
 796	if (strlen(prefix) > isc_buffer_availablelength(&b))
 797		fatal("path '%s' is too long", dsdir);
 798	isc_buffer_putstr(&b, prefix);
 799	result = dns_name_tofilenametext(name, ISC_FALSE, &b);
 800	check_result(result, "dns_name_tofilenametext()");
 801	if (isc_buffer_availablelength(&b) == 0) {
 802		char namestr[DNS_NAME_FORMATSIZE];
 803		dns_name_format(name, namestr, sizeof(namestr));
 804		fatal("name '%s' is too long", namestr);
 805	}
 806	isc_buffer_putuint8(&b, 0);
 807
 808	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
 809			       rdclass, 0, NULL, dbp);
 810	check_result(result, "dns_db_create()");
 811
 812	result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
 813	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
 814		dns_db_detach(dbp);
 815}
 816
 817/*%
 818 * Load the DS set for a child zone, if a dsset-* file can be found.
 819 * If not, try to find a keyset-* file from an earlier version of
 820 * dnssec-signzone, and build DS records from that.
 821 */
 822static isc_result_t
 823loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
 824	dns_db_t *db = NULL;
 825	dns_dbversion_t *ver = NULL;
 826	dns_dbnode_t *node = NULL;
 827	isc_result_t result;
 828	dns_rdataset_t keyset;
 829	dns_rdata_t key, ds;
 830	unsigned char dsbuf[DNS_DS_BUFFERSIZE];
 831	dns_diff_t diff;
 832	dns_difftuple_t *tuple = NULL;
 833
 834	opendb("dsset-", name, gclass, &db);
 835	if (db != NULL) {
 836		result = dns_db_findnode(db, name, ISC_FALSE, &node);
 837		if (result == ISC_R_SUCCESS) {
 838			dns_rdataset_init(dsset);
 839			result = dns_db_findrdataset(db, node, NULL,
 840						     dns_rdatatype_ds, 0, 0,
 841						     dsset, NULL);
 842			dns_db_detachnode(db, &node);
 843			if (result == ISC_R_SUCCESS) {
 844				vbprintf(2, "found DS records\n");
 845				dsset->ttl = ttl;
 846				dns_db_detach(&db);
 847				return (result);
 848			}
 849		}
 850		dns_db_detach(&db);
 851	}
 852
 853	/* No DS records found; try again, looking for DNSKEY records */
 854	opendb("keyset-", name, gclass, &db);
 855	if (db == NULL) {
 856		return (ISC_R_NOTFOUND);
 857	}
 858
 859	result = dns_db_findnode(db, name, ISC_FALSE, &node);
 860	if (result != ISC_R_SUCCESS) {
 861		dns_db_detach(&db);
 862		return (result);
 863	}
 864
 865	dns_rdataset_init(&keyset);
 866	result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
 867				     &keyset, NULL);
 868	if (result != ISC_R_SUCCESS) {
 869		dns_db_detachnode(db, &node);
 870		dns_db_detach(&db);
 871		return (result);
 872	}
 873	vbprintf(2, "found DNSKEY records\n");
 874
 875	result = dns_db_newversion(db, &ver);
 876	check_result(result, "dns_db_newversion");
 877	dns_diff_init(mctx, &diff);
 878
 879	for (result = dns_rdataset_first(&keyset);
 880	     result == ISC_R_SUCCESS;
 881	     result = dns_rdataset_next(&keyset))
 882	{
 883		dns_rdata_init(&key);
 884		dns_rdata_init(&ds);
 885		dns_rdataset_current(&keyset, &key);
 886		result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA1,
 887					   dsbuf, &ds);
 888		check_result(result, "dns_ds_buildrdata");
 889
 890		result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
 891					      ttl, &ds, &tuple);
 892		check_result(result, "dns_difftuple_create");
 893		dns_diff_append(&diff, &tuple);
 894
 895		dns_rdata_reset(&ds);
 896		result = dns_ds_buildrdata(name, &key, DNS_DSDIGEST_SHA256,
 897					   dsbuf, &ds);
 898		check_result(result, "dns_ds_buildrdata");
 899
 900		result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD, name,
 901					      ttl, &ds, &tuple);
 902		check_result(result, "dns_difftuple_create");
 903		dns_diff_append(&diff, &tuple);
 904	}
 905
 906	result = dns_diff_apply(&diff, db, ver);
 907	check_result(result, "dns_diff_apply");
 908	dns_diff_clear(&diff);
 909
 910	dns_db_closeversion(db, &ver, ISC_TRUE);
 911
 912	result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds, 0, 0,
 913				     dsset, NULL);
 914	check_result(result, "dns_db_findrdataset");
 915
 916	dns_rdataset_disassociate(&keyset);
 917	dns_db_detachnode(db, &node);
 918	dns_db_detach(&db);
 919	return (result);
 920}
 921
 922static isc_boolean_t
 923delegation(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t *ttlp) {
 924	dns_rdataset_t nsset;
 925	isc_result_t result;
 926
 927	if (dns_name_equal(name, gorigin))
 928		return (ISC_FALSE);
 929
 930	dns_rdataset_init(&nsset);
 931	result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ns,
 932				     0, 0, &nsset, NULL);
 933	if (dns_rdataset_isassociated(&nsset)) {
 934		if (ttlp != NULL)
 935			*ttlp = nsset.ttl;
 936		dns_rdataset_disassociate(&nsset);
 937	}
 938
 939	return (ISC_TF(result == ISC_R_SUCCESS));
 940}
 941
 942static isc_boolean_t
 943secure(dns_name_t *name, dns_dbnode_t *node) {
 944	dns_rdataset_t dsset;
 945	isc_result_t result;
 946
 947	if (dns_name_equal(name, gorigin))
 948		return (ISC_FALSE);
 949
 950	dns_rdataset_init(&dsset);
 951	result = dns_db_findrdataset(gdb, node, gversion, dns_rdatatype_ds,
 952				     0, 0, &dsset, NULL);
 953	if (dns_rdataset_isassociated(&dsset))
 954		dns_rdataset_disassociate(&dsset);
 955
 956	return (ISC_TF(result == ISC_R_SUCCESS));
 957}
 958
 959/*%
 960 * Signs all records at a name.
 961 */
 962static void
 963signname(dns_dbnode_t *node, dns_name_t *name) {
 964	isc_result_t result;
 965	dns_rdataset_t rdataset;
 966	dns_rdatasetiter_t *rdsiter;
 967	isc_boolean_t isdelegation = ISC_FALSE;
 968	dns_diff_t del, add;
 969	char namestr[DNS_NAME_FORMATSIZE];
 970
 971	dns_rdataset_init(&rdataset);
 972	dns_name_format(name, namestr, sizeof(namestr));
 973
 974	/*
 975	 * Determine if this is a delegation point.
 976	 */
 977	if (delegation(name, node, NULL))
 978		isdelegation = ISC_TRUE;
 979
 980	/*
 981	 * Now iterate through the rdatasets.
 982	 */
 983	dns_diff_init(mctx, &del);
 984	dns_diff_init(mctx, &add);
 985	rdsiter = NULL;
 986	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
 987	check_result(result, "dns_db_allrdatasets()");
 988	result = dns_rdatasetiter_first(rdsiter);
 989	while (result == ISC_R_SUCCESS) {
 990		dns_rdatasetiter_current(rdsiter, &rdataset);
 991
 992		/* If this is a RRSIG set, skip it. */
 993		if (rdataset.type == dns_rdatatype_rrsig)
 994			goto skip;
 995
 996		/*
 997		 * If this name is a delegation point, skip all records
 998		 * except NSEC and DS sets.  Otherwise check that there
 999		 * isn't a DS record.
1000		 */
1001		if (isdelegation) {
1002			if (rdataset.type != nsec_datatype &&
1003			    rdataset.type != dns_rdatatype_ds)
1004				goto skip;
1005		} else if (rdataset.type == dns_rdatatype_ds) {
1006			char namebuf[DNS_NAME_FORMATSIZE];
1007			dns_name_format(name, namebuf, sizeof(namebuf));
1008			fatal("'%s': found DS RRset without NS RRset\n",
1009			      namebuf);
1010		}
1011
1012		signset(&del, &add, node, name, &rdataset);
1013
1014 skip:
1015		dns_rdataset_disassociate(&rdataset);
1016		result = dns_rdatasetiter_next(rdsiter);
1017	}
1018	if (result != ISC_R_NOMORE)
1019		fatal("rdataset iteration for name '%s' failed: %s",
1020		      namestr, isc_result_totext(result));
1021
1022	dns_rdatasetiter_destroy(&rdsiter);
1023
1024	result = dns_diff_applysilently(&del, gdb, gversion);
1025	if (result != ISC_R_SUCCESS)
1026		fatal("failed to delete SIGs at node '%s': %s",
1027		      namestr, isc_result_totext(result));
1028
1029	result = dns_diff_applysilently(&add, gdb, gversion);
1030	if (result != ISC_R_SUCCESS)
1031		fatal("failed to add SIGs at node '%s': %s",
1032		      namestr, isc_result_totext(result));
1033
1034	dns_diff_clear(&del);
1035	dns_diff_clear(&add);
1036}
1037
1038static inline isc_boolean_t
1039active_node(dns_dbnode_t *node) {
1040	dns_rdatasetiter_t *rdsiter = NULL;
1041	dns_rdatasetiter_t *rdsiter2 = NULL;
1042	isc_boolean_t active = ISC_FALSE;
1043	isc_result_t result;
1044	dns_rdataset_t rdataset;
1045	dns_rdatatype_t type;
1046	dns_rdatatype_t covers;
1047	isc_boolean_t found;
1048
1049	dns_rdataset_init(&rdataset);
1050	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1051	check_result(result, "dns_db_allrdatasets()");
1052	result = dns_rdatasetiter_first(rdsiter);
1053	while (result == ISC_R_SUCCESS) {
1054		dns_rdatasetiter_current(rdsiter, &rdataset);
1055		if (rdataset.type != dns_rdatatype_nsec &&
1056		    rdataset.type != dns_rdatatype_nsec3 &&
1057		    rdataset.type != dns_rdatatype_rrsig)
1058			active = ISC_TRUE;
1059		dns_rdataset_disassociate(&rdataset);
1060		if (!active)
1061			result = dns_rdatasetiter_next(rdsiter);
1062		else
1063			result = ISC_R_NOMORE;
1064	}
1065	if (result != ISC_R_NOMORE)
1066		fatal("rdataset iteration failed: %s",
1067		      isc_result_totext(result));
1068
1069	if (!active && nsec_datatype == dns_rdatatype_nsec) {
1070		/*%
1071		 * The node is empty of everything but NSEC / RRSIG records.
1072		 */
1073		for (result = dns_rdatasetiter_first(rdsiter);
1074		     result == ISC_R_SUCCESS;
1075		     result = dns_rdatasetiter_next(rdsiter)) {
1076			dns_rdatasetiter_current(rdsiter, &rdataset);
1077			result = dns_db_deleterdataset(gdb, node, gversion,
1078						       rdataset.type,
1079						       rdataset.covers);
1080			check_result(result, "dns_db_deleterdataset()");
1081			dns_rdataset_disassociate(&rdataset);
1082		}
1083		if (result != ISC_R_NOMORE)
1084			fatal("rdataset iteration failed: %s",
1085			      isc_result_totext(result));
1086	} else {
1087		/*
1088		 * Delete RRSIGs for types that no longer exist.
1089		 */
1090		result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter2);
1091		check_result(result, "dns_db_allrdatasets()");
1092		for (result = dns_rdatasetiter_first(rdsiter);
1093		     result == ISC_R_SUCCESS;
1094		     result = dns_rdatasetiter_next(rdsiter)) {
1095			dns_rdatasetiter_current(rdsiter, &rdataset);
1096			type = rdataset.type;
1097			covers = rdataset.covers;
1098			dns_rdataset_disassociate(&rdataset);
1099			/*
1100			 * Delete the NSEC chain if we are signing with
1101			 * NSEC3.
1102			 */
1103			if (nsec_datatype == dns_rdatatype_nsec3 &&
1104			    (type == dns_rdatatype_nsec ||
1105			     covers == dns_rdatatype_nsec)) {
1106				result = dns_db_deleterdataset(gdb, node,
1107							       gversion, type,
1108							       covers);
1109				check_result(result,
1110					   "dns_db_deleterdataset(nsec/rrsig)");
1111				continue;
1112			}
1113			if (type != dns_rdatatype_rrsig)
1114				continue;
1115			found = ISC_FALSE;
1116			for (result = dns_rdatasetiter_first(rdsiter2);
1117			     !found && result == ISC_R_SUCCESS;
1118			     result = dns_rdatasetiter_next(rdsiter2)) {
1119				dns_rdatasetiter_current(rdsiter2, &rdataset);
1120				if (rdataset.type == covers)
1121					found = ISC_TRUE;
1122				dns_rdataset_disassociate(&rdataset);
1123			}
1124			if (!found) {
1125				if (result != ISC_R_NOMORE)
1126					fatal("rdataset iteration failed: %s",
1127					      isc_result_totext(result));
1128				result = dns_db_deleterdataset(gdb, node,
1129							       gversion, type,
1130							       covers);
1131				check_result(result,
1132					     "dns_db_deleterdataset(rrsig)");
1133			} else if (result != ISC_R_NOMORE &&
1134				   result != ISC_R_SUCCESS)
1135				fatal("rdataset iteration failed: %s",
1136				      isc_result_totext(result));
1137		}
1138		if (result != ISC_R_NOMORE)
1139			fatal("rdataset iteration failed: %s",
1140			      isc_result_totext(result));
1141		dns_rdatasetiter_destroy(&rdsiter2);
1142	}
1143	dns_rdatasetiter_destroy(&rdsiter);
1144
1145	return (active);
1146}
1147
1148/*%
1149 * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
1150 */
1151static void
1152get_soa_ttls(void) {
1153	dns_rdataset_t soaset;
1154	dns_fixedname_t fname;
1155	dns_name_t *name;
1156	isc_result_t result;
1157	dns_rdata_t rdata = DNS_RDATA_INIT;
1158
1159	dns_fixedname_init(&fname);
1160	name = dns_fixedname_name(&fname);
1161	dns_rdataset_init(&soaset);
1162	result = dns_db_find(gdb, gorigin, gversion, dns_rdatatype_soa,
1163			     0, 0, NULL, name, &soaset, NULL);
1164	if (result != ISC_R_SUCCESS)
1165		fatal("failed to find an SOA at the zone apex: %s",
1166		      isc_result_totext(result));
1167
1168	result = dns_rdataset_first(&soaset);
1169	check_result(result, "dns_rdataset_first");
1170	dns_rdataset_current(&soaset, &rdata);
1171	zone_soa_min_ttl = dns_soa_getminimum(&rdata);
1172	soa_ttl = soaset.ttl;
1173	dns_rdataset_disassociate(&soaset);
1174}
1175
1176/*%
1177 * Increment (or set if nonzero) the SOA serial
1178 */
1179static isc_result_t
1180setsoaserial(isc_uint32_t serial) {
1181	isc_result_t result;
1182	dns_dbnode_t *node = NULL;
1183	dns_rdataset_t rdataset;
1184	dns_rdata_t rdata = DNS_RDATA_INIT;
1185	isc_uint32_t old_serial, new_serial;
1186
1187	result = dns_db_getoriginnode(gdb, &node);
1188	if (result != ISC_R_SUCCESS)
1189		return result;
1190
1191	dns_rdataset_init(&rdataset);
1192
1193	result = dns_db_findrdataset(gdb, node, gversion,
1194				     dns_rdatatype_soa, 0,
1195				     0, &rdataset, NULL);
1196	if (result != ISC_R_SUCCESS)
1197		goto cleanup;
1198
1199	result = dns_rdataset_first(&rdataset);
1200	RUNTIME_CHECK(result == ISC_R_SUCCESS);
1201
1202	dns_rdataset_current(&rdataset, &rdata);
1203
1204	old_serial = dns_soa_getserial(&rdata);
1205
1206	if (serial) {
1207		/* Set SOA serial to the value provided. */
1208		new_serial = serial;
1209	} else {
1210		/* Increment SOA serial using RFC 1982 arithmetics */
1211		new_serial = (old_serial + 1) & 0xFFFFFFFF;
1212		if (new_serial == 0)
1213			new_serial = 1;
1214	}
1215
1216	/* If the new serial is not likely to cause a zone transfer
1217	 * (a/ixfr) from servers having the old serial, warn the user.
1218	 *
1219	 * RFC1982 section 7 defines the maximum increment to be
1220	 * (2^(32-1))-1.  Using u_int32_t arithmetic, we can do a single
1221	 * comparison.  (5 - 6 == (2^32)-1, not negative-one)
1222	 */
1223	if (new_serial == old_serial ||
1224	    (new_serial - old_serial) > 0x7fffffffU)
1225		fprintf(stderr, "%s: warning: Serial number not advanced, "
1226			"zone may not transfer\n", program);
1227
1228	dns_soa_setserial(new_serial, &rdata);
1229
1230	result = dns_db_deleterdataset(gdb, node, gversion,
1231				       dns_rdatatype_soa, 0);
1232	check_result(result, "dns_db_deleterdataset");
1233	if (result != ISC_R_SUCCESS)
1234		goto cleanup;
1235
1236	result = dns_db_addrdataset(gdb, node, gversion,
1237				    0, &rdataset, 0, NULL);
1238	check_result(result, "dns_db_addrdataset");
1239	if (result != ISC_R_SUCCESS)
1240		goto cleanup;
1241
1242cleanup:
1243	dns_rdataset_disassociate(&rdataset);
1244	if (node != NULL)
1245		dns_db_detachnode(gdb, &node);
1246	dns_rdata_reset(&rdata);
1247
1248	return (result);
1249}
1250
1251/*%
1252 * Delete any RRSIG records at a node.
1253 */
1254static void
1255cleannode(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) {
1256	dns_rdatasetiter_t *rdsiter = NULL;
1257	dns_rdataset_t set;
1258	isc_result_t result, dresult;
1259
1260	if (outputformat != dns_masterformat_text || !disable_zone_check)
1261		return;
1262
1263	dns_rdataset_init(&set);
1264	result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
1265	check_result(result, "dns_db_allrdatasets");
1266	result = dns_rdatasetiter_first(rdsiter);
1267	while (result == ISC_R_SUCCESS) {
1268		isc_boolean_t destroy = ISC_FALSE;
1269		dns_rdatatype_t covers = 0;
1270		dns_rdatasetiter_current(rdsiter, &set);
1271		if (set.type == dns_rdatatype_rrsig) {
1272			covers = set.covers;
1273			destroy = ISC_TRUE;
1274		}
1275		dns_rdataset_disassociate(&set);
1276		result = dns_rdatasetiter_next(rdsiter);
1277		if (destroy) {
1278			dresult = dns_db_deleterdataset(db, node, version,
1279							dns_rdatatype_rrsig,
1280							covers);
1281			check_result(dresult, "dns_db_deleterdataset");
1282		}
1283	}
1284	if (result != ISC_R_NOMORE)
1285		fatal("rdataset iteration failed: %s",
1286		      isc_result_totext(result));
1287	dns_rdatasetiter_destroy(&rdsiter);
1288}
1289
1290/*%
1291 * Set up the iterator and global state before starting the tasks.
1292 */
1293static void
1294presign(void) {
1295	isc_result_t result;
1296
1297	gdbiter = NULL;
1298	result = dns_db_createiterator(gdb, 0, &gdbiter);
1299	check_result(result, "dns_db_createiterator()");
1300}
1301
1302/*%
1303 * Clean up the iterator and global state after the tasks complete.
1304 */
1305static void
1306postsign(void) {
1307	dns_dbiterator_destroy(&gdbiter);
1308}
1309
1310static isc_boolean_t
1311goodsig(dns_rdata_t *sigrdata, dns_name_t *name, dns_rdataset_t *keyrdataset,
1312	dns_rdataset_t *rdataset)
1313{
1314	dns_rdata_dnskey_t key;
1315	dns_rdata_rrsig_t sig;
1316	dst_key_t *dstkey = NULL;
1317	isc_result_t result;
1318
1319	dns_rdata_tostruct(sigrdata, &sig, NULL);
1320
1321	for (result = dns_rdataset_first(keyrdataset);
1322	     result == ISC_R_SUCCESS;
1323	     result = dns_rdataset_next(keyrdataset)) {
1324		dns_rdata_t rdata = DNS_RDATA_INIT;
1325		dns_rdataset_current(keyrdataset, &rdata);
1326		dns_rdata_tostruct(&rdata, &key, NULL);
1327		result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
1328						 &dstkey);
1329		if (result != ISC_R_SUCCESS)
1330			return (ISC_FALSE);
1331		if (sig.algorithm != key.algorithm ||
1332		    sig.keyid != dst_key_id(dstkey) ||
1333		    !dns_name_equal(&sig.signer, gorigin)) {
1334			dst_key_free(&dstkey);
1335			continue;
1336		}
1337		result = dns_dnssec_verify(name, rdataset, dstkey, ISC_FALSE,
1338					   mctx, sigrdata);
1339		dst_key_free(&dstkey);
1340		if (result == ISC_R_SUCCESS)
1341			return(ISC_TRUE);
1342	}
1343	return (ISC_FALSE);
1344}
1345
1346static void
1347verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
1348	  dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1349	  unsigned char *bad_algorithms)
1350{
1351	unsigned char set_algorithms[256];
1352	char namebuf[DNS_NAME_FORMATSIZE];
1353	char algbuf[80];
1354	char typebuf[80];
1355	dns_rdataset_t sigrdataset;
1356	dns_rdatasetiter_t *rdsiter = NULL;
1357	isc_result_t result;
1358	int i;
1359
1360	dns_rdataset_init(&sigrdataset);
1361	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1362	check_result(result, "dns_db_allrdatasets()");
1363	for (result = dns_rdatasetiter_first(rdsiter);
1364	     result == ISC_R_SUCCESS;
1365	     result = dns_rdatasetiter_next(rdsiter)) {
1366		dns_rdatasetiter_current(rdsiter, &sigrdataset);
1367		if (sigrdataset.type == dns_rdatatype_rrsig &&
1368		    sigrdataset.covers == rdataset->type)
1369			break;
1370		dns_rdataset_disassociate(&sigrdataset);
1371	}
1372	if (result != ISC_R_SUCCESS) {
1373		dns_name_format(name, namebuf, sizeof(namebuf));
1374		type_format(rdataset->type, typebuf, sizeof(typebuf));
1375		fprintf(stderr, "no signatures for %s/%s\n", namebuf, typebuf);
1376		for (i = 0; i < 256; i++)
1377			if (ksk_algorithms[i] != 0)
1378				bad_algorithms[i] = 1;
1379		return;
1380	}
1381
1382	memset(set_algorithms, 0, sizeof(set_algorithms));
1383	for (result = dns_rdataset_first(&sigrdataset);
1384	     result == ISC_R_SUCCESS;
1385	     result = dns_rdataset_next(&sigrdataset)) {
1386		dns_rdata_t rdata = DNS_RDATA_INIT;
1387		dns_rdata_rrsig_t sig;
1388
1389		dns_rdataset_current(&sigrdataset, &rdata);
1390		dns_rdata_tostruct(&rdata, &sig, NULL);
1391		if (rdataset->ttl != sig.originalttl) {
1392			dns_name_format(name, namebuf, sizeof(namebuf));
1393			type_format(rdataset->type, typebuf, sizeof(typebuf));
1394			fprintf(stderr, "TTL mismatch for %s %s keytag %u\n",
1395				namebuf, typebuf, sig.keyid);
1396			continue;
1397		}
1398		if ((set_algorithms[sig.algorithm] != 0) ||
1399		    (ksk_algorithms[sig.algorithm] == 0))
1400			continue;
1401		if (goodsig(&rdata, name, keyrdataset, rdataset))
1402			set_algorithms[sig.algorithm] = 1;
1403	}
1404	dns_rdatasetiter_destroy(&rdsiter);
1405	if (memcmp(set_algorithms, ksk_algorithms, sizeof(set_algorithms))) {
1406		dns_name_format(name, namebuf, sizeof(namebuf));
1407		type_format(rdataset->type, typebuf, sizeof(typebuf));
1408		for (i = 0; i < 256; i++)
1409			if ((ksk_algorithms[i] != 0) &&
1410			    (set_algorithms[i] == 0)) {
1411				dns_secalg_format(i, algbuf, sizeof(algbuf));
1412				fprintf(stderr, "Missing %s signature for "
1413					"%s %s\n", algbuf, namebuf, typebuf);
1414				bad_algorithms[i] = 1;
1415			}
1416	}
1417	dns_rdataset_disassociate(&sigrdataset);
1418}
1419
1420static void
1421verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
1422	   dns_rdataset_t *keyrdataset, unsigned char *ksk_algorithms,
1423	   unsigned char *bad_algorithms)
1424{
1425	dns_rdataset_t rdataset;
1426	dns_rdatasetiter_t *rdsiter = NULL;
1427	isc_result_t result;
1428
1429	result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
1430	check_result(result, "dns_db_allrdatasets()");
1431	result = dns_rdatasetiter_first(rdsiter);
1432	dns_rdataset_init(&rdataset);
1433	while (result == ISC_R_SUCCESS) {
1434		dns_rdatasetiter_current(rdsiter, &rdataset);
1435		if (rdataset.type != dns_rdatatype_rrsig &&
1436		    rdataset.type != dns_rdatatype_dnskey &&
1437		    (!delegation || rdataset.type == dns_rdatatype_ds ||
1438		     rdataset.type == dns_rdatatype_nsec)) {
1439			verifyset(&rdataset, name, node, keyrdataset,
1440				  ksk_algorithms, bad_algorithms);
1441		}
1442		dns_rdataset_disassociate(&rdataset);
1443		result = dns_rdatasetiter_next(rdsiter);
1444	}
1445	if (result != ISC_R_NOMORE)
1446		fatal("rdataset iteration failed: %s",
1447		      isc_result_totext(result));
1448	dns_rdatasetiter_destroy(&rdsiter);
1449}
1450
1451/*%
1452 * Verify that certain things are sane:
1453 *
1454 *   The apex has a DNSKEY RRset with at least one KSK, and at least
1455 *   one ZSK if the -x flag was not used.
1456 *
1457 *   The DNSKEY record was signed with at least one of the KSKs in
1458 *   the DNSKEY RRset.
1459 *
1460 *   The rest of the zone was signed with at least one of the ZSKs
1461 *   present in the DNSKEY RRset.
1462 */
1463static void
1464verifyzone(void) {
1465	char algbuf[80];
1466	dns_dbiterator_t *dbiter = NULL;
1467	dns_dbnode_t *node = NULL, *nextnode = NULL;
1468	dns_fixedname_t fname, fnextname, fzonecut;
1469	dns_name_t *name, *nextname, *zonecut;
1470	dns_rdata_dnskey_t dnskey;
1471	dns_rdata_t rdata = DNS_RDATA_INIT;
1472	dns_rdataset_t keyset, soaset;
1473	dns_rdataset_t keysigs, soasigs;
1474	int i;
1475	isc_boolean_t done = ISC_FALSE;
1476	isc_boolean_t first = ISC_TRUE;
1477	isc_boolean_t goodksk = ISC_FALSE;
1478	isc_result_t result;
1479	unsigned char revoked_ksk[256];
1480	unsigned char revoked_zsk[256];
1481	unsigned char standby_ksk[256];
1482	unsigned char standby_zsk[256];
1483	unsigned char ksk_algorithms[256];
1484	unsigned char zsk_algorithms[256];
1485	unsigned char bad_algorithms[256];
1486#ifdef ALLOW_KSKLESS_ZONES
1487	isc_boolean_t allzsksigned = ISC_TRUE;
1488	unsigned char self_algorithms[256];
1489#endif
1490
1491	if (disable_zone_check)
1492		return;
1493
1494	result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
1495	if (result != ISC_R_SUCCESS)
1496		fatal("failed to find the zone's origin: %s",
1497		      isc_result_totext(result));
1498
1499	dns_rdataset_init(&keyset);
1500	dns_rdataset_init(&keysigs);
1501	dns_rdataset_init(&soaset);
1502	dns_rdataset_init(&soasigs);
1503
1504	result = dns_db_findrdataset(gdb, node, gversion,
1505				     dns_rdatatype_dnskey,
1506				     0, 0, &keyset, &keysigs);
1507	if (result != ISC_R_SUCCESS)
1508		fatal("cannot find DNSKEY rrset\n");
1509
1510	result = dns_db_findrdataset(gdb, node, gversion,
1511				     dns_rdatatype_soa,
1512				     0, 0, &soaset, &soasigs);
1513	dns_db_detachnode(gdb, &node);
1514	if (result != ISC_R_SUCCESS)
1515		fatal("cannot find SOA rrset\n");
1516
1517	if (!dns_rdataset_isassociated(&keysigs))
1518		fatal("cannot find DNSKEY RRSIGs\n");
1519
1520	if (!dns_rdataset_isassociated(&soasigs))
1521		fatal("cannot find SOA RRSIGs\n");
1522
1523	memset(revoked_ksk, 0, sizeof(revoked_ksk));
1524	memset(revoked_zsk, 0, sizeof(revoked_zsk));
1525	memset(standby_ksk, 0, sizeof(standby_ksk));
1526	memset(standby_zsk, 0, sizeof(standby_zsk));
1527	memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
1528	memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
1529	memset(bad_algorithms, 0, sizeof(bad_algorithms));
1530#ifdef ALLOW_KSKLESS_ZONES
1531	memset(self_algorithms, 0, sizeof(self_algorithms));
1532#endif
1533
1534	/*
1535	 * Check that the DNSKEY RR has at least one self signing KSK
1536	 * and one ZSK per algorithm in it (or, if -x was used, one
1537	 * self-signing KSK).
1538	 */
1539	for (result = dns_rdataset_first(&keyset);
1540	     result == ISC_R_SUCCESS;
1541	     result = dns_rdataset_next(&keyset)) {
1542		dns_rdataset_current(&keyset, &rdata);
1543		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
1544		check_result(result, "dns_rdata_tostruct");
1545
1546		if ((dnskey.flags & DNS_KEYOWNER_ZONE) == 0)
1547			;
1548		else if ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0) {
1549			if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1550			    !dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
1551						  &keysigs, ISC_FALSE,
1552						  mctx)) {
1553				char namebuf[DNS_NAME_FORMATSIZE];
1554				char buffer[1024];
1555				isc_buffer_t buf;
1556
1557				dns_name_format(gorigin, namebuf,
1558						sizeof(namebuf));
1559				isc_buffer_init(&buf, buffer, sizeof(buffer));
1560				result = dns_rdata_totext(&rdata, NULL, &buf);
1561				check_result(result, "dns_rdata_totext");
1562				fatal("revoked KSK is not self signed:\n"
1563				      "%s DNSKEY %.*s", namebuf,
1564				      (int)isc_buffer_usedlength(&buf), buffer);
1565			}
1566			if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
1567			     revoked_ksk[dnskey.algorithm] != 255)
1568				revoked_ksk[dnskey.algorithm]++;
1569			else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
1570				 revoked_zsk[dnskey.algorithm] != 255)
1571				revoked_zsk[dnskey.algorithm]++;
1572		} else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
1573			if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
1574					      &keysigs, ISC_FALSE, mctx)) {
1575				if (ksk_algorithms[dnskey.algorithm] != 255)
1576					ksk_algorithms[dnskey.algorithm]++;
1577				goodksk = ISC_TRUE;
1578			} else {
1579				if (standby_ksk[dnskey.algorithm] != 255)
1580					standby_ksk[dnskey.algorithm]++;
1581			}
1582		} else if (dns_dnssec_selfsigns(&rdata, gorigin, &keyset,
1583						&keysigs, ISC_FALSE,
1584						mctx)) {
1585#ifdef ALLOW_KSKLESS_ZONES
1586			if (self_algorithms[dnskey.algorithm] != 255)
1587				self_algorithms[dnskey.algorithm]++;
1588#endif
1589			if (zsk_algorithms[dnskey.algorithm] != 255)
1590				zsk_algorithms[dnskey.algorithm]++;
1591		} else if (dns_dnssec_signs(&rdata, gorigin, &soaset,
1592					    &soasigs, ISC_FALSE, mctx)) {
1593			if (zsk_algorithms[dnskey.algorithm] != 255)
1594				zsk_algorithms[dnskey.algorithm]++;
1595		} else {
1596			if (standby_zsk[dnskey.algorithm] != 255)
1597				standby_zsk[dnskey.algorithm]++;
1598#ifdef ALLOW_KSKLESS_ZONES
1599			allzsksigned = ISC_FALSE;
1600#endif
1601		}
1602		dns_rdata_freestruct(&dnskey);
1603		dns_rdata_reset(&rdata);
1604	}
1605	dns_rdataset_disassociate(&keysigs);
1606	dns_rdataset_disassociate(&soaset);
1607	dns_rdataset_disassociate(&soasigs);
1608
1609#ifdef ALLOW_KSKLESS_ZONES
1610	if (!goodksk) {
1611		if (!ignore_kskflag)
1612			fprintf(stderr, "No self signing KSK found. Using "
1613					"self signed ZSK's for active "
1614					"algorithm list.\n");
1615		memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms));
1616		if (!allzsksigned)
1617			fprintf(stderr, "warning: not all ZSK's are self "
1618				"signed.\n");
1619	}
1620#else
1621	if (!goodksk) {
1622		fatal("No self signed KSK's found");
1623	}
1624#endif
1625
1626	fprintf(stderr, "Verifying the zone using the following algorithms:");
1627	for (i = 0; i < 256; i++) {
1628#ifdef ALLOW_KSKLESS_ZONES
1629		if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0)
1630#else
1631		if (ksk_algorithms[i] != 0)
1632#endif
1633		{
1634			dns_secalg_format(i, algbuf, sizeof(algbuf));
1635			fprintf(stderr, " %s", algbuf);
1636		}
1637	}
1638	fprintf(stderr, ".\n");
1639
1640	if (!ignore_kskflag && !keyset_kskonly) {
1641		for (i = 0; i < 256; i++) {
1642			/*
1643			 * The counts should both be zero or both be non-zero.
1644			 * Mark the algorithm as bad if this is not met.
1645			 */
1646			if ((ksk_algorithms[i] != 0) ==
1647			    (zsk_algorithms[i] != 0))
1648				continue;
1649			dns_secalg_format(i, algbuf, sizeof(algbuf));
1650			fprintf(stderr, "Missing %s for algorithm %s\n",
1651				(ksk_algorithms[i] != 0)
1652				   ? "ZSK"
1653				   : "self signing KSK",
1654				algbuf);
1655			bad_algorithms[i] = 1;
1656		}
1657	}
1658
1659	/*
1660	 * Check that all the other records were signed by keys that are
1661	 * present in the DNSKEY RRSET.
1662	 */
1663
1664	dns_fixedname_init(&fname);
1665	name = dns_fixedname_name(&fname);
1666	dns_fixedname_init(&fnextname);
1667	nextname = dns_fixedname_name(&fnextname);
1668	dns_fixedname_init(&fzonecut);
1669	zonecut = NULL;
1670
1671	result = dns_db_createiterator(gdb, DNS_DB_NONSEC3, &dbiter);
1672	check_result(result, "dns_db_createiterator()");
1673
1674	result = dns_dbiterator_first(dbiter);
1675	check_result(result, "dns_dbiterator_first()");
1676
1677	while (!done) {
1678		isc_boolean_t isdelegation = ISC_FALSE;
1679
1680		result = dns_dbiterator_current(dbiter, &node, name);
1681		check_dns_dbiterator_current(result);
1682		if (!dns_name_issubdomain(name, gorigin)) {
1683			dns_db_detachnode(gdb, &node);
1684			result = dns_dbiterator_next(dbiter);
1685			if (result == ISC_R_NOMORE)
1686				done = ISC_TRUE;
1687			else
1688				check_result(result, "dns_dbiterator_next()");
1689			continue;
1690		}
1691		if (delegation(name, node, NULL)) {
1692			zonecut = dns_fixedname_name(&fzonecut);
1693			dns_name_copy(name, zonecut, NULL);
1694			isdelegation = ISC_TRUE;
1695		}
1696		verifynode(name, node, isdelegation, &keyset,
1697			   ksk_algorithms, bad_algorithms);
1698		result = dns_dbiterator_next(dbiter);
1699		nextnode = NULL;
1700		while (result == ISC_R_SUCCESS) {
1701			result = dns_dbiterator_current(dbiter, &nextnode,
1702							nextname);
1703			check_dns_dbiterator_current(result);
1704			if (!dns_name_issubdomain(nextname, gorigin) ||
1705			    (zonecut != NULL &&
1706			     dns_name_issubdomain(nextname, zonecut)))
1707			{
1708				dns_db_detachnode(gdb, &nextnode);
1709				result = dns_dbiterator_next(dbiter);
1710				continue;
1711			}
1712			dns_db_detachnode(gdb, &nextnode);
1713			break;
1714		}
1715		if (result == ISC_R_NOMORE) {
1716			done = ISC_TRUE;
1717		} else if (re

Large files files are truncated, but you can click here to view the full file