From 44f175a90a855326725439b2f1178f0dcca8f67d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 14 May 2010 04:38:52 +0000 Subject: [PATCH] 2892. [bug] Handle REVOKED keys better. [RT #20961] --- CHANGES | 2 + bin/tests/system/autosign/tests.sh | 7 +- lib/dns/include/dns/view.h | 18 +- lib/dns/validator.c | 269 +++++++++++++++-------------- lib/dns/view.c | 37 +++- lib/dns/zone.c | 116 +++++-------- 6 files changed, 242 insertions(+), 207 deletions(-) diff --git a/CHANGES b/CHANGES index 29ca511223..a47a41a458 100644 --- 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] diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh index c58b6bca46..c611c8725c 100644 --- a/bin/tests/system/autosign/tests.sh +++ b/bin/tests/system/autosign/tests.sh @@ -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` diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index ab369ef489..4f55cf70a0 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -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 #include +#include #include 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 */ diff --git a/lib/dns/validator.c b/lib/dns/validator.c index f28a62467d..cc49398737 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -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 @@ -28,17 +28,17 @@ #include #include -#include #include +#include #include #include +#include #include #include #include #include #include #include -#include #include #include #include @@ -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; diff --git a/lib/dns/view.c b/lib/dns/view.c index 7412701a6d..030b138daa 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -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 */ @@ -33,9 +33,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -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); +} + diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 6865b03397..d05b0eee3f 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -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