]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2710. [func] New 'dnssec-signzone -x' flag and 'dnskey-ksk-only'
authorEvan Hunt <each@isc.org>
Sat, 10 Oct 2009 01:48:00 +0000 (01:48 +0000)
committerEvan Hunt <each@isc.org>
Sat, 10 Oct 2009 01:48:00 +0000 (01:48 +0000)
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]

12 files changed:
CHANGES
bin/dnssec/dnssec-signzone.c
bin/dnssec/dnssec-signzone.docbook
bin/named/config.c
bin/named/named.conf.docbook
bin/named/update.c
bin/named/zoneconf.c
doc/arm/Bv9ARM-book.xml
lib/bind9/check.c
lib/dns/include/dns/zone.h
lib/dns/zone.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index 9b333880c7eed08914f89aa8405d9282a034f1fb..3472b24680628aa043120836cd57125f1543d769 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,8 @@
+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
index 1059d0b99edcf188f83863732a950a10154c6c9d..5d1634cf3fa42895190ee3fd8da59bbdab20787a 100644 (file)
@@ -29,7 +29,7 @@
  * 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 */
 
@@ -101,6 +101,8 @@ 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
 
@@ -158,6 +160,7 @@ 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 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;
@@ -579,9 +582,27 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name,
                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");
                }
@@ -1422,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.
@@ -1492,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;
@@ -1591,7 +1613,7 @@ verifyzone(void) {
        }
        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.
@@ -1708,20 +1730,24 @@ verifyzone(void) {
                 */
                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]);
                        }
                }
        }
@@ -3136,7 +3162,7 @@ writeset(const char *prefix, dns_rdatatype_t type) {
        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;
@@ -3162,22 +3188,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 (!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;
@@ -3196,6 +3206,27 @@ writeset(const char *prefix, dns_rdatatype_t type) {
             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);
@@ -3340,6 +3371,8 @@ usage(void) {
        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");
@@ -3348,8 +3381,6 @@ usage(void) {
        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");
 
@@ -3424,7 +3455,7 @@ main(int argc, char *argv[]) {
        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.
@@ -3644,6 +3675,10 @@ main(int argc, char *argv[]) {
                                fatal("verbose level must be numeric");
                        break;
 
+               case 'x':
+                       keyset_kskonly = ISC_TRUE;
+                       break;
+
                case 'z':
                        ignore_kskflag = ISC_TRUE;
                        break;
index aa3d506220b53abbdc792b1dc18d5fc0f8195f39..20c926ca9800aa4fd4c0d27006de47881cc1e2de 100644 (file)
@@ -18,7 +18,7 @@
  - 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>
@@ -83,6 +83,7 @@
       <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>
index 5b8abd6d9dd4db7b0f3a8c61557e26bc4a972046..39a8ba7ac6e6329fe69c99cebd552d82ec81a139 100644 (file)
@@ -15,7 +15,7 @@
  * 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 */
 
@@ -200,6 +200,7 @@ options {\n\
        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\
 "
index 87ba9b192b0be891d20f29e03973ed5ec6e609ca..a570654e15087006aac2e0bc8c369c6cc3e99f50 100644 (file)
@@ -17,7 +17,7 @@
  - 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>
@@ -292,6 +292,7 @@ options {
        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>;
@@ -457,6 +458,7 @@ view <replaceable>string</replaceable> <replaceable>optional_class</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>;
@@ -551,6 +553,7 @@ zone <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
                <replaceable>rrtypelist</replaceable>; ...
        };
        update-check-ksk <replaceable>boolean</replaceable>;
+       dnskey-ksk-only <replaceable>boolean</replaceable>;
 
        masterfile-format ( text | raw );
        notify <replaceable>notifytype</replaceable>;
index 406043d1c62d39c6a3dddb2f4cf977f92e93639c..59fc045872f1f9ea686485a068a912512ea3ba2d 100644 (file)
@@ -15,7 +15,7 @@
  * 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>
 
@@ -1810,44 +1810,6 @@ find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
        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".
  */
@@ -1856,7 +1818,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, 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_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;
@@ -1864,7 +1826,7 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
        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;
 
@@ -1880,13 +1842,52 @@ add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                                  (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. */
@@ -1997,7 +1998,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                 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;
@@ -2043,7 +2044,8 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                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;
        }
@@ -2073,8 +2075,7 @@ add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
 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;
@@ -2093,7 +2094,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
        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);
@@ -2126,27 +2127,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
         */
        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.
@@ -2213,7 +2195,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                                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. */
@@ -2365,7 +2347,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                        }
                        CHECK(add_exposed_sigs(client, zone, db, newver, name,
                                               cut, diff, zone_keys, nkeys,
-                                              inception, expire, check_ksk));
+                                              inception, expire, check_ksk,
+                                              keyset_kskonly));
                }
        }
 
@@ -2427,7 +2410,7 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                        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);
                }
@@ -2523,7 +2506,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                } 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));
@@ -2557,7 +2541,8 @@ update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db,
                        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);
                }
@@ -3503,7 +3488,6 @@ update_action(isc_task_t *task, isc_event_t *event) {
        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];
@@ -4107,8 +4091,7 @@ update_action(isc_task_t *task, isc_event_t *event) {
                        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,
index 0e58d0ad6f0ac8e56b71622765a1302b57f6b4f9..2529bacb5a2c49d88bb82878371f98b5683c9b06 100644 (file)
@@ -15,7 +15,7 @@
  * 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 $ */
 
 /*% */
 
@@ -859,6 +859,11 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
                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,
index 7ab3bf149607d5ad2289c13ccd17ca6eb789587e..1867f687ff376a9203cd8230ade16e20f347c71c 100644 (file)
@@ -18,7 +18,7 @@
  - 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>
 
@@ -4891,6 +4891,7 @@ badresp:1,adberr:0,findfail:0,valfail:0]
     <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>
@@ -6425,13 +6426,29 @@ options {
                  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>
@@ -9359,6 +9376,7 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
     <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> ;
@@ -9871,6 +9889,16 @@ zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replacea
                 </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>
index c808adc2b78bc761f86011e9bec12a1a0b1c4c3f..026dbb191107f494f2080d5d5817bff0e19080ee 100644 (file)
@@ -15,7 +15,7 @@
  * 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 */
 
@@ -1126,6 +1126,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
        { "check-srv-cname", MASTERZONE },
        { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE },
        { "update-check-ksk", MASTERZONE },
+       { "dnskey-ksk-only", MASTERZONE },
        { "try-tcp-refresh", SLAVEZONE },
        };
 
index 6a1f8b0f33cd0d937bd38ccba2b71b9be3ceff63..15f16f3a076b885aa7c05988dc34770a45c09f8a 100644 (file)
@@ -15,7 +15,7 @@
  * 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
@@ -72,6 +72,7 @@ typedef enum {
 #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
 /*
index 5f03a7db77bbf98d8e77fa3f24739cd3e93999f8..a04a248ee3c242780b82bd437068c6f5ee496f66 100644 (file)
@@ -15,7 +15,7 @@
  * 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 */
 
@@ -4265,44 +4265,6 @@ was_dumping(dns_zone_t *zone) {
 
 #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,
@@ -4492,7 +4454,8 @@ static isc_result_t
 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;
@@ -4500,7 +4463,7 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
        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));
@@ -4525,12 +4488,48 @@ add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
                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,
@@ -4560,7 +4559,7 @@ zone_resigninc(dns_zone_t *zone) {
        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;
@@ -4615,8 +4614,7 @@ zone_resigninc(dns_zone_t *zone) {
        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);
@@ -4660,7 +4658,7 @@ zone_resigninc(dns_zone_t *zone) {
                }
                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",
@@ -4705,7 +4703,7 @@ zone_resigninc(dns_zone_t *zone) {
         */
        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",
@@ -4845,8 +4843,8 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
            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;
@@ -4925,7 +4923,10 @@ sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
                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 &&
@@ -5355,7 +5356,8 @@ static isc_result_t
 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;
@@ -5375,7 +5377,7 @@ update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
                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",
@@ -5419,7 +5421,7 @@ zone_nsec3chain(dns_zone_t *zone) {
        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;
@@ -5491,8 +5493,7 @@ zone_nsec3chain(dns_zone_t *zone) {
        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
@@ -5964,7 +5965,7 @@ zone_nsec3chain(dns_zone_t *zone) {
         */
        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));
@@ -5977,7 +5978,7 @@ zone_nsec3chain(dns_zone_t *zone) {
         */
        result = update_sigs(&param_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));
@@ -5998,7 +5999,7 @@ zone_nsec3chain(dns_zone_t *zone) {
 
        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));
@@ -6030,7 +6031,7 @@ zone_nsec3chain(dns_zone_t *zone) {
 
        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));
@@ -6240,7 +6241,7 @@ zone_sign(dns_zone_t *zone) {
        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;
@@ -6255,8 +6256,6 @@ zone_sign(dns_zone_t *zone) {
        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);
@@ -6319,6 +6318,9 @@ zone_sign(dns_zone_t *zone) {
        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
@@ -6349,40 +6351,28 @@ zone_sign(dns_zone_t *zone) {
 
                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) {
@@ -6391,6 +6381,7 @@ zone_sign(dns_zone_t *zone) {
                                      signing->algorithm, signing->keyid,
                                      &sig_diff));
                }
+
                /*
                 * On the first pass we need to check if the current node
                 * has not been obscured.
@@ -6422,29 +6413,76 @@ zone_sign(dns_zone_t *zone) {
                 */
                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.
                 */
@@ -6514,13 +6552,6 @@ zone_sign(dns_zone_t *zone) {
                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
@@ -6538,7 +6569,7 @@ zone_sign(dns_zone_t *zone) {
                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",
@@ -6564,7 +6595,7 @@ zone_sign(dns_zone_t *zone) {
                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",
@@ -6606,7 +6637,7 @@ zone_sign(dns_zone_t *zone) {
         */
        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",
index 87d707c40c1f24b246a3097d504e7be01f5995b4..6d906d0318058cdd672357cf1cee6b5e29702f70 100644 (file)
@@ -15,7 +15,7 @@
  * 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 */
 
@@ -1113,6 +1113,7 @@ zone_clauses[] = {
        { "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 },