]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3632. [bug] Signature from newly inactive keys were not being
authorMark Andrews <marka@isc.org>
Thu, 15 Aug 2013 00:48:05 +0000 (10:48 +1000)
committerMark Andrews <marka@isc.org>
Thu, 15 Aug 2013 01:20:18 +0000 (11:20 +1000)
                        removed.  [RT #32178]

(cherry picked from commit 7ace3277956c49f7554b7130ef761bde3b35db30)

14 files changed:
CHANGES
bin/dnssec/dnssectool.c
bin/tests/system/dnssec/clean.sh
bin/tests/system/dnssec/ns3/named.conf
bin/tests/system/dnssec/ns3/publish-inactive.example.db.in [new file with mode: 0644]
bin/tests/system/dnssec/ns3/sign.sh
bin/tests/system/dnssec/tests.sh
lib/dns/dnssec.c
lib/dns/dst_api.c
lib/dns/dst_internal.h
lib/dns/include/dst/dst.h
lib/dns/update.c
lib/dns/win32/libdns.def
lib/dns/zone.c

diff --git a/CHANGES b/CHANGES
index f3e0e468fecbae9701bb0d3ad5c8ce2f5d8c48a5..124cc211f674e2fbb9f246f2781d663b201698c1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3632.  [bug]           Signature from newly inactive keys were not being
+                       removed. [RT #32178]
+
 3631.  [bug]           Remove spurious warning about missing signatures when
                        qtype is SIG. [RT #34600]
 
index 7c8c6ce2254aef83f068cb53613aac72d4678e1f..dfa0711afda85ddd428c2b7cdbcc7d5768df01e2 100644 (file)
@@ -319,11 +319,35 @@ strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
        isc_result_t result;
        const char *orig = str;
        char *endp;
+       int n;
 
        if ((str[0] == '0' || str[0] == '-') && str[1] == '\0')
                return ((isc_stdtime_t) 0);
 
-       if (strncmp(str, "now", 3) == 0) {
+       /*
+        * We accept times in the following formats:
+        *   now([+-]offset)
+        *   YYYYMMDD([+-]offset)
+        *   YYYYMMDDhhmmss([+-]offset)
+        *   [+-]offset
+        */
+       n = strspn(str, "0123456789");
+       if ((n == 8 || n == 14) &&
+           (str[n] == '\0' || str[n] == '-' || str[n] == '+'))
+       {
+               char timestr[15];
+
+               strlcpy(timestr, str, sizeof(timestr));
+               timestr[n] = 0;
+               if (n == 8)
+                       strlcat(timestr, "000000", sizeof(timestr));
+               result = dns_time64_fromtext(timestr, &val);
+               if (result != ISC_R_SUCCESS)
+                       fatal("time value %s is invalid: %s", orig,
+                             isc_result_totext(result));
+               base = val;
+               str += n;
+       } else if (strncmp(str, "now", 3) == 0) {
                base = now;
                str += 3;
        }
@@ -338,18 +362,7 @@ strtotime(const char *str, isc_int64_t now, isc_int64_t base) {
                offset = strtol(str + 1, &endp, 0);
                offset = time_units((isc_stdtime_t) offset, endp, orig);
                val = base - offset;
-       } else if (strlen(str) == 8U) {
-               char timestr[15];
-               sprintf(timestr, "%s000000", str);
-               result = dns_time64_fromtext(timestr, &val);
-               if (result != ISC_R_SUCCESS)
-                       fatal("time value %s is invalid: %s", orig,
-                             isc_result_totext(result));
-       } else if (strlen(str) > 14U) {
-               fatal("time value %s is invalid", orig);
        } else {
-               result = dns_time64_fromtext(str, &val);
-               if (result != ISC_R_SUCCESS)
                        fatal("time value %s is invalid: %s", orig,
                              isc_result_totext(result));
        }
index 383892f2bb69a86c75454cb70a477e849b8cca6e..0f333409b3156eb8a061a942c9f26394a9d28f08 100644 (file)
@@ -56,6 +56,7 @@ rm -f ns4/named.conf
 rm -f ns4/managed-keys.bind*
 rm -f ns3/auto-nsec.example.db ns3/auto-nsec3.example.db
 rm -f ns3/secure.below-cname.example.db
+rm -f ns3/publish-inactive.example.db
 rm -f signer/example.db.after signer/example.db.before
 rm -f signer/example.db.changed
 rm -f signer/nsec3param.out
index a23c6f872b99e25a8be984c486d95ae13745d2db..e40e4ae7777a1b916c9f807f4df06b31076adbe0 100644 (file)
@@ -33,6 +33,7 @@ options {
        notify yes;
        dnssec-enable yes;
        dnssec-validation yes;
+       session-keyfile "session.key";
 };
 
 key rndc_key {
@@ -262,4 +263,11 @@ zone "inline.example" {
         auto-dnssec maintain;
 };
 
+zone "publish-inactive.example" {
+       type master;
+       file "publish-inactive.example.db";
+       auto-dnssec maintain;
+       update-policy local;
+};
+
 include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in b/bin/tests/system/dnssec/ns3/publish-inactive.example.db.in
new file mode 100644 (file)
index 0000000..16c278b
--- /dev/null
@@ -0,0 +1,31 @@
+; Copyright (C) 2012  Internet Systems Consortium, Inc. ("ISC")
+;
+; Permission to use, copy, modify, and/or distribute this software for any
+; purpose with or without fee is hereby granted, provided that the above
+; copyright notice and this permission notice appear in all copies.
+;
+; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+; AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+; PERFORMANCE OF THIS SOFTWARE.
+
+; $Id: insecure.example.db,v 1.9 2007/06/19 23:47:02 tbox Exp $
+
+$TTL 300       ; 5 minutes
+@                      IN SOA  mname1. . (
+                               2000042407 ; serial
+                               20         ; refresh (20 seconds)
+                               20         ; retry (20 seconds)
+                               1814400    ; expire (3 weeks)
+                               3600       ; minimum (1 hour)
+                               )
+                       NS      ns
+ns                     A       10.53.0.3
+
+a                      A       10.0.0.1
+b                      A       10.0.0.2
+d                      A       10.0.0.4
+z                      A       10.0.0.26
index 36c8d30c2d5d9e2ef99f08da92c36786b9890ee1..0e1764241ad16e0382c3c8bf6bd7255d9b9b798c 100644 (file)
@@ -437,3 +437,17 @@ $CHECKZONE -D nosign.example nosign.example.db.signed 2>&- | \
 zone=inline.example.
 kskname=`$KEYGEN -q -3 -r $RANDFILE -fk $zone`
 zskname=`$KEYGEN -q -3 -r $RANDFILE $zone`
+
+#
+# publish a new key while deactivating another key at the same time.
+#
+zone=publish-inactive.example
+infile=publish-inactive.example.db.in
+zonefile=publish-inactive.example.db
+now=`date -u +%Y%m%d%H%M%S`
+kskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
+kskname=`$KEYGEN -P $now+90s -A $now+3600s -q -r $RANDFILE -f KSK $zone`
+kskname=`$KEYGEN -I $now+90s -q -r $RANDFILE -f KSK $zone`
+zskname=`$KEYGEN -q -r $RANDFILE $zone`
+cp $infile $zonefile
+$SIGNER -S -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
index c8c169c6d909eeb788c6540240610ea29a43860f..bb7452f82b1b953ff7350404f941261ed2c24236 100644 (file)
@@ -2260,5 +2260,25 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:check simultaneous inactivation and publishing of dnskeys removes inactive signature ($n)"
+ret=0
+cnt=0
+while :
+do
+$DIG $DIGOPTS publish-inactive.example @10.53.0.3 dnskey > dig.out.ns3.test$n
+keys=`awk '$5 == 257 { print; }' dig.out.ns3.test$n | wc -l`
+test $keys -gt 2 && break
+cnt=`expr $cnt + 1`
+test $cnt -gt 120 && break
+sleep 1
+done
+test $keys -gt 2 || ret=1
+sigs=`grep RRSIG dig.out.ns3.test$n | wc -l`
+sigs=`expr $sigs + 0`
+n=`expr $n + 1`
+test $sigs -eq 2 || ret=1
+if test $ret != 0 ; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 exit $status
index d00c99b4124c0cba476f23dae33c7c39972ccce8..602be1847d05198170554bdf701d413bd63950bc 100644 (file)
@@ -764,6 +764,7 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver,
                 * If a key is marked inactive, skip it
                 */
                if (!key_active(keys[count], now)) {
+                       dst_key_setinactive(pubkey, ISC_TRUE);
                        dst_key_free(&keys[count]);
                        keys[count] = pubkey;
                        pubkey = NULL;
index 98607246effcffb7cac2ab83220d683638176870..93dda089b6f0507e643afd0efb58514d4e683a76 100644 (file)
@@ -1349,10 +1349,27 @@ get_key_struct(dns_name_t *name, unsigned int alg,
                key->times[i] = 0;
                key->timeset[i] = ISC_FALSE;
        }
+       key->inactive = ISC_FALSE;
        key->magic = KEY_MAGIC;
        return (key);
 }
 
+isc_boolean_t
+dst_key_inactive(const dst_key_t *key) {
+
+       REQUIRE(VALID_KEY(key));
+
+       return (key->inactive);
+}
+
+void
+dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive) {
+
+       REQUIRE(VALID_KEY(key));
+
+       key->inactive = inactive;
+}
+
 /*%
  * Reads a public key from disk
  */
index c3e8e29a46e8ee944593679da63e6ff302dce834..9b897d113bdeaf3eb3bf50d127271f5a2b9b047b 100644 (file)
@@ -126,6 +126,8 @@ struct dst_key {
        isc_boolean_t   timeset[DST_MAX_TIMES + 1];  /*%< data set? */
        isc_stdtime_t   nums[DST_MAX_NUMERIC + 1];   /*%< numeric metadata */
        isc_boolean_t   numset[DST_MAX_NUMERIC + 1]; /*%< data set? */
+       isc_boolean_t   inactive;      /*%< private key not present as it is
+                                           inactive */
 
        int             fmt_major;     /*%< private key format, major version */
        int             fmt_minor;     /*%< private key format, minor version */
index 4724fc64c95e2e5fe6bc495c5f39da9cc1b5d89c..ef708b87c6db1a49a2707d44dac5d96451ccbe1e 100644 (file)
@@ -923,6 +923,23 @@ dst_key_restore(dns_name_t *name, unsigned int alg, unsigned int flags,
                unsigned int protocol, dns_rdataclass_t rdclass,
                isc_mem_t *mctx, const char *keystr, dst_key_t **keyp);
 
+isc_boolean_t
+dst_key_inactive(const dst_key_t *key);
+/*%<
+ * Determines if the private key is missing due the key being deemed inactive.
+ *
+ * Requires:
+ *     'key' to be valid.
+ */
+
+void
+dst_key_setinactive(dst_key_t *key, isc_boolean_t inactive);
+/*%<
+ * Set key inactive state.
+ *
+ * Requires:
+ *     'key' to be valid.
+ */
 
 ISC_LANG_ENDDECLS
 
index 14ffcc2234d89f2b557fdf520c037614b8dd59f5..0c4db04641aab61b65145092941875a056fce54e 100644 (file)
@@ -1211,7 +1211,9 @@ del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
                for (i = 0; i < nkeys; i++) {
                        if (rrsig.keyid == dst_key_id(keys[i])) {
                                found = ISC_TRUE;
-                               if (!dst_key_isprivate(keys[i])) {
+                               if (!dst_key_isprivate(keys[i]) &&
+                                   !dst_key_inactive(keys[i]))
+                               {
                                        /*
                                         * The re-signing code in zone.c
                                         * will mark this as offline.
index 4632763568b8978f84323c44cdfec33228cbbe55..f590d359f5e3f3aec4c7e01f695e09da77e2881b 100644 (file)
@@ -1006,6 +1006,7 @@ dst_key_getprivateformat
 dst_key_gettime
 dst_key_getttl
 dst_key_id
+dst_key_inactive
 dst_key_isnullkey
 dst_key_isprivate
 dst_key_iszonekey
@@ -1018,6 +1019,7 @@ dst_key_rid
 dst_key_secretsize
 dst_key_setbits
 dst_key_setflags
+dst_key_setinactive
 dst_key_setprivateformat
 dst_key_settime
 dst_key_setttl
index 426ba204afddb0f33c319d83edb1031cb18a5fe8..e1f1fece3c8c942d5204da8744281274ff04c9b5 100644 (file)
@@ -5424,7 +5424,9 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
                                 * We want the earliest offline expire time
                                 * iff there is a new offline signature.
                                 */
-                               if (!dst_key_isprivate(keys[i])) {
+                               if (!dst_key_inactive(keys[i]) &&
+                                   !dst_key_isprivate(keys[i]))
+                               {
                                        isc_int64_t timeexpire =
                                           dns_time64_from32(rrsig.timeexpire);
                                        if (warn != 0 && warn > timeexpire)