aboutsummaryrefslogtreecommitdiff
path: root/contrib/bind9/bin/dnssec/dnssec-signzone.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/bin/dnssec/dnssec-signzone.c')
-rw-r--r--contrib/bind9/bin/dnssec/dnssec-signzone.c1157
1 files changed, 757 insertions, 400 deletions
diff --git a/contrib/bind9/bin/dnssec/dnssec-signzone.c b/contrib/bind9/bin/dnssec/dnssec-signzone.c
index b8f4d664b6da..3997a135b465 100644
--- a/contrib/bind9/bin/dnssec/dnssec-signzone.c
+++ b/contrib/bind9/bin/dnssec/dnssec-signzone.c
@@ -29,7 +29,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-signzone.c,v 1.209.12.20 2010-06-03 23:47:48 tbox Exp $ */
+/* $Id: dnssec-signzone.c,v 1.262 2010-06-03 23:51:04 tbox Exp $ */
/*! \file */
@@ -87,6 +87,10 @@
#include "dnssectool.h"
+#ifndef PATH_MAX
+#define PATH_MAX 1024 /* AIX, WIN32, and others don't define this. */
+#endif
+
const char *program = "dnssec-signzone";
int verbose;
@@ -97,22 +101,11 @@ static int nsec_datatype = dns_rdatatype_nsec;
#define IS_NSEC3 (nsec_datatype == dns_rdatatype_nsec3)
#define OPTOUT(x) (((x) & DNS_NSEC3FLAG_OPTOUT) != 0)
+#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
+
#define BUFSIZE 2048
#define MAXDSKEYS 8
-typedef struct signer_key_struct signer_key_t;
-
-struct signer_key_struct {
- dst_key_t *key;
- isc_boolean_t issigningkey;
- isc_boolean_t isdsk;
- isc_boolean_t isksk;
- isc_boolean_t wasused;
- isc_boolean_t commandline;
- unsigned int position;
- ISC_LINK(signer_key_t) link;
-};
-
#define SIGNER_EVENTCLASS ISC_EVENTCLASS(0x4453)
#define SIGNER_EVENT_WRITE (SIGNER_EVENTCLASS + 0)
#define SIGNER_EVENT_WORK (SIGNER_EVENTCLASS + 1)
@@ -128,7 +121,7 @@ struct signer_event {
dns_dbnode_t *node;
};
-static ISC_LIST(signer_key_t) keylist;
+static dns_dnsseckeylist_t keylist;
static unsigned int keycount = 0;
isc_rwlock_t keylist_lock;
static isc_stdtime_t starttime = 0, endtime = 0, now;
@@ -138,7 +131,8 @@ static isc_boolean_t tryverify = ISC_FALSE;
static isc_boolean_t printstats = ISC_FALSE;
static isc_mem_t *mctx = NULL;
static isc_entropy_t *ectx = NULL;
-static dns_ttl_t zonettl;
+static dns_ttl_t zone_soa_min_ttl;
+static dns_ttl_t soa_ttl;
static FILE *fp;
static char *tempfile = NULL;
static const dns_master_style_t *masterstyle;
@@ -146,7 +140,7 @@ static dns_masterformat_t inputformat = dns_masterformat_text;
static dns_masterformat_t outputformat = dns_masterformat_text;
static unsigned int nsigned = 0, nretained = 0, ndropped = 0;
static unsigned int nverified = 0, nverifyfailed = 0;
-static const char *directory;
+static const char *directory = NULL, *dsdir = NULL;
static isc_mutex_t namelock, statslock;
static isc_taskmgr_t *taskmgr = NULL;
static dns_db_t *gdb; /* The database */
@@ -155,13 +149,18 @@ static dns_dbiterator_t *gdbiter; /* The database iterator */
static dns_rdataclass_t gclass; /* The class */
static dns_name_t *gorigin; /* The database origin */
static int nsec3flags = 0;
+static dns_iterations_t nsec3iter = 10U;
+static unsigned char saltbuf[255];
+static unsigned char *salt = saltbuf;
+static size_t salt_length = 0;
static isc_task_t *master = NULL;
static unsigned int ntasks = 0;
static isc_boolean_t shuttingdown = ISC_FALSE, finished = ISC_FALSE;
static isc_boolean_t nokeys = ISC_FALSE;
static isc_boolean_t removefile = ISC_FALSE;
static isc_boolean_t generateds = ISC_FALSE;
-static isc_boolean_t ignoreksk = ISC_FALSE;
+static isc_boolean_t ignore_kskflag = ISC_FALSE;
+static isc_boolean_t keyset_kskonly = ISC_FALSE;
static dns_name_t *dlv = NULL;
static dns_fixedname_t dlv_fixed;
static dns_master_style_t *dsstyle = NULL;
@@ -169,6 +168,9 @@ static unsigned int serialformat = SOA_SERIAL_KEEP;
static unsigned int hash_length = 0;
static isc_boolean_t unknownalg = ISC_FALSE;
static isc_boolean_t disable_zone_check = ISC_FALSE;
+static isc_boolean_t update_chain = ISC_FALSE;
+static isc_boolean_t set_keyttl = ISC_FALSE;
+static dns_ttl_t keyttl;
#define INCSTAT(counter) \
if (printstats) { \
@@ -195,48 +197,23 @@ dumpnode(dns_name_t *name, dns_dbnode_t *node) {
check_result(result, "dns_master_dumpnodetostream");
}
-static signer_key_t *
-newkeystruct(dst_key_t *dstkey, isc_boolean_t signwithkey) {
- signer_key_t *key;
-
- key = isc_mem_get(mctx, sizeof(signer_key_t));
- if (key == NULL)
- fatal("out of memory");
- key->key = dstkey;
- if ((dst_key_flags(dstkey) & DNS_KEYFLAG_KSK) != 0) {
- key->issigningkey = signwithkey;
- key->isksk = ISC_TRUE;
- key->isdsk = ISC_FALSE;
- } else {
- key->issigningkey = signwithkey;
- key->isksk = ISC_FALSE;
- key->isdsk = ISC_TRUE;
- }
- key->wasused = ISC_FALSE;
- key->commandline = ISC_FALSE;
- key->position = keycount++;
- ISC_LINK_INIT(key, link);
- return (key);
-}
-
/*%
* Sign the given RRset with given key, and add the signature record to the
* given tuple.
*/
-
static void
signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
dns_ttl_t ttl, dns_diff_t *add, const char *logmsg)
{
isc_result_t result;
isc_stdtime_t jendtime;
- char keystr[KEY_FORMATSIZE];
+ char keystr[DST_KEY_FORMATSIZE];
dns_rdata_t trdata = DNS_RDATA_INIT;
unsigned char array[BUFSIZE];
isc_buffer_t b;
dns_difftuple_t *tuple;
- key_format(key, keystr, sizeof(keystr));
+ dst_key_format(key, keystr, sizeof(keystr));
vbprintf(1, "\t%s %s\n", logmsg, keystr);
jendtime = (jitter != 0) ? isc_random_jitter(endtime, jitter) : endtime;
@@ -245,8 +222,8 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
mctx, &b, &trdata);
isc_entropy_stopcallbacksources(ectx);
if (result != ISC_R_SUCCESS) {
- char keystr[KEY_FORMATSIZE];
- key_format(key, keystr, sizeof(keystr));
+ char keystr[DST_KEY_FORMATSIZE];
+ dst_key_format(key, keystr, sizeof(keystr));
fatal("dnskey '%s' failed to sign data: %s",
keystr, isc_result_totext(result));
}
@@ -272,31 +249,43 @@ signwithkey(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *key,
}
static inline isc_boolean_t
-issigningkey(signer_key_t *key) {
- return (key->issigningkey);
+issigningkey(dns_dnsseckey_t *key) {
+ return (key->force_sign || key->hint_sign);
}
static inline isc_boolean_t
-iszonekey(signer_key_t *key) {
+iszonekey(dns_dnsseckey_t *key) {
return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) &&
dst_key_iszonekey(key->key)));
}
+static inline isc_boolean_t
+isksk(dns_dnsseckey_t *key) {
+ return (key->ksk);
+}
+
+static inline isc_boolean_t
+iszsk(dns_dnsseckey_t *key) {
+ return (ignore_kskflag || !key->ksk);
+}
+
/*%
- * Find the key if it is in our list. If it is, return it, otherwise null.
+ * Find the key that generated an RRSIG, if it is in the key list. If
+ * so, return a pointer to it, otherwise return NULL.
+ *
* No locking is performed here, this must be done by the caller.
*/
-static signer_key_t *
+static dns_dnsseckey_t *
keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
- signer_key_t *key;
+ dns_dnsseckey_t *key;
- key = ISC_LIST_HEAD(keylist);
- while (key != NULL) {
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
if (rrsig->keyid == dst_key_id(key->key) &&
rrsig->algorithm == dst_key_alg(key->key) &&
dns_name_equal(&rrsig->signer, dst_key_name(key->key)))
return (key);
- key = ISC_LIST_NEXT(key, link);
}
return (NULL);
}
@@ -305,11 +294,11 @@ keythatsigned_unlocked(dns_rdata_rrsig_t *rrsig) {
* Finds the key that generated a RRSIG, if possible. First look at the keys
* that we've loaded already, and then see if there's a key on disk.
*/
-static signer_key_t *
+static dns_dnsseckey_t *
keythatsigned(dns_rdata_rrsig_t *rrsig) {
isc_result_t result;
dst_key_t *pubkey = NULL, *privkey = NULL;
- signer_key_t *key;
+ dns_dnsseckey_t *key = NULL;
isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read);
key = keythatsigned_unlocked(rrsig);
@@ -325,7 +314,6 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) {
* after all.
*/
isc_rwlock_lock(&keylist_lock, isc_rwlocktype_write);
-
key = keythatsigned_unlocked(rrsig);
if (key != NULL) {
isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
@@ -334,7 +322,7 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) {
result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
rrsig->algorithm, DST_TYPE_PUBLIC,
- NULL, mctx, &pubkey);
+ directory, mctx, &pubkey);
if (result != ISC_R_SUCCESS) {
isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
return (NULL);
@@ -343,12 +331,15 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) {
result = dst_key_fromfile(&rrsig->signer, rrsig->keyid,
rrsig->algorithm,
DST_TYPE_PUBLIC | DST_TYPE_PRIVATE,
- NULL, mctx, &privkey);
+ directory, mctx, &privkey);
if (result == ISC_R_SUCCESS) {
dst_key_free(&pubkey);
- key = newkeystruct(privkey, ISC_FALSE);
- } else
- key = newkeystruct(pubkey, ISC_FALSE);
+ dns_dnsseckey_create(mctx, &privkey, &key);
+ } else {
+ dns_dnsseckey_create(mctx, &pubkey, &key);
+ }
+ key->force_publish = ISC_TRUE;
+ key->force_sign = ISC_FALSE;
ISC_LIST_APPEND(keylist, key, link);
isc_rwlock_unlock(&keylist_lock, isc_rwlocktype_write);
@@ -383,15 +374,16 @@ expecttofindkey(dns_name_t *name) {
dns_name_format(name, namestr, sizeof(namestr));
fatal("failure looking for '%s DNSKEY' in database: %s",
namestr, isc_result_totext(result));
+ /* NOTREACHED */
return (ISC_FALSE); /* removes a warning */
}
static inline isc_boolean_t
-setverifies(dns_name_t *name, dns_rdataset_t *set, signer_key_t *key,
+setverifies(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key,
dns_rdata_t *rrsig)
{
isc_result_t result;
- result = dns_dnssec_verify(name, set, key->key, ISC_FALSE, mctx, rrsig);
+ result = dns_dnssec_verify(name, set, key, ISC_FALSE, mctx, rrsig);
if (result == ISC_R_SUCCESS) {
INCSTAT(nverified);
return (ISC_TRUE);
@@ -413,7 +405,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
dns_rdataset_t sigset;
dns_rdata_t sigrdata = DNS_RDATA_INIT;
dns_rdata_rrsig_t rrsig;
- signer_key_t *key;
+ dns_dnsseckey_t *key;
isc_result_t result;
isc_boolean_t nosigs = ISC_FALSE;
isc_boolean_t *wassignedby, *nowsignedby;
@@ -483,8 +475,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
"invalid validity period\n",
sigstr);
} else if (key == NULL && !future &&
- expecttofindkey(&rrsig.signer))
- {
+ expecttofindkey(&rrsig.signer)) {
/* rrsig is dropped and not replaced */
vbprintf(2, "\trrsig by %s dropped - "
"private dnskey not found\n",
@@ -495,35 +486,33 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
if (!expired)
keep = ISC_TRUE;
} else if (issigningkey(key)) {
- if (!expired && setverifies(name, set, key, &sigrdata))
- {
+ if (!expired && setverifies(name, set, key->key,
+ &sigrdata)) {
vbprintf(2, "\trrsig by %s retained\n", sigstr);
keep = ISC_TRUE;
- wassignedby[key->position] = ISC_TRUE;
- nowsignedby[key->position] = ISC_TRUE;
- key->wasused = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
+ nowsignedby[key->index] = ISC_TRUE;
} else {
vbprintf(2, "\trrsig by %s dropped - %s\n",
sigstr,
expired ? "expired" :
"failed to verify");
- wassignedby[key->position] = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
resign = ISC_TRUE;
}
} else if (iszonekey(key)) {
- if (!expired && setverifies(name, set, key, &sigrdata))
- {
+ if (!expired && setverifies(name, set, key->key,
+ &sigrdata)) {
vbprintf(2, "\trrsig by %s retained\n", sigstr);
keep = ISC_TRUE;
- wassignedby[key->position] = ISC_TRUE;
- nowsignedby[key->position] = ISC_TRUE;
- key->wasused = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
+ nowsignedby[key->index] = ISC_TRUE;
} else {
vbprintf(2, "\trrsig by %s dropped - %s\n",
sigstr,
expired ? "expired" :
"failed to verify");
- wassignedby[key->position] = ISC_TRUE;
+ wassignedby[key->index] = ISC_TRUE;
}
} else if (!expired) {
vbprintf(2, "\trrsig by %s retained\n", sigstr);
@@ -533,7 +522,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
}
if (keep) {
- nowsignedby[key->position] = ISC_TRUE;
+ nowsignedby[key->index] = ISC_TRUE;
INCSTAT(nretained);
if (sigset.ttl != ttl) {
vbprintf(2, "\tfixing ttl %s\n", sigstr);
@@ -568,8 +557,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
signwithkey(name, set, key->key, ttl, add,
"resigning with dnskey");
- nowsignedby[key->position] = ISC_TRUE;
- key->wasused = ISC_TRUE;
+ nowsignedby[key->index] = ISC_TRUE;
}
dns_rdata_reset(&sigrdata);
@@ -587,20 +575,37 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
key != NULL;
key = ISC_LIST_NEXT(key, link))
{
- if (nowsignedby[key->position])
+ if (nowsignedby[key->index])
continue;
- if (!key->issigningkey)
- continue;
- if (!(ignoreksk || key->isdsk ||
- (key->isksk &&
- set->type == dns_rdatatype_dnskey &&
- dns_name_equal(name, gorigin))))
+ if (!issigningkey(key))
continue;
- signwithkey(name, set, key->key, ttl, add,
- "signing with dnskey");
- key->wasused = ISC_TRUE;
+ if (set->type == dns_rdatatype_dnskey &&
+ dns_name_equal(name, gorigin)) {
+ isc_boolean_t have_ksk;
+ dns_dnsseckey_t *tmpkey;
+
+ have_ksk = isksk(key);
+ for (tmpkey = ISC_LIST_HEAD(keylist);
+ tmpkey != NULL;
+ tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
+ if (dst_key_alg(key->key) !=
+ dst_key_alg(tmpkey->key))
+ continue;
+ if (REVOKE(tmpkey->key))
+ continue;
+ if (isksk(tmpkey))
+ have_ksk = ISC_TRUE;
+ }
+ if (isksk(key) || !have_ksk ||
+ (iszsk(key) && !keyset_kskonly))
+ signwithkey(name, set, key->key, ttl, add,
+ "signing with dnskey");
+ } else if (iszsk(key)) {
+ signwithkey(name, set, key->key, ttl, add,
+ "signing with dnskey");
+ }
}
isc_mem_put(mctx, wassignedby, arraysize * sizeof(isc_boolean_t));
@@ -774,16 +779,21 @@ static void
opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
dns_db_t **dbp)
{
- char filename[256];
+ char filename[PATH_MAX];
isc_buffer_t b;
isc_result_t result;
isc_buffer_init(&b, filename, sizeof(filename));
- if (directory != NULL) {
- isc_buffer_putstr(&b, directory);
- if (directory[strlen(directory) - 1] != '/')
+ if (dsdir != NULL) {
+ /* allow room for a trailing slash */
+ if (strlen(dsdir) >= isc_buffer_availablelength(&b))
+ fatal("path '%s' is too long", dsdir);
+ isc_buffer_putstr(&b, dsdir);
+ if (dsdir[strlen(dsdir) - 1] != '/')
isc_buffer_putstr(&b, "/");
}
+ if (strlen(prefix) > isc_buffer_availablelength(&b))
+ fatal("path '%s' is too long", dsdir);
isc_buffer_putstr(&b, prefix);
result = dns_name_tofilenametext(name, ISC_FALSE, &b);
check_result(result, "dns_name_tofilenametext()");
@@ -798,13 +808,15 @@ opendb(const char *prefix, dns_name_t *name, dns_rdataclass_t rdclass,
rdclass, 0, NULL, dbp);
check_result(result, "dns_db_create()");
- result = dns_db_load(*dbp, filename);
+ result = dns_db_load3(*dbp, filename, inputformat, DNS_MASTER_HINT);
if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
dns_db_detach(dbp);
}
/*%
- * Loads the key set for a child zone, if there is one, and builds DS records.
+ * Load the DS set for a child zone, if a dsset-* file can be found.
+ * If not, try to find a keyset-* file from an earlier version of
+ * dnssec-signzone, and build DS records from that.
*/
static isc_result_t
loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
@@ -818,29 +830,49 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
dns_diff_t diff;
dns_difftuple_t *tuple = NULL;
+ opendb("dsset-", name, gclass, &db);
+ if (db != NULL) {
+ result = dns_db_findnode(db, name, ISC_FALSE, &node);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdataset_init(dsset);
+ result = dns_db_findrdataset(db, node, NULL,
+ dns_rdatatype_ds, 0, 0,
+ dsset, NULL);
+ dns_db_detachnode(db, &node);
+ if (result == ISC_R_SUCCESS) {
+ vbprintf(2, "found DS records\n");
+ dsset->ttl = ttl;
+ dns_db_detach(&db);
+ return (result);
+ }
+ }
+ dns_db_detach(&db);
+ }
+
+ /* No DS records found; try again, looking for DNSKEY records */
opendb("keyset-", name, gclass, &db);
- if (db == NULL)
+ if (db == NULL) {
return (ISC_R_NOTFOUND);
+ }
result = dns_db_findnode(db, name, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS) {
dns_db_detach(&db);
- return (DNS_R_BADDB);
+ return (result);
}
+
dns_rdataset_init(&keyset);
- result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0,
- 0, &keyset, NULL);
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_dnskey, 0, 0,
+ &keyset, NULL);
if (result != ISC_R_SUCCESS) {
dns_db_detachnode(db, &node);
dns_db_detach(&db);
return (result);
}
-
vbprintf(2, "found DNSKEY records\n");
result = dns_db_newversion(db, &ver);
check_result(result, "dns_db_newversion");
-
dns_diff_init(mctx, &diff);
for (result = dns_rdataset_first(&keyset);
@@ -869,6 +901,7 @@ loadds(dns_name_t *name, isc_uint32_t ttl, dns_rdataset_t *dsset) {
check_result(result, "dns_difftuple_create");
dns_diff_append(&diff, &tuple);
}
+
result = dns_diff_apply(&diff, db, ver);
check_result(result, "dns_diff_apply");
dns_diff_clear(&diff);
@@ -1112,17 +1145,15 @@ active_node(dns_dbnode_t *node) {
}
/*%
- * Extracts the TTL from the SOA.
+ * Extracts the minimum TTL from the SOA record, and the SOA record's TTL.
*/
-static dns_ttl_t
-soattl(void) {
+static void
+get_soa_ttls(void) {
dns_rdataset_t soaset;
dns_fixedname_t fname;
dns_name_t *name;
isc_result_t result;
- dns_ttl_t ttl;
dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdata_soa_t soa;
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
@@ -1136,11 +1167,9 @@ soattl(void) {
result = dns_rdataset_first(&soaset);
check_result(result, "dns_rdataset_first");
dns_rdataset_current(&soaset, &rdata);
- result = dns_rdata_tostruct(&rdata, &soa, NULL);
- check_result(result, "dns_rdata_tostruct");
- ttl = soa.minimum;
+ zone_soa_min_ttl = dns_soa_getminimum(&rdata);
+ soa_ttl = soaset.ttl;
dns_rdataset_disassociate(&soaset);
- return (ttl);
}
/*%
@@ -1371,7 +1400,7 @@ verifyset(dns_rdataset_t *rdataset, dns_name_t *name, dns_dbnode_t *node,
for (i = 0; i < 256; i++)
if ((ksk_algorithms[i] != 0) &&
(set_algorithms[i] == 0)) {
- alg_format(i, algbuf, sizeof(algbuf));
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, "Missing %s signature for "
"%s %s\n", algbuf, namebuf, typebuf);
bad_algorithms[i] = 1;
@@ -1414,8 +1443,8 @@ verifynode(dns_name_t *name, dns_dbnode_t *node, isc_boolean_t delegation,
/*%
* Verify that certain things are sane:
*
- * The apex has a DNSKEY record with at least one KSK and at least
- * one ZSK.
+ * The apex has a DNSKEY record with at least one KSK, and at least
+ * one ZSK if the -x flag was not used.
*
* The DNSKEY record was signed with at least one of the KSKs in this
* set.
@@ -1440,8 +1469,10 @@ verifyzone(void) {
isc_boolean_t goodksk = ISC_FALSE;
isc_boolean_t goodzsk = ISC_FALSE;
isc_result_t result;
- unsigned char revoked[256];
- unsigned char standby[256];
+ unsigned char revoked_ksk[256];
+ unsigned char revoked_zsk[256];
+ unsigned char standby_ksk[256];
+ unsigned char standby_zsk[256];
unsigned char ksk_algorithms[256];
unsigned char zsk_algorithms[256];
unsigned char bad_algorithms[256];
@@ -1470,8 +1501,10 @@ verifyzone(void) {
if (!dns_rdataset_isassociated(&sigrdataset))
fatal("cannot find DNSKEY RRSIGs\n");
- memset(revoked, 0, sizeof(revoked));
- memset(standby, 0, sizeof(revoked));
+ memset(revoked_ksk, 0, sizeof(revoked_ksk));
+ memset(revoked_zsk, 0, sizeof(revoked_zsk));
+ memset(standby_ksk, 0, sizeof(standby_ksk));
+ memset(standby_zsk, 0, sizeof(standby_zsk));
memset(ksk_algorithms, 0, sizeof(ksk_algorithms));
memset(zsk_algorithms, 0, sizeof(zsk_algorithms));
memset(bad_algorithms, 0, sizeof(bad_algorithms));
@@ -1480,8 +1513,9 @@ verifyzone(void) {
#endif
/*
- * Check that the DNSKEY RR has at least one self signing KSK and
- * one ZSK per algorithm in it.
+ * Check that the DNSKEY RR has at least one self signing KSK
+ * and one ZSK per algorithm in it (or, if -x was used, one
+ * self-signing KSK).
*/
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
@@ -1511,8 +1545,11 @@ verifyzone(void) {
(int)isc_buffer_usedlength(&buf), buffer);
}
if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0 &&
- revoked[dnskey.algorithm] != 255)
- revoked[dnskey.algorithm]++;
+ revoked_ksk[dnskey.algorithm] != 255)
+ revoked_ksk[dnskey.algorithm]++;
+ else if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0 &&
+ revoked_zsk[dnskey.algorithm] != 255)
+ revoked_zsk[dnskey.algorithm]++;
} else if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) {
if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
&sigrdataset, ISC_FALSE, mctx)) {
@@ -1520,8 +1557,8 @@ verifyzone(void) {
ksk_algorithms[dnskey.algorithm]++;
goodksk = ISC_TRUE;
} else {
- if (standby[dnskey.algorithm] != 255)
- standby[dnskey.algorithm]++;
+ if (standby_ksk[dnskey.algorithm] != 255)
+ standby_ksk[dnskey.algorithm]++;
}
} else if (dns_dnssec_selfsigns(&rdata, gorigin, &rdataset,
&sigrdataset, ISC_FALSE,
@@ -1534,8 +1571,8 @@ verifyzone(void) {
zsk_algorithms[dnskey.algorithm]++;
goodzsk = ISC_TRUE;
} else {
- if (zsk_algorithms[dnskey.algorithm] != 255)
- zsk_algorithms[dnskey.algorithm]++;
+ if (standby_zsk[dnskey.algorithm] != 255)
+ standby_zsk[dnskey.algorithm]++;
#ifdef ALLOW_KSKLESS_ZONES
allzsksigned = ISC_FALSE;
#endif
@@ -1545,42 +1582,54 @@ verifyzone(void) {
}
dns_rdataset_disassociate(&sigrdataset);
- if (!goodksk) {
#ifdef ALLOW_KSKLESS_ZONES
- if (!goodzsk)
- fatal("no self signing keys found");
- fprintf(stderr, "No self signing KSK found. Using self signed "
- "ZSK's for active algorithm list.\n");
+ if (!goodksk) {
+ if (!ignore_kskflag)
+ fprintf(stderr, "No self signing KSK found. Using "
+ "self signed ZSK's for active "
+ "algorithm list.\n");
memcpy(ksk_algorithms, self_algorithms, sizeof(ksk_algorithms));
if (!allzsksigned)
fprintf(stderr, "warning: not all ZSK's are self "
"signed.\n");
+ }
#else
+ if (!goodksk) {
fatal("no self signed KSK's found");
-#endif
}
+#endif
fprintf(stderr, "Verifying the zone using the following algorithms:");
for (i = 0; i < 256; i++) {
- if (ksk_algorithms[i] != 0) {
- alg_format(i, algbuf, sizeof(algbuf));
+#ifdef ALLOW_KSKLESS_ZONES
+ if (ksk_algorithms[i] != 0 || zsk_algorithms[i] != 0)
+#else
+ if (ksk_algorithms[i] != 0)
+#endif
+ {
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, " %s", algbuf);
}
}
fprintf(stderr, ".\n");
- for (i = 0; i < 256; i++) {
- /*
- * The counts should both be zero or both be non-zero.
- * Mark the algorithm as bad if this is not met.
- */
- if ((ksk_algorithms[i] != 0) == (zsk_algorithms[i] != 0))
- continue;
- alg_format(i, algbuf, sizeof(algbuf));
- fprintf(stderr, "Missing %s for algorithm %s\n",
- (ksk_algorithms[i] != 0) ? "ZSK" : "self signing KSK",
- algbuf);
- bad_algorithms[i] = 1;
+ if (!ignore_kskflag && !keyset_kskonly) {
+ for (i = 0; i < 256; i++) {
+ /*
+ * The counts should both be zero or both be non-zero.
+ * Mark the algorithm as bad if this is not met.
+ */
+ if ((ksk_algorithms[i] != 0) ==
+ (zsk_algorithms[i] != 0))
+ continue;
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
+ fprintf(stderr, "Missing %s for algorithm %s\n",
+ (ksk_algorithms[i] != 0)
+ ? "ZSK"
+ : "self signing KSK",
+ algbuf);
+ bad_algorithms[i] = 1;
+ }
}
/*
@@ -1674,7 +1723,7 @@ verifyzone(void) {
if (first)
fprintf(stderr, "The zone is not fully signed "
"for the following algorithms:");
- alg_format(i, algbuf, sizeof(algbuf));
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
fprintf(stderr, " %s", algbuf);
first = ISC_FALSE;
}
@@ -1684,21 +1733,30 @@ verifyzone(void) {
fatal("DNSSEC completeness test failed.");
}
- if (goodksk) {
+ if (goodksk || ignore_kskflag) {
/*
* Print the success summary.
*/
fprintf(stderr, "Zone signing complete:\n");
for (i = 0; i < 256; i++) {
- if ((zsk_algorithms[i] != 0) ||
- (ksk_algorithms[i] != 0) ||
- (revoked[i] != 0) || (standby[i] != 0)) {
- alg_format(i, algbuf, sizeof(algbuf));
- fprintf(stderr, "Algorithm: %s: ZSKs: %u, "
- "KSKs: %u active, %u revoked, %u "
- "stand-by\n", algbuf,
- zsk_algorithms[i], ksk_algorithms[i],
- revoked[i], standby[i]);
+ if ((ksk_algorithms[i] != 0) ||
+ (standby_ksk[i] != 0) ||
+ (revoked_zsk[i] != 0) ||
+ (zsk_algorithms[i] != 0) ||
+ (standby_zsk[i] != 0) ||
+ (revoked_zsk[i] != 0)) {
+ dns_secalg_format(i, algbuf, sizeof(algbuf));
+ fprintf(stderr, "Algorithm: %s: KSKs: "
+ "%u active, %u stand-by, %u revoked\n",
+ algbuf, ksk_algorithms[i],
+ standby_ksk[i], revoked_ksk[i]);
+ fprintf(stderr, "%*sZSKs: "
+ "%u active, %u %s, %u revoked\n",
+ (int) strlen(algbuf) + 13, "",
+ zsk_algorithms[i],
+ standby_zsk[i],
+ keyset_kskonly ? "present" : "stand-by",
+ revoked_zsk[i]);
}
}
}
@@ -1923,6 +1981,7 @@ add_ds(dns_name_t *name, dns_dbnode_t *node, isc_uint32_t nsttl) {
dns_rdatatype_ds, 0);
check_result(result, "dns_db_deleterdataset");
}
+
result = loadds(name, nsttl, &dsset);
if (result == ISC_R_SUCCESS) {
result = dns_db_addrdataset(gdb, node, gversion, 0,
@@ -1953,7 +2012,7 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) {
dns_rdataset_init(&rdataset);
/*
- * Delete any NSEC records at the apex.
+ * Delete any records of the given type at the apex.
*/
result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
check_result(result, "dns_db_allrdatasets()");
@@ -1965,6 +2024,12 @@ remove_records(dns_dbnode_t *node, dns_rdatatype_t which) {
covers = rdataset.covers;
dns_rdataset_disassociate(&rdataset);
if (type == which || covers == which) {
+ if (which == dns_rdatatype_nsec && !update_chain)
+ fatal("Zone contains NSEC records. Use -u "
+ "to update to NSEC3.");
+ if (which == dns_rdatatype_nsec3param && !update_chain)
+ fatal("Zone contains NSEC3 chains. Use -u "
+ "to update to NSEC.");
result = dns_db_deleterdataset(gdb, node, gversion,
type, covers);
check_result(result, "dns_db_deleterdataset()");
@@ -2088,8 +2153,9 @@ nsecify(void) {
} else if (result != ISC_R_SUCCESS)
fatal("iterating through the database failed: %s",
isc_result_totext(result));
+ dns_dbiterator_pause(dbiter);
result = dns_nsec_build(gdb, gversion, node, nextname,
- zonettl);
+ zone_soa_min_ttl);
check_result(result, "dns_nsec_build()");
dns_db_detachnode(gdb, &node);
}
@@ -2320,6 +2386,97 @@ nsec3clean(dns_name_t *name, dns_dbnode_t *node,
check_result(result, "dns_db_deleterdataset(RRSIG(NSEC3))");
}
+static void
+rrset_remove_duplicates(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_diff_t *diff)
+{
+ dns_difftuple_t *tuple = NULL;
+ isc_result_t result;
+ unsigned int count1 = 0;
+ dns_rdataset_t tmprdataset;
+
+ dns_rdataset_init(&tmprdataset);
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata1 = DNS_RDATA_INIT;
+ unsigned int count2 = 0;
+
+ count1++;
+ dns_rdataset_current(rdataset, &rdata1);
+ dns_rdataset_clone(rdataset, &tmprdataset);
+ for (result = dns_rdataset_first(&tmprdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&tmprdataset)) {
+ dns_rdata_t rdata2 = DNS_RDATA_INIT;
+ count2++;
+ if (count1 >= count2)
+ continue;
+ dns_rdataset_current(&tmprdataset, &rdata2);
+ if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
+ result = dns_difftuple_create(mctx,
+ DNS_DIFFOP_DEL,
+ name,
+ rdataset->ttl,
+ &rdata2, &tuple);
+ check_result(result, "dns_difftuple_create");
+ dns_diff_append(diff, &tuple);
+ }
+ }
+ dns_rdataset_disassociate(&tmprdataset);
+ }
+}
+
+static void
+remove_duplicates(void) {
+ isc_result_t result;
+ dns_dbiterator_t *dbiter = NULL;
+ dns_rdatasetiter_t *rdsiter = NULL;
+ dns_diff_t diff;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_fixedname_t fname;
+ dns_name_t *name;
+
+ dns_diff_init(mctx, &diff);
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ dns_rdataset_init(&rdataset);
+
+ result = dns_db_createiterator(gdb, 0, &dbiter);
+ check_result(result, "dns_db_createiterator()");
+
+ for (result = dns_dbiterator_first(dbiter);
+ result == ISC_R_SUCCESS;
+ result = dns_dbiterator_next(dbiter)) {
+
+ result = dns_dbiterator_current(dbiter, &node, name);
+ check_dns_dbiterator_current(result);
+ result = dns_db_allrdatasets(gdb, node, gversion, 0, &rdsiter);
+ check_result(result, "dns_db_allrdatasets()");
+ for (result = dns_rdatasetiter_first(rdsiter);
+ result == ISC_R_SUCCESS;
+ result = dns_rdatasetiter_next(rdsiter)) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ rrset_remove_duplicates(name, &rdataset, &diff);
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("rdatasets iteration failed.");
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(gdb, &node);
+ }
+ if (result != ISC_R_NOMORE)
+ fatal("zone iteration failed.");
+
+ if (!ISC_LIST_EMPTY(diff.tuples)) {
+ result = dns_diff_applysilently(&diff, gdb, gversion);
+ check_result(result, "dns_diff_applysilently");
+ }
+ dns_diff_clear(&diff);
+ dns_dbiterator_destroy(&dbiter);
+}
+
/*
* Generate NSEC3 records for the zone.
*/
@@ -2546,7 +2703,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations,
*/
dns_dbiterator_pause(dbiter);
addnsec3(name, node, salt, salt_length, iterations,
- hashlist, zonettl);
+ hashlist, zone_soa_min_ttl);
dns_db_detachnode(gdb, &node);
/*
* Add NSEC3's for empty nodes. Use closest encloser logic.
@@ -2557,7 +2714,7 @@ nsec3ify(unsigned int hashalg, unsigned int iterations,
count--;
dns_name_split(nextname, count, NULL, nextname);
addnsec3(nextname, NULL, salt, salt_length,
- iterations, hashlist, zonettl);
+ iterations, hashlist, zone_soa_min_ttl);
}
}
dns_dbiterator_destroy(&dbiter);
@@ -2580,7 +2737,7 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
dns_fixedname_init(&fname);
name = dns_fixedname_name(&fname);
- result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL);
+ result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
if (result != ISC_R_SUCCESS)
fatal("failed converting name '%s' to dns format: %s",
origin, isc_result_totext(result));
@@ -2600,90 +2757,169 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) {
* private keys from disk.
*/
static void
-loadzonekeys(dns_db_t *db) {
+loadzonekeys(isc_boolean_t preserve_keys, isc_boolean_t load_public) {
dns_dbnode_t *node;
- dns_dbversion_t *currentversion;
+ dns_dbversion_t *currentversion = NULL;
isc_result_t result;
- dst_key_t *keys[20];
- unsigned int nkeys, i;
-
- currentversion = NULL;
- dns_db_currentversion(db, &currentversion);
+ dns_rdataset_t rdataset, keysigs, soasigs;
node = NULL;
- result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
+ result = dns_db_findnode(gdb, gorigin, ISC_FALSE, &node);
if (result != ISC_R_SUCCESS)
fatal("failed to find the zone's origin: %s",
isc_result_totext(result));
- result = dns_dnssec_findzonekeys(db, currentversion, node, gorigin,
- mctx, 20, keys, &nkeys);
- if (result == ISC_R_NOTFOUND)
- result = ISC_R_SUCCESS;
+ dns_db_currentversion(gdb, &currentversion);
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&soasigs);
+ dns_rdataset_init(&keysigs);
+
+ /* Make note of the keys which signed the SOA, if any */
+ result = dns_db_findrdataset(gdb, node, currentversion,
+ dns_rdatatype_soa, 0, 0,
+ &rdataset, &soasigs);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ /* Preserve the TTL of the DNSKEY RRset, if any */
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_db_findrdataset(gdb, node, currentversion,
+ dns_rdatatype_dnskey, 0, 0,
+ &rdataset, &keysigs);
+
if (result != ISC_R_SUCCESS)
- fatal("failed to find the zone keys: %s",
+ goto cleanup;
+
+ if (set_keyttl && keyttl != rdataset.ttl) {
+ fprintf(stderr, "User-specified TTL (%d) conflicts "
+ "with existing DNSKEY RRset TTL.\n",
+ keyttl);
+ fprintf(stderr, "Imported keys will use the RRSet "
+ "TTL (%d) instead.\n",
+ rdataset.ttl);
+ }
+ keyttl = rdataset.ttl;
+
+ /* Load keys corresponding to the existing DNSKEY RRset */
+ result = dns_dnssec_keylistfromrdataset(gorigin, directory, mctx,
+ &rdataset, &keysigs, &soasigs,
+ preserve_keys, load_public,
+ &keylist);
+ if (result != ISC_R_SUCCESS)
+ fatal("failed to load the zone keys: %s",
isc_result_totext(result));
- for (i = 0; i < nkeys; i++) {
- signer_key_t *key;
+ cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (dns_rdataset_isassociated(&keysigs))
+ dns_rdataset_disassociate(&keysigs);
+ if (dns_rdataset_isassociated(&soasigs))
+ dns_rdataset_disassociate(&soasigs);
+ dns_db_detachnode(gdb, &node);
+ dns_db_closeversion(gdb, &currentversion, ISC_FALSE);
+}
+
+static void
+loadexplicitkeys(char *keyfiles[], int n, isc_boolean_t setksk) {
+ isc_result_t result;
+ int i;
+
+ for (i = 0; i < n; i++) {
+ dns_dnsseckey_t *key = NULL;
+ dst_key_t *newkey = NULL;
+
+ result = dst_key_fromnamedfile(keyfiles[i], directory,
+ DST_TYPE_PUBLIC |
+ DST_TYPE_PRIVATE,
+ mctx, &newkey);
+ if (result != ISC_R_SUCCESS)
+ fatal("cannot load dnskey %s: %s", keyfiles[i],
+ isc_result_totext(result));
+
+ if (!dns_name_equal(gorigin, dst_key_name(newkey)))
+ fatal("key %s not at origin\n", keyfiles[i]);
+
+ if (!dst_key_isprivate(newkey))
+ fatal("cannot sign zone with non-private dnskey %s",
+ keyfiles[i]);
+
+ /* Skip any duplicates */
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ if (dst_key_id(key->key) == dst_key_id(newkey) &&
+ dst_key_alg(key->key) == dst_key_alg(newkey))
+ break;
+ }
+
+ if (key == NULL) {
+ /* We haven't seen this key before */
+ dns_dnsseckey_create(mctx, &newkey, &key);
+ ISC_LIST_APPEND(keylist, key, link);
+ key->source = dns_keysource_user;
+ } else {
+ dst_key_free(&key->key);
+ key->key = newkey;
+ }
+
+ key->force_publish = ISC_TRUE;
+ key->force_sign = ISC_TRUE;
- key = newkeystruct(keys[i], dst_key_isprivate(keys[i]));
- ISC_LIST_APPEND(keylist, key, link);
+ if (setksk)
+ key->ksk = ISC_TRUE;
}
- dns_db_detachnode(db, &node);
- dns_db_closeversion(db, &currentversion, ISC_FALSE);
}
-/*%
- * Finds all public zone keys in the zone.
- */
static void
-loadzonepubkeys(dns_db_t *db) {
- dns_dbversion_t *currentversion = NULL;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dst_key_t *pubkey;
- signer_key_t *key;
+report(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ putc('\n', stderr);
+}
+
+static void
+build_final_keylist() {
isc_result_t result;
+ dns_dbversion_t *ver = NULL;
+ dns_diff_t diff;
+ dns_dnsseckeylist_t matchkeys;
+ char name[DNS_NAME_FORMATSIZE];
- dns_db_currentversion(db, &currentversion);
+ /*
+ * Find keys that match this zone in the key repository.
+ */
+ ISC_LIST_INIT(matchkeys);
+ result = dns_dnssec_findmatchingkeys(gorigin, directory,
+ mctx, &matchkeys);
+ if (result == ISC_R_NOTFOUND)
+ result = ISC_R_SUCCESS;
+ check_result(result, "dns_dnssec_findmatchingkeys");
- result = dns_db_findnode(db, gorigin, ISC_FALSE, &node);
- if (result != ISC_R_SUCCESS)
- fatal("failed to find the zone's origin: %s",
- isc_result_totext(result));
+ result = dns_db_newversion(gdb, &ver);
+ check_result(result, "dns_db_newversion");
- dns_rdataset_init(&rdataset);
- result = dns_db_findrdataset(db, node, currentversion,
- dns_rdatatype_dnskey, 0, 0, &rdataset,
- NULL);
+ dns_diff_init(mctx, &diff);
+
+ /*
+ * Update keylist with information from from the key repository.
+ */
+ dns_dnssec_updatekeys(&keylist, &matchkeys, NULL, gorigin, keyttl,
+ &diff, ignore_kskflag, mctx, report);
+
+ dns_name_format(gorigin, name, sizeof(name));
+
+ result = dns_diff_applysilently(&diff, gdb, ver);
if (result != ISC_R_SUCCESS)
- fatal("failed to find keys at the zone apex: %s",
- isc_result_totext(result));
- result = dns_rdataset_first(&rdataset);
- check_result(result, "dns_rdataset_first");
- while (result == ISC_R_SUCCESS) {
- pubkey = NULL;
- dns_rdata_reset(&rdata);
- dns_rdataset_current(&rdataset, &rdata);
- result = dns_dnssec_keyfromrdata(gorigin, &rdata, mctx,
- &pubkey);
- if (result != ISC_R_SUCCESS)
- goto next;
- if (!dst_key_iszonekey(pubkey)) {
- dst_key_free(&pubkey);
- goto next;
- }
+ fatal("failed to update DNSKEY RRset at node '%s': %s",
+ name, isc_result_totext(result));
- key = newkeystruct(pubkey, ISC_FALSE);
- ISC_LIST_APPEND(keylist, key, link);
- next:
- result = dns_rdataset_next(&rdataset);
- }
- dns_rdataset_disassociate(&rdataset);
- dns_db_detachnode(db, &node);
- dns_db_closeversion(db, &currentversion, ISC_FALSE);
+ dns_db_closeversion(gdb, &ver, ISC_TRUE);
+
+ dns_diff_clear(&diff);
}
static void
@@ -2727,18 +2963,112 @@ warnifallksk(dns_db_t *db) {
dns_rdataset_disassociate(&rdataset);
dns_db_detachnode(db, &node);
dns_db_closeversion(db, &currentversion, ISC_FALSE);
- if (!have_non_ksk && !ignoreksk) {
+ if (!have_non_ksk && !ignore_kskflag) {
if (disable_zone_check)
- fprintf(stderr, "%s: warning: No non-KSK dnskey found. "
- "Supply non-KSK dnskey or use '-z'.\n",
+ fprintf(stderr, "%s: warning: No non-KSK DNSKEY found; "
+ "supply a ZSK or use '-z'.\n",
program);
else
- fatal("No non-KSK dnskey found. "
- "Supply non-KSK dnskey or use '-z'.");
+ fatal("No non-KSK DNSKEY found; "
+ "supply a ZSK or use '-z'.");
}
}
static void
+set_nsec3params(isc_boolean_t update_chain, isc_boolean_t set_salt,
+ isc_boolean_t set_optout, isc_boolean_t set_iter)
+{
+ isc_result_t result;
+ dns_dbversion_t *ver = NULL;
+ dns_dbnode_t *node = NULL;
+ dns_rdataset_t rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_nsec3_t nsec3;
+ dns_fixedname_t fname;
+ dns_name_t *hashname;
+ unsigned char orig_salt[256];
+ size_t orig_saltlen;
+ dns_hash_t orig_hash;
+ isc_uint16_t orig_iter;
+
+ dns_db_currentversion(gdb, &ver);
+ dns_rdataset_init(&rdataset);
+
+ orig_saltlen = sizeof(orig_salt);
+ result = dns_db_getnsec3parameters(gdb, ver, &orig_hash, NULL,
+ &orig_iter, orig_salt,
+ &orig_saltlen);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ nsec_datatype = dns_rdatatype_nsec3;
+
+ if (!update_chain && set_salt) {
+ if (salt_length != orig_saltlen ||
+ memcmp(saltbuf, orig_salt, salt_length) != 0)
+ fatal("An NSEC3 chain exists with a different salt. "
+ "Use -u to update it.");
+ } else if (!set_salt) {
+ salt_length = orig_saltlen;
+ memcpy(saltbuf, orig_salt, orig_saltlen);
+ salt = saltbuf;
+ }
+
+ if (!update_chain && set_iter) {
+ if (nsec3iter != orig_iter)
+ fatal("An NSEC3 chain exists with different "
+ "iterations. Use -u to update it.");
+ } else if (!set_iter)
+ nsec3iter = orig_iter;
+
+ /*
+ * Find an NSEC3 record to get the current OPTOUT value.
+ * (This assumes all NSEC3 records agree.)
+ */
+
+ dns_fixedname_init(&fname);
+ hashname = dns_fixedname_name(&fname);
+ result = dns_nsec3_hashname(&fname, NULL, NULL,
+ gorigin, gorigin, dns_hash_sha1,
+ orig_iter, orig_salt, orig_saltlen);
+ check_result(result, "dns_nsec3_hashname");
+
+ result = dns_db_findnsec3node(gdb, hashname, ISC_FALSE, &node);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_db_findrdataset(gdb, node, ver, dns_rdatatype_nsec3,
+ 0, 0, &rdataset, NULL);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = dns_rdataset_first(&rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdataset_current(&rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ if (!update_chain && set_optout) {
+ if (nsec3flags != nsec3.flags)
+ fatal("An NSEC3 chain exists with%s OPTOUT. "
+ "Use -u -%s to %s it.",
+ OPTOUT(nsec3.flags) ? "" : "out",
+ OPTOUT(nsec3.flags) ? "AA" : "A",
+ OPTOUT(nsec3.flags) ? "clear" : "set");
+ } else if (!set_optout)
+ nsec3flags = nsec3.flags;
+
+ dns_rdata_freestruct(&nsec3);
+
+ cleanup:
+ if (dns_rdataset_isassociated(&rdataset))
+ dns_rdataset_disassociate(&rdataset);
+ if (node != NULL)
+ dns_db_detachnode(gdb, &node);
+ dns_db_closeversion(gdb, &ver, ISC_FALSE);
+}
+
+static void
writeset(const char *prefix, dns_rdatatype_t type) {
char *filename;
char namestr[DNS_NAME_FORMATSIZE];
@@ -2755,7 +3085,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
isc_buffer_t namebuf;
isc_region_t r;
isc_result_t result;
- signer_key_t *key;
+ dns_dnsseckey_t *key, *tmpkey;
unsigned char dsbuf[DNS_DS_BUFFERSIZE];
unsigned char keybuf[DST_KEY_MAXSIZE];
unsigned int filenamelen;
@@ -2767,13 +3097,13 @@ writeset(const char *prefix, dns_rdatatype_t type) {
check_result(result, "dns_name_tofilenametext");
isc_buffer_putuint8(&namebuf, 0);
filenamelen = strlen(prefix) + strlen(namestr);
- if (directory != NULL)
- filenamelen += strlen(directory) + 1;
+ if (dsdir != NULL)
+ filenamelen += strlen(dsdir) + 1;
filename = isc_mem_get(mctx, filenamelen + 1);
if (filename == NULL)
fatal("out of memory");
- if (directory != NULL)
- sprintf(filename, "%s/", directory);
+ if (dsdir != NULL)
+ sprintf(filename, "%s/", dsdir);
else
filename[0] = 0;
strcat(filename, prefix);
@@ -2781,22 +3111,6 @@ writeset(const char *prefix, dns_rdatatype_t type) {
dns_diff_init(mctx, &diff);
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link))
- if (!key->isksk) {
- have_non_ksk = ISC_TRUE;
- break;
- }
-
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link))
- if (key->isksk) {
- have_ksk = ISC_TRUE;
- break;
- }
-
if (type == dns_rdatatype_dlv) {
dns_name_t tname;
unsigned int labels;
@@ -2815,7 +3129,28 @@ writeset(const char *prefix, dns_rdatatype_t type) {
key != NULL;
key = ISC_LIST_NEXT(key, link))
{
- if (have_ksk && have_non_ksk && !key->isksk)
+ if (REVOKE(key->key))
+ continue;
+ if (isksk(key)) {
+ have_ksk = ISC_TRUE;
+ have_non_ksk = ISC_FALSE;
+ } else {
+ have_ksk = ISC_FALSE;
+ have_non_ksk = ISC_TRUE;
+ }
+ for (tmpkey = ISC_LIST_HEAD(keylist);
+ tmpkey != NULL;
+ tmpkey = ISC_LIST_NEXT(tmpkey, link)) {
+ if (dst_key_alg(key->key) != dst_key_alg(tmpkey->key))
+ continue;
+ if (REVOKE(tmpkey->key))
+ continue;
+ if (isksk(tmpkey))
+ have_ksk = ISC_TRUE;
+ else
+ have_non_ksk = ISC_TRUE;
+ }
+ if (have_ksk && have_non_ksk && !isksk(key))
continue;
dns_rdata_init(&rdata);
dns_rdata_init(&ds);
@@ -2848,7 +3183,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
} else
result = dns_difftuple_create(mctx, DNS_DIFFOP_ADD,
- gorigin, zonettl,
+ gorigin, zone_soa_min_ttl,
&rdata, &tuple);
check_result(result, "dns_difftuple_create");
dns_diff_append(&diff, &tuple);
@@ -2893,6 +3228,9 @@ print_version(FILE *fp) {
fprintf(fp, "; dnssec_signzone version " VERSION "\n");
}
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
static void
usage(void) {
fprintf(stderr, "Usage:\n");
@@ -2903,14 +3241,18 @@ usage(void) {
fprintf(stderr, "Version: %s\n", VERSION);
fprintf(stderr, "Options: (default value in parenthesis) \n");
- fprintf(stderr, "\t-c class (IN)\n");
- fprintf(stderr, "\t-d directory\n");
- fprintf(stderr, "\t\tdirectory to find keyset files (.)\n");
+ fprintf(stderr, "\t-S:\tsmart signing: automatically finds key files\n"
+ "\t\tfor the zone and determines how they are to "
+ "be used\n");
+ fprintf(stderr, "\t-K directory:\n");
+ fprintf(stderr, "\t\tdirectory to find key files (.)\n");
+ fprintf(stderr, "\t-d directory:\n");
+ fprintf(stderr, "\t\tdirectory to find dsset-* files (.)\n");
fprintf(stderr, "\t-g:\t");
- fprintf(stderr, "generate DS records from keyset files\n");
+ fprintf(stderr, "update DS records based on child zones' "
+ "dsset-* files\n");
fprintf(stderr, "\t-s [YYYYMMDDHHMMSS|+offset]:\n");
- fprintf(stderr, "\t\tRRSIG start time - absolute|offset "
- "(now - 1 hour)\n");
+ fprintf(stderr, "\t\tRRSIG start time - absolute|offset (now - 1 hour)\n");
fprintf(stderr, "\t-e [YYYYMMDDHHMMSS|+offset|\"now\"+offset]:\n");
fprintf(stderr, "\t\tRRSIG end time - absolute|from start|from now "
"(now + 30 days)\n");
@@ -2918,8 +3260,7 @@ usage(void) {
fprintf(stderr, "\t\tcycle interval - resign "
"if < interval from end ( (end-start)/4 )\n");
fprintf(stderr, "\t-j jitter:\n");
- fprintf(stderr, "\t\trandomize signature end time up to jitter "
- "seconds\n");
+ fprintf(stderr, "\t\trandomize signature end time up to jitter seconds\n");
fprintf(stderr, "\t-v debuglevel (0)\n");
fprintf(stderr, "\t-o origin:\n");
fprintf(stderr, "\t\tzone origin (name of zonefile)\n");
@@ -2936,20 +3277,33 @@ usage(void) {
fprintf(stderr, "\t\ta file containing random data\n");
fprintf(stderr, "\t-a:\t");
fprintf(stderr, "verify generated signatures\n");
+ fprintf(stderr, "\t-c class (IN)\n");
+ fprintf(stderr, "\t-E engine:\n");
+#ifdef USE_PKCS11
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use "
+ "(default is \"pkcs11\")\n");
+#else
+ fprintf(stderr, "\t\tname of an OpenSSL engine to use\n");
+#endif
fprintf(stderr, "\t-p:\t");
fprintf(stderr, "use pseudorandom data (faster but less secure)\n");
fprintf(stderr, "\t-P:\t");
fprintf(stderr, "disable post-sign verification\n");
+ fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n");
fprintf(stderr, "\t-t:\t");
fprintf(stderr, "print statistics\n");
+ fprintf(stderr, "\t-u:\t");
+ fprintf(stderr, "update or replace an existing NSEC/NSEC3 chain\n");
+ fprintf(stderr, "\t-x:\tsign DNSKEY record with KSKs only, not ZSKs\n");
+ fprintf(stderr, "\t-z:\tsign all records with KSKs\n");
+ fprintf(stderr, "\t-C:\tgenerate a keyset file, for compatibility\n"
+ "\t\twith older versions of dnssec-signzone -g\n");
fprintf(stderr, "\t-n ncpus (number of cpus present)\n");
fprintf(stderr, "\t-k key_signing_key\n");
fprintf(stderr, "\t-l lookasidezone\n");
- fprintf(stderr, "\t-3 salt (NSEC3 salt)\n");
- fprintf(stderr, "\t-H iterations (NSEC3 iterations)\n");
- fprintf(stderr, "\t-A (NSEC3 optout)\n");
- fprintf(stderr, "\t-z:\t");
- fprintf(stderr, "ignore KSK flag in DNSKEYs");
+ fprintf(stderr, "\t-3 NSEC3 salt\n");
+ fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
+ fprintf(stderr, "\t-A NSEC3 optout\n");
fprintf(stderr, "\n");
@@ -3001,10 +3355,15 @@ main(int argc, char *argv[]) {
int ndskeys = 0;
char *endp;
isc_time_t timer_start, timer_finish;
- signer_key_t *key;
+ dns_dnsseckey_t *key;
isc_result_t result;
isc_log_t *log = NULL;
isc_boolean_t pseudorandom = ISC_FALSE;
+#ifdef USE_PKCS11
+ const char *engine = "pkcs11";
+#else
+ const char *engine = NULL;
+#endif
unsigned int eflags;
isc_boolean_t free_output = ISC_FALSE;
int tempfilelen;
@@ -3012,13 +3371,15 @@ main(int argc, char *argv[]) {
isc_task_t **tasks = NULL;
isc_buffer_t b;
int len;
- unsigned int iterations = 100U;
- const unsigned char *salt = NULL;
- size_t salt_length = 0;
- unsigned char saltbuf[255];
hashlist_t hashlist;
+ isc_boolean_t smartsign = ISC_FALSE;
+ isc_boolean_t make_keyset = ISC_FALSE;
+ isc_boolean_t set_salt = ISC_FALSE;
+ isc_boolean_t set_optout = ISC_FALSE;
+ isc_boolean_t set_iter = ISC_FALSE;
-#define CMDLINE_FLAGS "3:aAc:d:e:f:FghH:i:I:j:k:l:m:n:N:o:O:pPr:s:StUv:z"
+#define CMDLINE_FLAGS \
+ "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:xz"
/*
* Process memory debugging argument first.
@@ -3058,7 +3419,9 @@ main(int argc, char *argv[]) {
while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (ch) {
case '3':
- if (strcmp(isc_commandline_argument, "-")) {
+ set_salt = ISC_TRUE;
+ nsec_datatype = dns_rdatatype_nsec3;
+ if (strcmp(isc_commandline_argument, "-") != 0) {
isc_buffer_t target;
char *sarg;
@@ -3068,29 +3431,42 @@ main(int argc, char *argv[]) {
result = isc_hex_decodestring(sarg, &target);
check_result(result,
"isc_hex_decodestring(salt)");
- salt = saltbuf;
salt_length = isc_buffer_usedlength(&target);
- } else {
- salt = saltbuf;
- salt_length = 0;
}
- nsec_datatype = dns_rdatatype_nsec3;
break;
case 'A':
- nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
+ set_optout = ISC_TRUE;
+ if (OPTOUT(nsec3flags))
+ nsec3flags &= ~DNS_NSEC3FLAG_OPTOUT;
+ else
+ nsec3flags |= DNS_NSEC3FLAG_OPTOUT;
break;
case 'a':
tryverify = ISC_TRUE;
break;
+ case 'C':
+ make_keyset = ISC_TRUE;
+ break;
+
case 'c':
classname = isc_commandline_argument;
break;
case 'd':
- directory = isc_commandline_argument;
+ dsdir = isc_commandline_argument;
+ if (strlen(dsdir) == 0U)
+ fatal("DS directory must be non-empty string");
+ result = try_dir(dsdir);
+ if (result != ISC_R_SUCCESS)
+ fatal("cannot open directory %s: %s",
+ dsdir, isc_result_totext(result));
+ break;
+
+ case 'E':
+ engine = isc_commandline_argument;
break;
case 'e':
@@ -3106,11 +3482,11 @@ main(int argc, char *argv[]) {
break;
case 'H':
- iterations = strtoul(isc_commandline_argument,
- &endp, 0);
+ set_iter = ISC_TRUE;
+ nsec3iter = strtoul(isc_commandline_argument, &endp, 0);
if (*endp != '\0')
fatal("iterations must be numeric");
- if (iterations > 0xffffU)
+ if (nsec3iter > 0xffffU)
fatal("iterations too big");
break;
@@ -3118,6 +3494,10 @@ main(int argc, char *argv[]) {
usage();
break;
+ case 'I':
+ inputformatstr = isc_commandline_argument;
+ break;
+
case 'i':
endp = NULL;
cycle = strtol(isc_commandline_argument, &endp, 0);
@@ -3126,10 +3506,6 @@ main(int argc, char *argv[]) {
"positive");
break;
- case 'I':
- inputformatstr = isc_commandline_argument;
- break;
-
case 'j':
endp = NULL;
jitter = strtol(isc_commandline_argument, &endp, 0);
@@ -3137,6 +3513,10 @@ main(int argc, char *argv[]) {
fatal("jitter must be numeric and positive");
break;
+ case 'K':
+ directory = isc_commandline_argument;
+ break;
+
case 'k':
if (ndskeys == MAXDSKEYS)
fatal("too many key-signing keys specified");
@@ -3150,14 +3530,18 @@ main(int argc, char *argv[]) {
dns_fixedname_init(&dlv_fixed);
dlv = dns_fixedname_name(&dlv_fixed);
- result = dns_name_fromtext(dlv, &b, dns_rootname,
- ISC_FALSE, NULL);
+ result = dns_name_fromtext(dlv, &b, dns_rootname, 0,
+ NULL);
check_result(result, "dns_name_fromtext(dlv)");
break;
case 'm':
break;
+ case 'N':
+ serialformatstr = isc_commandline_argument;
+ break;
+
case 'n':
endp = NULL;
ntasks = strtol(isc_commandline_argument, &endp, 0);
@@ -3165,38 +3549,38 @@ main(int argc, char *argv[]) {
fatal("number of cpus must be numeric");
break;
- case 'N':
- serialformatstr = isc_commandline_argument;
+ case 'O':
+ outputformatstr = isc_commandline_argument;
break;
case 'o':
origin = isc_commandline_argument;
break;
- case 'O':
- outputformatstr = isc_commandline_argument;
+ case 'P':
+ disable_zone_check = ISC_TRUE;
break;
case 'p':
pseudorandom = ISC_TRUE;
break;
- case 'P':
- disable_zone_check = ISC_TRUE;
- break;
-
case 'r':
setup_entropy(mctx, isc_commandline_argument, &ectx);
break;
+ case 'S':
+ smartsign = ISC_TRUE;
+ break;
+
case 's':
startstr = isc_commandline_argument;
break;
- case 'S':
- /* This is intentionally undocumented */
- /* -S: simple output style */
- masterstyle = &dns_master_style_simple;
+ case 'T':
+ endp = NULL;
+ set_keyttl = ISC_TRUE;
+ keyttl = strtottl(isc_commandline_argument);
break;
case 't':
@@ -3207,6 +3591,10 @@ main(int argc, char *argv[]) {
unknownalg = ISC_TRUE;
break;
+ case 'u':
+ update_chain = ISC_TRUE;
+ break;
+
case 'v':
endp = NULL;
verbose = strtol(isc_commandline_argument, &endp, 0);
@@ -3214,8 +3602,12 @@ main(int argc, char *argv[]) {
fatal("verbose level must be numeric");
break;
+ case 'x':
+ keyset_kskonly = ISC_TRUE;
+ break;
+
case 'z':
- ignoreksk = ISC_TRUE;
+ ignore_kskflag = ISC_TRUE;
break;
case 'F':
@@ -3245,20 +3637,21 @@ main(int argc, char *argv[]) {
if (result != ISC_R_SUCCESS)
fatal("could not create hash context");
- result = dst_lib_init(mctx, ectx, eflags);
+ result = dst_lib_init2(mctx, ectx, engine, eflags);
if (result != ISC_R_SUCCESS)
- fatal("could not initialize dst");
+ fatal("could not initialize dst: %s",
+ isc_result_totext(result));
isc_stdtime_get(&now);
- if (startstr != NULL)
+ if (startstr != NULL) {
starttime = strtotime(startstr, now, now);
- else
+ } else
starttime = now - 3600; /* Allow for some clock skew. */
- if (endstr != NULL)
+ if (endstr != NULL) {
endtime = strtotime(endstr, now, starttime);
- else
+ } else
endtime = starttime + (30 * 24 * 60 * 60);
if (cycle == -1)
@@ -3270,6 +3663,9 @@ main(int argc, char *argv[]) {
rdclass = strtoclass(classname);
+ if (directory == NULL)
+ directory = ".";
+
setup_logging(verbose, mctx, &log);
argc -= isc_commandline_index;
@@ -3335,7 +3731,19 @@ main(int argc, char *argv[]) {
loadzone(file, origin, rdclass, &gdb);
gorigin = dns_db_origin(gdb);
gclass = dns_db_class(gdb);
- zonettl = soattl();
+ get_soa_ttls();
+
+ if (!set_keyttl)
+ keyttl = soa_ttl;
+
+ /*
+ * Check for any existing NSEC3 parameters in the zone,
+ * and use them as defaults if -u was not specified.
+ */
+ if (update_chain && !set_optout && !set_iter && !set_salt)
+ nsec_datatype = dns_rdatatype_nsec;
+ else
+ set_nsec3params(update_chain, set_salt, set_optout, set_iter);
if (IS_NSEC3) {
isc_boolean_t answer;
@@ -3356,95 +3764,42 @@ main(int argc, char *argv[]) {
ISC_LIST_INIT(keylist);
isc_rwlock_init(&keylist_lock, 0, 0);
- if (argc == 0) {
- loadzonekeys(gdb);
- } else {
- for (i = 0; i < argc; i++) {
- dst_key_t *newkey = NULL;
-
- result = dst_key_fromnamedfile(argv[i],
- DST_TYPE_PUBLIC |
- DST_TYPE_PRIVATE,
- mctx, &newkey);
- if (result != ISC_R_SUCCESS)
- fatal("cannot load dnskey %s: %s", argv[i],
- isc_result_totext(result));
-
- if (!dns_name_equal(gorigin, dst_key_name(newkey)))
- fatal("key %s not at origin\n", argv[i]);
-
- key = ISC_LIST_HEAD(keylist);
- while (key != NULL) {
- dst_key_t *dkey = key->key;
- if (dst_key_id(dkey) == dst_key_id(newkey) &&
- dst_key_alg(dkey) == dst_key_alg(newkey) &&
- dns_name_equal(dst_key_name(dkey),
- dst_key_name(newkey)))
- {
- if (!dst_key_isprivate(dkey))
- fatal("cannot sign zone with "
- "non-private dnskey %s",
- argv[i]);
- break;
- }
- key = ISC_LIST_NEXT(key, link);
- }
- if (key == NULL) {
- key = newkeystruct(newkey, ISC_TRUE);
- key->commandline = ISC_TRUE;
- ISC_LIST_APPEND(keylist, key, link);
- } else
- dst_key_free(&newkey);
- }
-
- loadzonepubkeys(gdb);
- }
-
- for (i = 0; i < ndskeys; i++) {
- dst_key_t *newkey = NULL;
-
- result = dst_key_fromnamedfile(dskeyfile[i],
- DST_TYPE_PUBLIC |
- DST_TYPE_PRIVATE,
- mctx, &newkey);
- if (result != ISC_R_SUCCESS)
- fatal("cannot load dnskey %s: %s", dskeyfile[i],
- isc_result_totext(result));
+ /*
+ * Fill keylist with:
+ * 1) Keys listed in the DNSKEY set that have
+ * private keys associated, *if* no keys were
+ * set on the command line.
+ * 2) ZSKs set on the command line
+ * 3) KSKs set on the command line
+ * 4) Any keys remaining in the DNSKEY set which
+ * do not have private keys associated and were
+ * not specified on the command line.
+ */
+ if (argc == 0 || smartsign)
+ loadzonekeys(!smartsign, ISC_FALSE);
+ loadexplicitkeys(argv, argc, ISC_FALSE);
+ loadexplicitkeys(dskeyfile, ndskeys, ISC_TRUE);
+ loadzonekeys(!smartsign, ISC_TRUE);
- if (!dns_name_equal(gorigin, dst_key_name(newkey)))
- fatal("key %s not at origin\n", dskeyfile[i]);
+ /*
+ * If we're doing smart signing, look in the key repository for
+ * key files with metadata, and merge them with the keylist
+ * we have now.
+ */
+ if (smartsign)
+ build_final_keylist();
- key = ISC_LIST_HEAD(keylist);
- while (key != NULL) {
- dst_key_t *dkey = key->key;
- if (dst_key_id(dkey) == dst_key_id(newkey) &&
- dst_key_alg(dkey) == dst_key_alg(newkey) &&
- dns_name_equal(dst_key_name(dkey),
- dst_key_name(newkey)))
- {
- /* Override key flags. */
- key->issigningkey = ISC_TRUE;
- key->isksk = ISC_TRUE;
- key->isdsk = ISC_FALSE;
- dst_key_free(&dkey);
- key->key = newkey;
- break;
- }
- key = ISC_LIST_NEXT(key, link);
- }
- if (key == NULL) {
- /* Override dnskey flags. */
- key = newkeystruct(newkey, ISC_TRUE);
- key->isksk = ISC_TRUE;
- key->isdsk = ISC_FALSE;
- ISC_LIST_APPEND(keylist, key, link);
- }
+ /* Now enumerate the key list */
+ for (key = ISC_LIST_HEAD(keylist);
+ key != NULL;
+ key = ISC_LIST_NEXT(key, link)) {
+ key->index = keycount++;
}
- if (ISC_LIST_EMPTY(keylist)) {
+ if (keycount == 0) {
if (disable_zone_check)
fprintf(stderr, "%s: warning: No keys specified "
- "or found\n", program);
+ "or found\n", program);
else
fatal("No signing keys specified or found.");
nokeys = ISC_TRUE;
@@ -3454,7 +3809,7 @@ main(int argc, char *argv[]) {
unsigned int max;
result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max);
check_result(result, "dns_nsec3_maxiterations()");
- if (iterations > max)
+ if (nsec3iter > max)
fatal("NSEC3 iterations too big for weakest DNSKEY "
"strength. Maximum iterations allowed %u.", max);
}
@@ -3478,15 +3833,18 @@ main(int argc, char *argv[]) {
break;
}
+ remove_duplicates();
+
if (IS_NSEC3)
- nsec3ify(dns_hash_sha1, iterations, salt, salt_length,
+ nsec3ify(dns_hash_sha1, nsec3iter, salt, salt_length,
&hashlist);
else
nsecify();
if (!nokeys) {
- writeset("keyset-", dns_rdatatype_dnskey);
writeset("dsset-", dns_rdatatype_ds);
+ if (make_keyset)
+ writeset("keyset-", dns_rdatatype_dnskey);
if (dlv != NULL) {
writeset("dlvset-", dns_rdatatype_dlv);
}
@@ -3591,8 +3949,7 @@ main(int argc, char *argv[]) {
while (!ISC_LIST_EMPTY(keylist)) {
key = ISC_LIST_HEAD(keylist);
ISC_LIST_UNLINK(keylist, key, link);
- dst_key_free(&key->key);
- isc_mem_put(mctx, key, sizeof(signer_key_t));
+ dns_dnsseckey_destroy(mctx, &key);
}
isc_mem_put(mctx, tempfile, tempfilelen);