+2710. [func] New 'dnssec-signzone -x' flag and 'dnskey-ksk-only'
+ zone option cause a zone to be signed with only KSKs
+ signing the DNSKEY RRset, not ZSKs. This reduces
+ the size of a DNSKEY answer. [RT #20340]
+
2709. [func] Added some data fields, currently unused, to the
private key file format, to allow implementation
of explicit key rollover in a future release
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dnssec-signzone.c,v 1.242 2009/10/09 06:09:21 each Exp $ */
+/* $Id: dnssec-signzone.c,v 1.243 2009/10/10 01:47:59 each Exp $ */
/*! \file */
#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
static isc_boolean_t removefile = ISC_FALSE;
static isc_boolean_t generateds = 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;
if (!issigningkey(key))
continue;
- if (iszsk(key) ||
- (isksk(key) && set->type == dns_rdatatype_dnskey &&
- dns_name_equal(name, gorigin))) {
+ if (set->type == dns_rdatatype_dnskey &&
+ dns_name_equal(name, gorigin)) {
+ isc_boolean_t have_ksk = isksk(key);;
+ dns_dnsseckey_t *tmpkey;
+
+ 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");
}
/*%
* 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.
#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;
}
fprintf(stderr, ".\n");
- if (!ignore_kskflag) {
+ if (!ignore_kskflag && !keyset_kskonly) {
for (i = 0; i < 256; i++) {
/*
* The counts should both be zero or both be non-zero.
*/
fprintf(stderr, "Zone signing complete:\n");
for (i = 0; i < 256; i++) {
- if ((zsk_algorithms[i] != 0) ||
- (ksk_algorithms[i] != 0) ||
- (standby_zsk[i] != 0) || (standby_ksk[i] != 0) ||
- (revoked_ksk[i] != 0) || (revoked_zsk[i] != 0)) {
+ 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)) {
alg_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 stand-by, %u revoked\n",
+ "%u active, %u %s, %u revoked\n",
(int) strlen(algbuf) + 13, "",
zsk_algorithms[i],
- standby_zsk[i], revoked_zsk[i]);
+ standby_zsk[i],
+ keyset_kskonly ? "present" : "stand-by",
+ revoked_zsk[i]);
}
}
}
isc_buffer_t namebuf;
isc_region_t r;
isc_result_t result;
- dns_dnsseckey_t *key;
+ dns_dnsseckey_t *key, *tmpkey;
unsigned char dsbuf[DNS_DS_BUFFERSIZE];
unsigned char keybuf[DST_KEY_MAXSIZE];
unsigned int filenamelen;
dns_diff_init(mctx, &diff);
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link))
- if (!isksk(key)) {
- have_non_ksk = ISC_TRUE;
- break;
- }
-
- for (key = ISC_LIST_HEAD(keylist);
- key != NULL;
- key = ISC_LIST_NEXT(key, link))
- if (isksk(key)) {
- have_ksk = ISC_TRUE;
- break;
- }
-
if (type == dns_rdatatype_dlv) {
dns_name_t tname;
unsigned int labels;
key != NULL;
key = ISC_LIST_NEXT(key, link))
{
+ 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);
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-3 NSEC3 salt\n");
fprintf(stderr, "\t-H NSEC3 iterations (10)\n");
fprintf(stderr, "\t-A NSEC3 optout\n");
- fprintf(stderr, "\t-z:\t");
- fprintf(stderr, "ignore KSK flag in DNSKEYs");
fprintf(stderr, "\n");
isc_boolean_t set_iter = ISC_FALSE;
#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:z"
+ "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.
fatal("verbose level must be numeric");
break;
+ case 'x':
+ keyset_kskonly = ISC_TRUE;
+ break;
+
case 'z':
ignore_kskflag = ISC_TRUE;
break;
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: dnssec-signzone.docbook,v 1.39 2009/10/05 17:30:49 fdupont Exp $ -->
+<!-- $Id: dnssec-signzone.docbook,v 1.40 2009/10/10 01:47:59 each Exp $ -->
<refentry id="man.dnssec-signzone">
<refentryinfo>
<date>June 05, 2009</date>
<arg><option>-t</option></arg>
<arg><option>-u</option></arg>
<arg><option>-v <replaceable class="parameter">level</replaceable></option></arg>
+ <arg><option>-x</option></arg>
<arg><option>-z</option></arg>
<arg><option>-3 <replaceable class="parameter">salt</replaceable></option></arg>
<arg><option>-H <replaceable class="parameter">iterations</replaceable></option></arg>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>-x</term>
+ <listitem>
+ <para>
+ Only sign the DNSKEY RRset with key-signing keys, and omit
+ signatures from zone-signing keys.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>-z</term>
<listitem>
<para>
- Ignore KSK flag on key when determining what to sign.
+ Ignore KSK flag on key when determining what to sign. This
+ causes KSK-flagged keys to sign all records, not just the
+ DNSKEY RRset.
</para>
</listitem>
</varlistentry>
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: config.c,v 1.102 2009/10/08 23:13:05 marka Exp $ */
+/* $Id: config.c,v 1.103 2009/10/10 01:47:59 each Exp $ */
/*! \file */
check-srv-cname warn;\n\
zero-no-soa-ttl yes;\n\
update-check-ksk yes;\n\
+ dnskey-ksk-only no;\n\
try-tcp-refresh yes; /* BIND 8 compat */\n\
};\n\
"
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- $Id: named.conf.docbook,v 1.41 2009/10/08 23:48:09 tbox Exp $ -->
+<!-- $Id: named.conf.docbook,v 1.42 2009/10/10 01:47:59 each Exp $ -->
<refentry>
<refentryinfo>
<date>Aug 13, 2004</date>
allow-update { <replaceable>address_match_element</replaceable>; ... };
allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
update-check-ksk <replaceable>boolean</replaceable>;
+ dnskey-ksk-only <replaceable>boolean</replaceable>;
masterfile-format ( text | raw );
notify <replaceable>notifytype</replaceable>;
allow-update { <replaceable>address_match_element</replaceable>; ... };
allow-update-forwarding { <replaceable>address_match_element</replaceable>; ... };
update-check-ksk <replaceable>boolean</replaceable>;
+ dnskey-ksk-only <replaceable>boolean</replaceable>;
masterfile-format ( text | raw );
notify <replaceable>notifytype</replaceable>;
<replaceable>rrtypelist</replaceable>; ...
};
update-check-ksk <replaceable>boolean</replaceable>;
+ dnskey-ksk-only <replaceable>boolean</replaceable>;
masterfile-format ( text | raw );
notify <replaceable>notifytype</replaceable>;
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: update.c,v 1.161 2009/10/08 23:48:09 tbox Exp $ */
+/* $Id: update.c,v 1.162 2009/10/10 01:47:59 each Exp $ */
#include <config.h>
return (result);
}
-static isc_boolean_t
-ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) {
- isc_boolean_t ret = ISC_FALSE;
- isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE;
- isc_result_t result;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdata_dnskey_t dnskey;
-
- dns_rdataset_init(&rdataset);
- CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
- CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
- &rdataset, NULL));
- CHECK(dns_rdataset_first(&rdataset));
- while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) {
- dns_rdataset_current(&rdataset, &rdata);
- CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
- if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
- == DNS_KEYOWNER_ZONE) {
- if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0)
- have_ksk = ISC_TRUE;
- else
- have_nonksk = ISC_TRUE;
- }
- dns_rdata_reset(&rdata);
- result = dns_rdataset_next(&rdataset);
- }
- if (have_ksk && have_nonksk)
- ret = ISC_TRUE;
- failure:
- if (dns_rdataset_isassociated(&rdataset))
- dns_rdataset_disassociate(&rdataset);
- if (node != NULL)
- dns_db_detachnode(db, &node);
- return (ret);
-}
-
/*%
* Add RRSIG records for an RRset, recording the change in "diff".
*/
dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
isc_stdtime_t inception, isc_stdtime_t expire,
- isc_boolean_t check_ksk)
+ isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
dns_rdata_t sig_rdata = DNS_RDATA_INIT;
isc_buffer_t buffer;
unsigned char data[1024]; /* XXX */
- unsigned int i;
+ unsigned int i, j;
isc_boolean_t added_sig = ISC_FALSE;
isc_mem_t *mctx = client->mctx;
(isc_stdtime_t) 0, &rdataset, NULL));
dns_db_detachnode(db, &node);
+#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) == 1)
+#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) == 1)
+#define ALG(x) dst_key_alg(x)
+
+ /*
+ * If we are honoring KSK flags then we need to check that we
+ * have both KSK and non-KSK keys that are not revoked per
+ * algorithm.
+ */
for (i = 0; i < nkeys; i++) {
+ isc_boolean_t both = ISC_FALSE;
- if (check_ksk && type != dns_rdatatype_dnskey &&
- (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
+ if (!dst_key_isprivate(keys[i]))
continue;
- if (!dst_key_isprivate(keys[i]))
+ if (check_ksk && !REVOKE(keys[i])) {
+ isc_boolean_t have_ksk, have_nonksk;
+ if (KSK(keys[i])) {
+ have_ksk = ISC_TRUE;
+ have_nonksk = ISC_FALSE;
+ } else {
+ have_ksk = ISC_FALSE;
+ have_nonksk = ISC_TRUE;
+ }
+ for (j = 0; j < nkeys; j++) {
+ if (j == i || ALG(keys[i]) != ALG(keys[j]))
+ continue;
+ if (REVOKE(keys[j]))
+ continue;
+ if (KSK(keys[j]))
+ have_ksk = ISC_TRUE;
+ else
+ have_nonksk = ISC_TRUE;
+ both = have_ksk && have_nonksk;
+ if (both)
+ break;
+ }
+ }
+
+ if (both) {
+ if (type == dns_rdatatype_dnskey) {
+ if (!KSK(keys[i]) && keyset_kskonly)
+ continue;
+ } else if (!KSK(keys[i]))
+ continue;
+ } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
continue;
/* Calculate the signature, creating a RRSIG RDATA. */
dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut,
dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
isc_stdtime_t inception, isc_stdtime_t expire,
- isc_boolean_t check_ksk)
+ isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
{
isc_result_t result;
dns_dbnode_t *node;
if (flag)
continue;;
result = add_sigs(client, zone, db, ver, name, type, diff,
- keys, nkeys, inception, expire, check_ksk);
+ keys, nkeys, inception, expire,
+ check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS)
goto cleanup_iterator;
}
static isc_result_t
update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
dns_dbversion_t *oldver, dns_dbversion_t *newver,
- dns_diff_t *diff, isc_uint32_t sigvalidityinterval,
- isc_boolean_t *deleted_zsk)
+ dns_diff_t *diff, isc_uint32_t sigvalidityinterval)
{
isc_result_t result;
dns_difftuple_t *t;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t rdataset;
dns_dbnode_t *node = NULL;
- isc_boolean_t check_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly;
isc_boolean_t unsecure;
isc_boolean_t cut;
dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
*/
check_ksk = ISC_TF((dns_zone_getoptions(zone) &
DNS_ZONEOPT_UPDATECHECKKSK) != 0);
- /*
- * If we are not checking the ZSK flag then all DNSKEY's are
- * already signing all RRsets so we don't need to trigger special
- * changes.
- */
- if (*deleted_zsk && (!check_ksk || !ksk_sanity(db, oldver)))
- *deleted_zsk = ISC_FALSE;
-
- if (check_ksk) {
- check_ksk = ksk_sanity(db, newver);
- if (!check_ksk && ksk_sanity(db, oldver))
- update_log(client, zone, ISC_LOG_WARNING,
- "disabling update-check-ksk");
- }
-
- /*
- * If we have deleted a ZSK and we we still have some ZSK's
- * we don't need to convert the KSK's to a ZSK's.
- */
- if (*deleted_zsk && check_ksk)
- *deleted_zsk = ISC_FALSE;
+ keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) &
+ DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
/*
* Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
CHECK(add_sigs(client, zone, db, newver, name,
type, &sig_diff, zone_keys,
nkeys, inception, expire,
- check_ksk));
+ check_ksk, keyset_kskonly));
}
skip:
/* Skip any other updates to the same RRset. */
}
CHECK(add_exposed_sigs(client, zone, db, newver, name,
cut, diff, zone_keys, nkeys,
- inception, expire, check_ksk));
+ inception, expire, check_ksk,
+ keyset_kskonly));
}
}
CHECK(add_sigs(client, zone, db, newver, &t->name,
dns_rdatatype_nsec, &sig_diff,
zone_keys, nkeys, inception, expire,
- check_ksk));
+ check_ksk, keyset_kskonly));
} else {
INSIST(0);
}
} else {
CHECK(add_exposed_sigs(client, zone, db, newver, name,
cut, diff, zone_keys, nkeys,
- inception, expire, check_ksk));
+ inception, expire, check_ksk,
+ keyset_kskonly));
CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl,
unsecure, privatetype,
&nsec_diff));
CHECK(add_sigs(client, zone, db, newver, &t->name,
dns_rdatatype_nsec3,
&sig_diff, zone_keys, nkeys,
- inception, expire, check_ksk));
+ inception, expire, check_ksk,
+ keyset_kskonly));
} else {
INSIST(0);
}
dns_fixedname_t tmpnamefixed;
dns_name_t *tmpname = NULL;
unsigned int options;
- isc_boolean_t deleted_zsk;
dns_difftuple_t *tuple;
dns_rdata_dnskey_t dnskey;
unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
isc_uint32_t interval;
interval = dns_zone_getsigvalidityinterval(zone);
result = update_signatures(client, zone, db, oldver,
- ver, &diff, interval,
- &deleted_zsk);
+ ver, &diff, interval);
if (result != ISC_R_SUCCESS) {
update_log(client, zone,
ISC_LOG_ERROR,
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zoneconf.c,v 1.155 2009/10/08 23:13:06 marka Exp $ */
+/* $Id: zoneconf.c,v 1.156 2009/10/10 01:47:59 each Exp $ */
/*% */
dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
cfg_obj_asboolean(obj));
+ obj = NULL;
+ result = ns_config_get(maps, "dnskey-ksk-only", &obj);
+ INSIST(result == ISC_R_SUCCESS);
+ dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
+ cfg_obj_asboolean(obj));
} else if (ztype == dns_zone_slave) {
RETERR(configure_zone_acl(zconfig, vconfig, config,
allow_update_forwarding, ac, zone,
- PERFORMANCE OF THIS SOFTWARE.
-->
-<!-- File: $Id: Bv9ARM-book.xml,v 1.431 2009/10/08 23:13:06 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.432 2009/10/10 01:47:59 each Exp $ -->
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<title>BIND 9 Administrator Reference Manual</title>
<optional> allow-update { <replaceable>address_match_list</replaceable> }; </optional>
<optional> allow-update-forwarding { <replaceable>address_match_list</replaceable> }; </optional>
<optional> update-check-ksk <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dnskey-ksk-only <replaceable>yes_or_no</replaceable>; </optional>
<optional> secure-to-insecure <replaceable>yes_or_no</replaceable> ;</optional>
<optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
<optional> allow-v6-synthesis { <replaceable>address_match_list</replaceable> }; </optional>
request to a secure zone, check the KSK flag on
the DNSKEY RR to determine if this key should be
used to generate the RRSIG. This flag is ignored
- if there are not DNSKEY RRs both with and without
- a KSK.
+ if there are not non-revoked DNSKEY RRs both with
+ and without a KSK for the algorithm.
The default is <command>yes</command>.
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>dnskey-ksk-only</command></term>
+ <listitem>
+ <para>
+ When regenerating the RRSIGs following a UPDATE
+ request to a secure zone and
+ <command>update-check-ksk</command> is true then
+ only generate signatures DNSKEY RRSIG using DNSKEY's
+ with the KSK bit set. This flag is ignored if there
+ are not non-revoked DNSKEY RRs both with and without
+ a KSK for the algorithm.
+ The default is <command>no</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><command>try-tcp-refresh</command></term>
<listitem>
<optional> allow-transfer { <replaceable>address_match_list</replaceable> }; </optional>
<optional> allow-update-forwarding { <replaceable>address_match_list</replaceable> }; </optional>
<optional> update-check-ksk <replaceable>yes_or_no</replaceable>; </optional>
+ <optional> dnskey-ksk-only <replaceable>yes_or_no</replaceable>; </optional>
<optional> secure-to-insecure <replaceable>yes_or_no</replaceable> ; </optional>
<optional> try-tcp-refresh <replaceable>yes_or_no</replaceable>; </optional>
<optional> also-notify { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ;
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><command>dnskey-ksk-only</command></term>
+ <listitem>
+ <para>
+ See the description of
+ <command>dnskey-ksk-only</command> in <xref linkend="boolean_options"/>.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><command>try-tcp-refresh</command></term>
<listitem>
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: check.c,v 1.109 2009/10/08 23:13:06 marka Exp $ */
+/* $Id: check.c,v 1.110 2009/10/10 01:48:00 each Exp $ */
/*! \file */
{ "check-srv-cname", MASTERZONE },
{ "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
{ "update-check-ksk", MASTERZONE },
+ { "dnskey-ksk-only", MASTERZONE },
{ "try-tcp-refresh", SLAVEZONE },
};
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.h,v 1.168 2009/10/08 23:13:07 marka Exp $ */
+/* $Id: zone.h,v 1.169 2009/10/10 01:48:00 each Exp $ */
#ifndef DNS_ZONE_H
#define DNS_ZONE_H 1
#define DNS_ZONEOPT_NOTIFYTOSOA 0x02000000U /*%< Notify the SOA MNAME */
#define DNS_ZONEOPT_NSEC3TESTZONE 0x04000000U /*%< nsec3-test-zone */
#define DNS_ZONEOPT_SECURETOINSECURE 0x08000000U /*%< secure-to-insecure */
+#define DNS_ZONEOPT_DNSKEYKSKONLY 0x10000000U /*%< dnskey-ksk-only */
#ifndef NOMINUM_PUBLIC
/*
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.513 2009/10/08 23:58:14 marka Exp $ */
+/* $Id: zone.c,v 1.514 2009/10/10 01:48:00 each Exp $ */
/*! \file */
#define MAXZONEKEYS 10
-static isc_boolean_t
-ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) {
- isc_boolean_t ret = ISC_FALSE;
- isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE;
- isc_result_t result;
- dns_dbnode_t *node = NULL;
- dns_rdataset_t rdataset;
- dns_rdata_t rdata = DNS_RDATA_INIT;
- dns_rdata_dnskey_t dnskey;
-
- dns_rdataset_init(&rdataset);
- CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
- CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
- &rdataset, NULL));
- CHECK(dns_rdataset_first(&rdataset));
- while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) {
- dns_rdataset_current(&rdataset, &rdata);
- CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
- if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
- == DNS_KEYOWNER_ZONE) {
- if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0)
- have_ksk = ISC_TRUE;
- else
- have_nonksk = ISC_TRUE;
- }
- dns_rdata_reset(&rdata);
- result = dns_rdataset_next(&rdataset);
- }
- if (have_ksk && have_nonksk)
- ret = ISC_TRUE;
- failure:
- if (dns_rdataset_isassociated(&rdataset))
- dns_rdataset_disassociate(&rdataset);
- if (node != NULL)
- dns_db_detachnode(db, &node);
- return (ret);
-}
-
static isc_result_t
find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
isc_mem_t *mctx, unsigned int maxkeys,
add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
- isc_stdtime_t expire, isc_boolean_t check_ksk)
+ isc_stdtime_t expire, isc_boolean_t check_ksk,
+ isc_boolean_t keyset_kskonly)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
dns_rdata_t sig_rdata = DNS_RDATA_INIT;
unsigned char data[1024]; /* XXX */
isc_buffer_t buffer;
- unsigned int i;
+ unsigned int i, j;
dns_rdataset_init(&rdataset);
isc_buffer_init(&buffer, data, sizeof(data));
goto failure;
}
+#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) == 1)
+#define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) == 1)
+#define ALG(x) dst_key_alg(x)
+
for (i = 0; i < nkeys; i++) {
- if (check_ksk && type != dns_rdatatype_dnskey &&
- (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
- continue;
+ isc_boolean_t both = ISC_FALSE;
+
if (!dst_key_isprivate(keys[i]))
continue;
+
+ if (check_ksk && !REVOKE(keys[i])) {
+ isc_boolean_t have_ksk, have_nonksk;
+ if (KSK(keys[i])) {
+ have_ksk = ISC_TRUE;
+ have_nonksk = ISC_FALSE;
+ } else {
+ have_ksk = ISC_FALSE;
+ have_nonksk = ISC_TRUE;
+ }
+ for (j = 0; j < nkeys; j++) {
+ if (j == i || ALG(keys[i]) != ALG(keys[j]))
+ continue;
+ if (REVOKE(keys[j]))
+ continue;
+ if (KSK(keys[j]))
+ have_ksk = ISC_TRUE;
+ else
+ have_nonksk = ISC_TRUE;
+ both = have_ksk && have_nonksk;
+ if (both)
+ break;
+ }
+ }
+ if (both) {
+ if (type == dns_rdatatype_dnskey) {
+ if (!KSK(keys[i]) && keyset_kskonly)
+ continue;
+ } else if (!KSK(keys[i]))
+ continue;
+ } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
+ continue;
+
/* Calculate the signature, creating a RRSIG RDATA. */
CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
&inception, &expire,
dns_rdataset_t rdataset;
dns_rdatatype_t covers;
dst_key_t *zone_keys[MAXZONEKEYS];
- isc_boolean_t check_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
isc_result_t result;
isc_stdtime_t now, inception, soaexpire, expire, stop;
isc_uint32_t jitter;
stop = now + 5;
check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
- if (check_ksk)
- check_ksk = ksk_sanity(db, version);
+ keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
name = dns_fixedname_name(&fixed);
result = dns_db_getsigningtime(db, &rdataset, name);
}
result = add_sigs(db, version, name, covers, &sig_diff,
zone_keys, nkeys, zone->mctx, inception,
- expire, check_ksk);
+ expire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:add_sigs -> %s\n",
*/
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
&sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk);
+ soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_resigninc:add_sigs -> %s\n",
isc_boolean_t build_nsec, dst_key_t *key,
isc_stdtime_t inception, isc_stdtime_t expire,
unsigned int minimum, isc_boolean_t is_ksk,
- isc_boolean_t *delegation, dns_diff_t *diff,
- isc_int32_t *signatures, isc_mem_t *mctx)
+ isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
+ dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
{
isc_result_t result;
dns_rdatasetiter_t *iterator = NULL;
if (rdataset.type == dns_rdatatype_soa ||
rdataset.type == dns_rdatatype_rrsig)
goto next_rdataset;
- if (is_ksk && rdataset.type != dns_rdatatype_dnskey)
+ if (rdataset.type == dns_rdatatype_dnskey) {
+ if (!is_ksk && keyset_kskonly)
+ goto next_rdataset;
+ } else if (is_ksk)
goto next_rdataset;
if (*delegation &&
rdataset.type != dns_rdatatype_ds &&
update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
- isc_boolean_t check_ksk, dns_diff_t *sig_diff)
+ isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
+ dns_diff_t *sig_diff)
{
dns_difftuple_t *tuple;
isc_result_t result;
result = add_sigs(db, version, &tuple->name,
tuple->rdata.type, sig_diff,
zone_keys, nkeys, zone->mctx, inception,
- expire, check_ksk);
+ expire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"update_sigs:add_sigs -> %s\n",
dns_nsec3chainlist_t cleanup;
dst_key_t *zone_keys[MAXZONEKEYS];
isc_int32_t signatures;
- isc_boolean_t check_ksk, is_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
isc_boolean_t delegation;
isc_boolean_t first;
isc_result_t result;
stop = now + 5;
check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
- if (check_ksk)
- check_ksk = ksk_sanity(db, version);
+ keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
/*
* We keep pulling nodes off each iterator in turn until
*/
result = update_sigs(&nsec3_diff, db, version, zone_keys,
nkeys, zone, inception, expire, now,
- check_ksk, &sig_diff);
+ check_ksk, keyset_kskonly, &sig_diff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"update_sigs -> %s\n", dns_result_totext(result));
*/
result = update_sigs(¶m_diff, db, version, zone_keys,
nkeys, zone, inception, expire, now,
- check_ksk, &sig_diff);
+ check_ksk, keyset_kskonly, &sig_diff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"update_sigs -> %s\n", dns_result_totext(result));
result = update_sigs(&nsec_diff, db, version, zone_keys,
nkeys, zone, inception, expire, now,
- check_ksk, &sig_diff);
+ check_ksk, keyset_kskonly, &sig_diff);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"update_sigs -> %s\n", dns_result_totext(result));
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
&sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk);
+ soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
"add_sigs -> %s\n", dns_result_totext(result));
dns_signinglist_t cleanup;
dst_key_t *zone_keys[MAXZONEKEYS];
isc_int32_t signatures;
- isc_boolean_t check_ksk, is_ksk;
+ isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
isc_boolean_t commit = ISC_FALSE;
isc_boolean_t delegation;
isc_boolean_t finishedakey = ISC_FALSE;
unsigned int nkeys = 0;
isc_uint32_t nodes;
isc_boolean_t was_ksk;
- isc_boolean_t have_ksk;
- isc_boolean_t have_nonksk;
dns_rdataset_init(&rdataset);
dns_fixedname_init(&fixed);
signing = ISC_LIST_HEAD(zone->signing);
first = ISC_TRUE;
+ check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
+ keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
+
/*
* If we have already determined that we are building a NSEC chain
* continue to do so otherwise workout which type of chain we need
delegation = ISC_FALSE;
- /*
- * ksk_sanity() accounting for the key to be removed.
- */
-
was_ksk = ISC_FALSE;
- have_ksk = ISC_FALSE;
- have_nonksk = ISC_FALSE;
- for (i = 0, j = 0; i < nkeys; i++) {
+ if (first && signing->delete) {
/*
- * Find the key we want to remove.
+ * Remove the key we are deleting from consideration.
*/
- if (signing->delete &&
- dst_key_alg(zone_keys[i]) == signing->algorithm &&
- dst_key_id(zone_keys[i]) == signing->keyid) {
- if ((dst_key_flags(zone_keys[j]) &
- DNS_KEYFLAG_KSK) != 0)
- was_ksk = ISC_TRUE;
- dst_key_free(&zone_keys[i]);
+ for (i = 0, j = 0; i < nkeys; i++) {
+ /*
+ * Find the key we want to remove.
+ */
+ if (ALG(zone_keys[i]) == signing->algorithm &&
+ dst_key_id(zone_keys[i]) == signing->keyid) {
+ if (KSK(zone_keys[i]))
+ dst_key_free(&zone_keys[i]);
+ continue;
+ }
+ zone_keys[j] = zone_keys[i];
+ j++;
}
- zone_keys[j] = zone_keys[i];
- if ((dst_key_flags(zone_keys[j]) &
- DNS_KEYFLAG_KSK) != 0)
- have_ksk = ISC_TRUE;
- else
- have_nonksk = ISC_TRUE;
- j++;
+ nkeys = j;
}
- check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
- if (check_ksk && (!have_nonksk || !have_ksk))
- check_ksk = ISC_FALSE;
- nkeys = j;
-
dns_dbiterator_current(signing->dbiterator, &node, name);
if (signing->delete) {
signing->algorithm, signing->keyid,
&sig_diff));
}
+
/*
* On the first pass we need to check if the current node
* has not been obscured.
*/
dns_dbiterator_pause(signing->dbiterator);
for (i = 0; i < nkeys; i++) {
+ isc_boolean_t both = ISC_FALSE;
+
/*
* Find the keys we want to sign with.
*/
if (!dst_key_isprivate(zone_keys[i]))
continue;
- if ((!signing->delete || was_ksk || check_ksk) &&
+
+ /*
+ * When adding look for the specific key.
+ */
+ if (!signing->delete &&
(dst_key_alg(zone_keys[i]) != signing->algorithm ||
dst_key_id(zone_keys[i]) != signing->keyid))
continue;
+
+ /*
+ * When deleting make sure we are properly signed
+ * with the algorithm that was being removed.
+ */
+ if (signing->delete &&
+ ALG(zone_keys[i]) != signing->algorithm)
+ continue;
+
/*
* Do we do KSK processing?
*/
- is_ksk = ISC_FALSE;
- if (check_ksk &&
- (dst_key_flags(zone_keys[i]) & DNS_KEYFLAG_KSK) != 0)
- is_ksk = ISC_TRUE;
+ if (check_ksk && !REVOKE(zone_keys[i])) {
+ isc_boolean_t have_ksk, have_nonksk;
+ if (KSK(zone_keys[i])) {
+ have_ksk = ISC_TRUE;
+ have_nonksk = ISC_FALSE;
+ } else {
+ have_ksk = ISC_FALSE;
+ have_nonksk = ISC_TRUE;
+ }
+ for (j = 0; j < nkeys; j++) {
+ if (j == i ||
+ ALG(zone_keys[i]) !=
+ ALG(zone_keys[j]))
+ continue;
+ if (REVOKE(zone_keys[j]))
+ continue;
+ if (KSK(zone_keys[j]))
+ have_ksk = ISC_TRUE;
+ else
+ have_nonksk = ISC_TRUE;
+ both = have_ksk && have_nonksk;
+ if (both)
+ break;
+ }
+ }
+ if (both)
+ is_ksk = KSK(zone_keys[i]);
+ else
+ is_ksk = ISC_FALSE;
CHECK(sign_a_node(db, name, node, version, build_nsec3,
build_nsec, zone_keys[i], inception,
expire, zone->minimum, is_ksk,
- &delegation, &sig_diff, &signatures,
- zone->mctx));
- break;
+ ISC_TF(both && keyset_kskonly),
+ &delegation, &sig_diff,
+ &signatures, zone->mctx));
+ /*
+ * If we are adding we are done. Look for other keys
+ * of the same algorithm if deleting.
+ */
+ if (!signing->delete)
+ break;
}
+
/*
* Go onto next node.
*/
first = ISC_TRUE;
}
- /*
- * Recompute check_ksk as it may have changed.
- */
- check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
- if (check_ksk)
- check_ksk = ksk_sanity(db, version);
-
if (secureupdated) {
/*
* We have changed the NSEC RRset above so we need to update
result = add_sigs(db, version, &zone->origin,
dns_rdatatype_nsec, &sig_diff, zone_keys,
nkeys, zone->mctx, inception, soaexpire,
- check_ksk);
+ check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:add_sigs -> %s\n",
result = add_sigs(db, version, &zone->origin,
zone->privatetype, &sig_diff,
zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk);
+ soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:add_sigs -> %s\n",
*/
result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
&sig_diff, zone_keys, nkeys, zone->mctx, inception,
- soaexpire, check_ksk);
+ soaexpire, check_ksk, keyset_kskonly);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"zone_sign:add_sigs -> %s\n",
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: namedconf.c,v 1.106 2009/10/08 23:13:07 marka Exp $ */
+/* $Id: namedconf.c,v 1.107 2009/10/10 01:48:00 each Exp $ */
/*! \file */
{ "check-srv-cname", &cfg_type_checkmode, 0 },
{ "check-wildcard", &cfg_type_boolean, 0 },
{ "dialup", &cfg_type_dialuptype, 0 },
+ { "dnskey-ksk-only", &cfg_type_boolean, 0 },
{ "forward", &cfg_type_forwardtype, 0 },
{ "forwarders", &cfg_type_portiplist, 0 },
{ "key-directory", &cfg_type_qstring, 0 },