]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2892. [bug] Handle REVOKED keys better. [RT #20961]
authorMark Andrews <marka@isc.org>
Fri, 14 May 2010 04:38:52 +0000 (04:38 +0000)
committerMark Andrews <marka@isc.org>
Fri, 14 May 2010 04:38:52 +0000 (04:38 +0000)
CHANGES
bin/tests/system/autosign/tests.sh
lib/dns/include/dns/view.h
lib/dns/validator.c
lib/dns/view.c
lib/dns/zone.c

diff --git a/CHANGES b/CHANGES
index 29ca511223bb30aefe26c95fceb129db7c94d079..a47a41a4587aaff73a375526a9c490fa06279d18 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+2892.  [bug]           Handle REVOKED keys better. [RT #20961]
+
 2891.  [maint]         Update empty-zones list to match
                        draft-ietf-dnsop-default-local-zones-13. [RT# 21099]
 
index c58b6bca465f0dec84e4e167c15c0a7a6770cd1b..c611c8725c1e945619453e9727aab67a315333e6 100644 (file)
@@ -14,7 +14,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: tests.sh,v 1.7 2010/01/18 23:48:39 tbox Exp $
+# $Id: tests.sh,v 1.8 2010/05/14 04:38:52 marka Exp $
 
 SYSTEMTESTTOP=..
 . $SYSTEMTESTTOP/conf.sh
@@ -530,10 +530,11 @@ status=`expr $status + $ret`
 # Try validating with a revoked trusted key.
 # This should fail.
 
-echo "I:checking that validation fails due to revoked trusted key ($n)"
+echo "I:checking that validation returns insecure due to revoked trusted key ($n)"
 ret=0
 $DIG $DIGOPTS example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
-grep "SERVFAIL" dig.out.ns5.test$n > /dev/null || ret=1
+grep "flags:.*; QUERY" dig.out.ns5.test$n > /dev/null || ret=1
+grep "flags:.* ad.*; QUERY" dig.out.ns5.test$n > /dev/null && ret=1
 n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
index ab369ef489b62f9b953cc2795780128a909e3966..4f55cf70a0878062a36d510b284cf34c7419e6e2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.h,v 1.120 2009/11/28 15:57:37 vjs Exp $ */
+/* $Id: view.h,v 1.121 2010/05/14 04:38:52 marka Exp $ */
 
 #ifndef DNS_VIEW_H
 #define DNS_VIEW_H 1
@@ -73,6 +73,7 @@
 
 #include <dns/acl.h>
 #include <dns/fixedname.h>
+#include <dns/rdatastruct.h>
 #include <dns/types.h>
 
 ISC_LANG_BEGINDECLS
@@ -962,4 +963,19 @@ dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
  *\li  ISC_R_SUCCESS
  *\li  Any other value indicates failure
  */
+
+void 
+dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
+                 dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx);
+/*%<
+ * Remove keys that match 'keyname' and 'dnskey' from the views trust
+ * anchors.
+ *
+ * Requires:
+ * \li 'view' is valid.
+ * \li 'keyname' is valid.
+ * \li 'mctx' is valid.
+ * \li 'dnskey' is valid.
+ */
+
 #endif /* DNS_VIEW_H */
index f28a62467dbaceff5c763e2ee1e2a24c683ef17b..cc493987371a3a443806834ead61d12bb8338e2f 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: validator.c,v 1.191 2010/05/14 00:13:43 marka Exp $ */
+/* $Id: validator.c,v 1.192 2010/05/14 04:38:51 marka Exp $ */
 
 #include <config.h>
 
 #include <isc/util.h>
 
 #include <dns/db.h>
-#include <dns/ds.h>
 #include <dns/dnssec.h>
+#include <dns/ds.h>
 #include <dns/events.h>
 #include <dns/keytable.h>
+#include <dns/keyvalues.h>
 #include <dns/log.h>
 #include <dns/message.h>
 #include <dns/ncache.h>
 #include <dns/nsec.h>
 #include <dns/nsec3.h>
 #include <dns/rdata.h>
-#include <dns/rdatastruct.h>
 #include <dns/rdataset.h>
 #include <dns/rdatatype.h>
 #include <dns/resolver.h>
@@ -1746,16 +1746,23 @@ compute_keytag(dns_rdata_t *rdata, dns_rdata_dnskey_t *key) {
  */
 static isc_boolean_t
 isselfsigned(dns_validator_t *val) {
+       dns_fixedname_t fixed;
        dns_rdataset_t *rdataset, *sigrdataset;
        dns_rdata_t rdata = DNS_RDATA_INIT;
        dns_rdata_t sigrdata = DNS_RDATA_INIT;
        dns_rdata_dnskey_t key;
        dns_rdata_rrsig_t sig;
        dns_keytag_t keytag;
+       dns_name_t *name;
        isc_result_t result;
+       dst_key_t *dstkey;
+       isc_mem_t *mctx;
+       isc_boolean_t answer = ISC_FALSE;
 
        rdataset = val->event->rdataset;
        sigrdataset = val->event->sigrdataset;
+       name = val->event->name;
+       mctx = val->view->mctx;
 
        INSIST(rdataset->type == dns_rdatatype_dnskey);
 
@@ -1777,12 +1784,31 @@ isselfsigned(dns_validator_t *val) {
                        result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
                        RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
-                       if (sig.algorithm == key.algorithm &&
-                           sig.keyid == keytag)
-                               return (ISC_TRUE);
+                       if (sig.algorithm != key.algorithm ||
+                           sig.keyid != keytag ||
+                           !dns_name_equal(name, &sig.signer))
+                               continue;
+
+                       dstkey = NULL;
+                       result = dns_dnssec_keyfromrdata(name, &rdata, mctx,
+                                                        &dstkey);
+                       if (result != ISC_R_SUCCESS)
+                               continue;
+
+                       result = dns_dnssec_verify2(name, rdataset, dstkey,
+                                                   ISC_TRUE, mctx, &sigrdata,
+                                                   dns_fixedname_name(&fixed));
+                       dst_key_free(&dstkey);
+                       if (result != ISC_R_SUCCESS)
+                               continue;
+                       if ((key.flags & DNS_KEYFLAG_REVOKE) == 0) {
+                               answer = ISC_TRUE;
+                               continue;
+                       }
+                       dns_view_untrust(val->view, name, &key, mctx);
                }
        }
-       return (ISC_FALSE);
+       return (answer);
 }
 
 /*%
@@ -1946,8 +1972,6 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
                        isc_stdtime_get(&now);
                        ttl = ISC_MIN(event->rdataset->ttl,
                                      val->siginfo->timeexpire - now);
-                       if (val->keyset != NULL)
-                               ttl = ISC_MIN(ttl, val->keyset->ttl);
                        event->rdataset->ttl = ttl;
                        event->sigrdataset->ttl = ttl;
                }
@@ -1997,25 +2021,102 @@ validate(dns_validator_t *val, isc_boolean_t resume) {
        return (DNS_R_NOVALIDSIG);
 }
 
+/*%
+ * Check whether this DNSKEY (keyrdata) signed the DNSKEY RRset
+ * (val->event->rdataset).
+ */
+static isc_result_t
+checkkey(dns_validator_t *val, dns_rdata_t *keyrdata, isc_uint16_t keyid,
+        dns_secalg_t algorithm)
+{
+       dns_rdata_rrsig_t sig;
+       dst_key_t *dstkey = NULL;
+       isc_result_t result;
+
+       for (result = dns_rdataset_first(val->event->sigrdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(val->event->sigrdataset))
+       {
+               dns_rdata_t rdata = DNS_RDATA_INIT;
+
+               dns_rdataset_current(val->event->sigrdataset, &rdata);
+               result = dns_rdata_tostruct(&rdata, &sig, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               if (keyid != sig.keyid || algorithm != sig.algorithm)
+                       continue;
+               if (dstkey == NULL) {
+                       result = dns_dnssec_keyfromrdata(val->event->name,
+                                                        keyrdata,
+                                                        val->view->mctx,
+                                                        &dstkey);
+                       if (result != ISC_R_SUCCESS)
+                               /*
+                                * This really shouldn't happen, but...
+                                */
+                               continue;
+               }
+               result = verify(val, dstkey, &rdata, sig.keyid);
+               if (result == ISC_R_SUCCESS)
+                       break;
+       }
+       if (dstkey != NULL)
+               dst_key_free(&dstkey);
+       return (result);
+}
+
+/*%
+ * Find the DNSKEY that corresponds to the DS.
+ */
+static isc_result_t
+keyfromds(dns_validator_t *val, dns_rdataset_t *rdataset, dns_rdata_t *dsrdata,
+         isc_uint8_t digest, isc_uint16_t keyid, dns_secalg_t algorithm,
+         dns_rdata_t *keyrdata)
+{
+       dns_keytag_t keytag;
+       dns_rdata_dnskey_t key;
+       isc_result_t result;
+       unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+       for (result = dns_rdataset_first(rdataset);
+            result == ISC_R_SUCCESS;
+            result = dns_rdataset_next(rdataset))
+       {
+               dns_rdata_t newdsrdata = DNS_RDATA_INIT;
+
+               dns_rdata_reset(keyrdata);
+               dns_rdataset_current(rdataset, keyrdata);
+               result = dns_rdata_tostruct(keyrdata, &key, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               keytag = compute_keytag(keyrdata, &key);
+               if (keyid != keytag || algorithm != key.algorithm)
+                       continue;
+               dns_rdata_reset(&newdsrdata);
+               result = dns_ds_buildrdata(val->event->name, keyrdata, digest,
+                                          dsbuf, &newdsrdata);
+               if (result != ISC_R_SUCCESS) {
+                       validator_log(val, ISC_LOG_DEBUG(3),
+                                     "dns_ds_buildrdata() -> %s",
+                                     dns_result_totext(result));
+                       continue;
+               }
+               if (dns_rdata_compare(dsrdata, &newdsrdata) == 0)
+                       break;
+       }
+       return (result);
+}
+
 /*%
  * Validate the DNSKEY RRset by looking for a DNSKEY that matches a
  * DLV record and that also verifies the DNSKEY RRset.
  */
 static isc_result_t
 dlv_validatezonekey(dns_validator_t *val) {
-       dns_keytag_t keytag;
        dns_rdata_dlv_t dlv;
-       dns_rdata_dnskey_t key;
-       dns_rdata_rrsig_t sig;
        dns_rdata_t dlvrdata = DNS_RDATA_INIT;
        dns_rdata_t keyrdata = DNS_RDATA_INIT;
-       dns_rdata_t newdsrdata = DNS_RDATA_INIT;
-       dns_rdata_t sigrdata = DNS_RDATA_INIT;
        dns_rdataset_t trdataset;
-       dst_key_t *dstkey;
        isc_boolean_t supported_algorithm;
        isc_result_t result;
-       unsigned char dsbuf[DNS_DS_BUFFERSIZE];
        isc_uint8_t digest_type;
 
        validator_log(val, ISC_LOG_DEBUG(3), "dlv_validatezonekey");
@@ -2080,70 +2181,27 @@ dlv_validatezonekey(dns_validator_t *val) {
                dns_rdataset_init(&trdataset);
                dns_rdataset_clone(val->event->rdataset, &trdataset);
 
-               for (result = dns_rdataset_first(&trdataset);
-                    result == ISC_R_SUCCESS;
-                    result = dns_rdataset_next(&trdataset))
-               {
-                       dns_rdata_reset(&keyrdata);
-                       dns_rdataset_current(&trdataset, &keyrdata);
-                       result = dns_rdata_tostruct(&keyrdata, &key, NULL);
-                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
-                       keytag = compute_keytag(&keyrdata, &key);
-                       if (dlv.key_tag != keytag ||
-                           dlv.algorithm != key.algorithm)
-                               continue;
-                       dns_rdata_reset(&newdsrdata);
-                       result = dns_ds_buildrdata(val->event->name,
-                                                  &keyrdata, dlv.digest_type,
-                                                  dsbuf, &newdsrdata);
-                       if (result != ISC_R_SUCCESS) {
-                               validator_log(val, ISC_LOG_DEBUG(3),
-                                             "dns_ds_buildrdata() -> %s",
-                                             dns_result_totext(result));
-                               continue;
-                       }
-                       /* Covert to DLV */
-                       newdsrdata.type = dns_rdatatype_dlv;
-                       if (dns_rdata_compare(&dlvrdata, &newdsrdata) == 0)
-                               break;
-               }
+               /*
+                * Convert to DLV to DS and find matching DNSKEY.
+                */
+               dlvrdata.type = dns_rdatatype_ds;
+               result = keyfromds(val, &trdataset, &dlvrdata,
+                                  dlv.digest_type, dlv.key_tag,
+                                  dlv.algorithm, &keyrdata);
                if (result != ISC_R_SUCCESS) {
                        dns_rdataset_disassociate(&trdataset);
                        validator_log(val, ISC_LOG_DEBUG(3),
                                      "no DNSKEY matching DLV");
                        continue;
                }
+
                validator_log(val, ISC_LOG_DEBUG(3),
                      "Found matching DLV record: checking for signature");
+               /*
+                * Check that this DNSKEY signed the DNSKEY rrset.
+                */
+               result = checkkey(val, &keyrdata, dlv.key_tag, dlv.algorithm);
 
-               for (result = dns_rdataset_first(val->event->sigrdataset);
-                    result == ISC_R_SUCCESS;
-                    result = dns_rdataset_next(val->event->sigrdataset))
-               {
-                       dns_rdata_reset(&sigrdata);
-                       dns_rdataset_current(val->event->sigrdataset,
-                                            &sigrdata);
-                       result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
-                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
-                       if (dlv.key_tag != sig.keyid ||
-                           dlv.algorithm != sig.algorithm)
-                               continue;
-                       dstkey = NULL;
-                       result = dns_dnssec_keyfromrdata(val->event->name,
-                                                        &keyrdata,
-                                                        val->view->mctx,
-                                                        &dstkey);
-                       if (result != ISC_R_SUCCESS)
-                               /*
-                                * This really shouldn't happen, but...
-                                */
-                               continue;
-
-                       result = verify(val, dstkey, &sigrdata, sig.keyid);
-                       dst_key_free(&dstkey);
-                       if (result == ISC_R_SUCCESS)
-                               break;
-               }
                dns_rdataset_disassociate(&trdataset);
                if (result == ISC_R_SUCCESS)
                        break;
@@ -2185,14 +2243,10 @@ validatezonekey(dns_validator_t *val) {
        dns_validatorevent_t *event;
        dns_rdataset_t trdataset;
        dns_rdata_t dsrdata = DNS_RDATA_INIT;
-       dns_rdata_t newdsrdata = DNS_RDATA_INIT;
        dns_rdata_t keyrdata = DNS_RDATA_INIT;
        dns_rdata_t sigrdata = DNS_RDATA_INIT;
-       unsigned char dsbuf[DNS_DS_BUFFERSIZE];
        char namebuf[DNS_NAME_FORMATSIZE];
-       dns_keytag_t keytag;
        dns_rdata_ds_t ds;
-       dns_rdata_dnskey_t key;
        dns_rdata_rrsig_t sig;
        dst_key_t *dstkey;
        isc_boolean_t supported_algorithm;
@@ -2235,8 +2289,7 @@ validatezonekey(dns_validator_t *val) {
                        result = dns_keytable_findkeynode(val->keytable,
                                                          val->event->name,
                                                          sig.algorithm,
-                                                         sig.keyid,
-                                                         &keynode);
+                                                         sig.keyid, &keynode);
                        if (result == ISC_R_NOTFOUND &&
                            dns_keytable_finddeepestmatch(val->keytable,
                                  val->event->name, found) != ISC_R_SUCCESS) {
@@ -2466,29 +2519,10 @@ validatezonekey(dns_validator_t *val) {
                dns_rdataset_clone(val->event->rdataset, &trdataset);
 
                /*
-                * Look for the KEY that matches the DS record.
+                * Find matching DNSKEY from DS.
                 */
-               for (result = dns_rdataset_first(&trdataset);
-                    result == ISC_R_SUCCESS;
-                    result = dns_rdataset_next(&trdataset))
-               {
-                       dns_rdata_reset(&keyrdata);
-                       dns_rdataset_current(&trdataset, &keyrdata);
-                       result = dns_rdata_tostruct(&keyrdata, &key, NULL);
-                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
-                       keytag = compute_keytag(&keyrdata, &key);
-                       if (ds.key_tag != keytag ||
-                           ds.algorithm != key.algorithm)
-                               continue;
-                       dns_rdata_reset(&newdsrdata);
-                       result = dns_ds_buildrdata(val->event->name,
-                                                  &keyrdata, ds.digest_type,
-                                                  dsbuf, &newdsrdata);
-                       if (result != ISC_R_SUCCESS)
-                               continue;
-                       if (dns_rdata_compare(&dsrdata, &newdsrdata) == 0)
-                               break;
-               }
+               result = keyfromds(val, &trdataset, &dsrdata, ds.digest_type,
+                                  ds.key_tag, ds.algorithm, &keyrdata);
                if (result != ISC_R_SUCCESS) {
                        dns_rdataset_disassociate(&trdataset);
                        validator_log(val, ISC_LOG_DEBUG(3),
@@ -2496,38 +2530,11 @@ validatezonekey(dns_validator_t *val) {
                        continue;
                }
 
-               for (result = dns_rdataset_first(val->event->sigrdataset);
-                    result == ISC_R_SUCCESS;
-                    result = dns_rdataset_next(val->event->sigrdataset))
-               {
-                       dns_rdata_reset(&sigrdata);
-                       dns_rdataset_current(val->event->sigrdataset,
-                                            &sigrdata);
-                       result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
-                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
-                       if (ds.key_tag != sig.keyid ||
-                           ds.algorithm != sig.algorithm)
-                               continue;
-                       if (!dns_name_equal(val->event->name, &sig.signer)) {
-                               validator_log(val, ISC_LOG_DEBUG(3),
-                                             "DNSKEY signer mismatch");
-                               continue;
-                       }
-                       dstkey = NULL;
-                       result = dns_dnssec_keyfromrdata(val->event->name,
-                                                        &keyrdata,
-                                                        val->view->mctx,
-                                                        &dstkey);
-                       if (result != ISC_R_SUCCESS)
-                               /*
-                                * This really shouldn't happen, but...
-                                */
-                               continue;
-                       result = verify(val, dstkey, &sigrdata, sig.keyid);
-                       dst_key_free(&dstkey);
-                       if (result == ISC_R_SUCCESS)
-                               break;
-               }
+               /*
+                * Check that this DNSKEY signed the DNSKEY rrset.
+                */
+               result = checkkey(val, &keyrdata, ds.key_tag, ds.algorithm);
+
                dns_rdataset_disassociate(&trdataset);
                if (result == ISC_R_SUCCESS)
                        break;
index 7412701a6d9790c6110da21fb3829a337066986c..030b138daa01fa61d167c5857cdad3553d0c67e9 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: view.c,v 1.161 2010/02/25 05:08:01 tbox Exp $ */
+/* $Id: view.c,v 1.162 2010/05/14 04:38:51 marka Exp $ */
 
 /*! \file */
 
 #include <dns/cache.h>
 #include <dns/db.h>
 #include <dns/dlz.h>
+#include <dns/dnssec.h>
 #include <dns/events.h>
 #include <dns/forward.h>
 #include <dns/keytable.h>
+#include <dns/keyvalues.h>
 #include <dns/master.h>
 #include <dns/masterdump.h>
 #include <dns/order.h>
@@ -1566,3 +1568,36 @@ dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
        return (dns_keytable_issecuredomain(view->secroots_priv, name,
                                            secure_domain));
 }
+
+void
+dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
+                dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
+{
+       isc_result_t result;
+       unsigned char data[4096];
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       isc_buffer_t buffer;
+       dst_key_t *key = NULL;
+       dns_keytable_t *sr = NULL;
+
+       /*
+        * Clear the revoke bit, if set, so that the key will match what's
+        * in secroots now.
+        */
+       dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
+
+       /* Convert dnskey to DST key. */
+       isc_buffer_init(&buffer, data, sizeof(data));
+       dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
+                            dns_rdatatype_dnskey, dnskey, &buffer);
+       result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
+       if (result != ISC_R_SUCCESS)
+               return;
+       result = dns_view_getsecroots(view, &sr);
+       if (result == ISC_R_SUCCESS) {
+               dns_keytable_deletekeynode(sr, key);
+               dns_keytable_detach(&sr);
+       }
+       dst_key_free(&key);
+}
+
index 6865b0339766e21e870a9f40d4176d67f8365926..d05b0eee3fcb57932f5e36d6c49fdc994fadeab2 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.c,v 1.561 2010/04/28 23:50:51 tbox Exp $ */
+/* $Id: zone.c,v 1.562 2010/05/14 04:38:51 marka Exp $ */
 
 /*! \file */
 
@@ -2855,39 +2855,11 @@ static void
 untrust_key(dns_viewlist_t *viewlist, dns_name_t *keyname, isc_mem_t *mctx,
            dns_rdata_dnskey_t *dnskey)
 {
-       isc_result_t result;
-       unsigned char data[4096];
-       dns_rdata_t rdata = DNS_RDATA_INIT;
-       isc_buffer_t buffer;
        dns_view_t *view;
-       dst_key_t *key = NULL;
-
-       /*
-        * Clear the revoke bit, if set, so that the key will match what's
-        * in secroots now.
-        */
-       dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
-
-       /* Convert dnskey to DST key. */
-       isc_buffer_init(&buffer, data, sizeof(data));
-       dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
-                            dns_rdatatype_dnskey, dnskey, &buffer);
-       result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
-       if (result != ISC_R_SUCCESS)
-               return;
 
        for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
-            view = ISC_LIST_NEXT(view, link)) {
-               dns_keytable_t *sr = NULL;
-               result = dns_view_getsecroots(view, &sr);
-               if (result != ISC_R_SUCCESS)
-                       continue;
-
-               dns_keytable_deletekeynode(sr, key);
-               dns_keytable_detach(&sr);
-       }
-
-       dst_key_free(&key);
+            view = ISC_LIST_NEXT(view, link))
+               dns_view_untrust(view, keyname, dnskey, mctx);
 }
 
 /*
@@ -7201,6 +7173,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
        dst_key_t *dstkey;
        isc_stdtime_t now;
        int pending = 0;
+       isc_boolean_t secure;
 
        UNUSED(task);
        INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
@@ -7253,8 +7226,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
 
        /*
         * Validate the dnskeyset against the current trusted keys.
-        * (Note, if a key has been revoked and isn't RSAMD5, then
-        * its key ID will have changed.)
         */
        for (result = dns_rdataset_first(&kfetch->dnskeysigset);
             result == ISC_R_SUCCESS;
@@ -7277,9 +7248,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                break;
 
                        if (dst_key_alg(dstkey) == sig.algorithm &&
-                           (dst_key_id(dstkey) == sig.keyid ||
-                            (sig.algorithm != 1 && sig.keyid ==
-                              ((dst_key_id(dstkey) + 128) & 0xffff)))) {
+                           dst_key_id(dstkey) == sig.keyid) {
                                result = dns_dnssec_verify2(keyname,
                                                    &kfetch->dnskeyset,
                                                    dstkey, ISC_FALSE,
@@ -7312,15 +7281,11 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                        break;
        }
 
-       /* Failed to validate?  Let's go home. */
-       if (kfetch->dnskeyset.trust != dns_trust_secure) {
-               dns_zone_log(zone, ISC_LOG_WARNING,
-                            "DNSKEY set for zone '%s' failed to validate",
-                            namebuf);
-               CHECK(minimal_update(kfetch, ver, &diff));
-               changed = ISC_TRUE;
-               goto failure;
-       }
+       /*
+        * If we were not able to verify the answer using the current
+        * trusted keys then all we can do is look at any revoked keys.
+        */
+       secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
 
        /*
         * First scan keydataset to find keys that are not in dnskeyset
@@ -7354,7 +7319,10 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
                        isc_boolean_t deletekey = ISC_FALSE;
 
-                       if (now < keydata.addhd) {
+                       if (!secure) {
+                               if (now > keydata.removehd)
+                                       deletekey = ISC_TRUE;
+                       } else if (now < keydata.addhd) {
                                dns_zone_log(zone, ISC_LOG_WARNING,
                                             "Pending key unexpectedly missing "
                                             "from %s; restarting acceptance "
@@ -7374,13 +7342,15 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                keydata.refresh = refresh_time(kfetch);
                        }
 
-                       /* Delete old version */
-                       CHECK(update_one_rr(kfetch->db, ver, &diff,
-                                           DNS_DIFFOP_DEL, keyname, 0,
-                                           &keydatarr));
-                       changed = ISC_TRUE;
+                       if  (secure || deletekey) {
+                               /* Delete old version */
+                               CHECK(update_one_rr(kfetch->db, ver, &diff,
+                                                   DNS_DIFFOP_DEL, keyname, 0,
+                                                   &keydatarr));
+                               changed = ISC_TRUE;
+                       }
 
-                       if (deletekey)
+                       if (!secure || deletekey)
                                continue;
 
                        dns_rdata_reset(&keydatarr);
@@ -7439,7 +7409,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                        dns_rdataset_current(&kfetch->keydataset, &keydatarr);
                        dns_rdata_tostruct(&keydatarr, &keydata, NULL);
 
-                       if (revoked) {
+                       if (revoked && revocable(kfetch, &keydata)) {
                                if (keydata.addhd > now) {
                                        /*
                                         * Key wasn't trusted yet, and now
@@ -7447,20 +7417,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                         */
                                        deletekey = ISC_TRUE;
                                } else if (keydata.removehd == 0) {
-                                       /*
-                                        * Newly revoked key?  Make sure
-                                        * it signed itself
-                                        */
-                                       if(! revocable(kfetch, &keydata)) {
-                                               dns_zone_log(zone,
-                                                            ISC_LOG_WARNING,
-                                                        "Active key for zone "
-                                                        "'%s' is revoked but "
-                                                        "did not self-sign; "
-                                                        "ignoring.", namebuf);
-                                               continue;
-                                       }
-
                                        /* Remove from secroots */
                                        untrust_key(zone->view->viewlist,
                                                    keyname, mctx, &dnskey);
@@ -7474,7 +7430,16 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
                                        /* Scheduled for removal */
                                        deletekey = ISC_TRUE;
                                }
-                       } else {
+                       } else if (revoked) {
+                               if (secure && keydata.removehd == 0) {
+                                       dns_zone_log(zone, ISC_LOG_WARNING,
+                                                    "Active key for zone "
+                                                    "'%s' is revoked but "
+                                                    "did not self-sign; "
+                                                        "ignoring.", namebuf);
+                                               continue;
+                               }
+                       } else if (secure) {
                                if (keydata.removehd != 0) {
                                        /*
                                         * Key isn't revoked--but it
@@ -7495,7 +7460,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) {
 
                        if (!deletekey && !newkey)
                                updatekey = ISC_TRUE;
-               } else {
+               } else if (secure) {
                        /*
                         * Key wasn't in the key zone but it's
                         * revoked now anyway, so just skip it
@@ -7641,6 +7606,7 @@ zone_refreshkeys(dns_zone_t *zone) {
        dns_rdata_t rdata = DNS_RDATA_INIT;
        dns_rdata_keydata_t kd;
        isc_stdtime_t now;
+       isc_boolean_t commit = ISC_FALSE;
 
        ENTER;
        REQUIRE(zone->db != NULL);
@@ -7732,12 +7698,19 @@ zone_refreshkeys(dns_zone_t *zone) {
                                         &kfetch->dnskeysigset,
                                         &kfetch->fetch);
        }
+       if (!ISC_LIST_EMPTY(diff.tuples)) {
+               CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
+               commit = ISC_TRUE;
+               zone_journal(zone, &diff, "sync_keyzone");
+                DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
+                zone_needdump(zone, 30);
+       }
   failure:
        UNLOCK_ZONE(zone);
 
        dns_rriterator_destroy(&rrit);
        dns_diff_clear(&diff);
-       dns_db_closeversion(db, &ver, ISC_FALSE);
+       dns_db_closeversion(db, &ver, commit);
        dns_db_detach(&db);
 }
 
@@ -11147,7 +11120,8 @@ zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
        vsnprintf(message, sizeof(message), fmt, ap);
        va_end(ap);
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
-                     level, "%s: zone %s: %s", me, zone->strnamerd, message);
+                     level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
+                     "zone" : "managed-keys-zone", zone->strnamerd, message);
 }
 
 static int