diff --git a/CHANGES b/CHANGES index 51c58ae74a..23e67dd4d2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ +3102. [func] New 'dnssec-loadkeys-interval' option configures + how often, in minutes, to check the key repository + for updates when using automatic key maintenance. + Default is every 60 minutes (formerly hard-coded + to 12 hours). [RT #23744] + +3101. [bug] Zones using automatic key maintenance could fail + to check the key repository for updates. [RT #23744] + 3100. [security] Certain response policy zone configurations could trigger an INSIST when receiving a query of type RRSIG. [RT #24280] diff --git a/bin/named/config.c b/bin/named/config.c index 7122e27a32..00ba064986 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.116 2011/02/23 03:08:08 marka Exp $ */ +/* $Id: config.c,v 1.117 2011/04/29 21:37:14 each Exp $ */ /*! \file */ @@ -210,6 +210,7 @@ options {\n\ zero-no-soa-ttl yes;\n\ update-check-ksk yes;\n\ dnssec-dnskey-kskonly no;\n\ + dnssec-loadkeys-interval 60;\n\ try-tcp-refresh yes; /* BIND 8 compat */\n\ };\n\ " diff --git a/bin/named/zoneconf.c b/bin/named/zoneconf.c index 3fd1cfe278..387a724d55 100644 --- a/bin/named/zoneconf.c +++ b/bin/named/zoneconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zoneconf.c,v 1.174 2011/03/11 06:11:21 marka Exp $ */ +/* $Id: zoneconf.c,v 1.175 2011/04/29 21:37:14 each Exp $ */ /*% */ @@ -1229,6 +1229,12 @@ ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, cfg_obj_asboolean(obj)); + + obj = NULL; + result = ns_config_get(maps, "dnssec-loadkeys-interval", &obj); + INSIST(result == ISC_R_SUCCESS && obj != NULL); + RETERR(dns_zone_setrefreshkeyinterval(zone, + cfg_obj_asuint32(obj))); } else if (ztype == dns_zone_slave) { RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update_forwarding, ac, zone, diff --git a/bin/tests/system/autosign/ns2/named.conf b/bin/tests/system/autosign/ns2/named.conf index 10a91907b6..1969be56a2 100644 --- a/bin/tests/system/autosign/ns2/named.conf +++ b/bin/tests/system/autosign/ns2/named.conf @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named.conf,v 1.5 2010/01/18 23:48:40 tbox Exp $ */ +/* $Id: named.conf,v 1.6 2011/04/29 21:37:14 each Exp $ */ // NS2 @@ -32,6 +32,7 @@ options { notify yes; dnssec-enable yes; dnssec-validation yes; + dnssec-loadkeys-interval 30; }; key rndc_key { diff --git a/bin/tests/system/autosign/ns3/named.conf b/bin/tests/system/autosign/ns3/named.conf index 4d6598ee3d..8a8eaa32d5 100644 --- a/bin/tests/system/autosign/ns3/named.conf +++ b/bin/tests/system/autosign/ns3/named.conf @@ -14,7 +14,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named.conf,v 1.10 2011/03/25 23:53:02 each Exp $ */ +/* $Id: named.conf,v 1.11 2011/04/29 21:37:14 each Exp $ */ // NS3 @@ -32,6 +32,7 @@ options { notify yes; dnssec-enable yes; dnssec-validation yes; + dnssec-loadkeys-interval 10; }; key rndc_key { diff --git a/bin/tests/system/autosign/tests.sh b/bin/tests/system/autosign/tests.sh index a03bdac832..729271fc87 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.20 2011/03/25 23:53:02 each Exp $ +# $Id: tests.sh,v 1.21 2011/04/29 21:37:14 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -879,6 +879,43 @@ grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || lret=1 n=`expr $n + 1` if [ $lret != 0 ]; then echo "I:not yet implemented"; fi +echo "I:checking key event timers are always set ($n)" +# this is a regression test for a bug in which the next key event could +# be scheduled for the present moment, and then never fire. check for +# visible evidence of this error in the logs: +awk '/next key event/ {if ($1 == $8 && $2 == $9) exit 1}' */named.run || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +# this confirms that key events are never scheduled more than +# 'dnssec-loadkeys-interval' minutes in the future, and that the +# last event scheduled is precisely that far in the future. +check_interval () { + awk '/next key event/ {print $2 ":" $9}' $1/named.run | + awk -F: -vinterval=$2 ' + { + if ($6 == 0) + $6 = 25; + x = ($6+ $5*60 + $4*3600) - ($3 + $2*60 + $1*3600); + if (x != int(x)) + x = int(x + 1); + if (x > interval) + exit (1); + } + END { if (x != interval) exit(1) }' + return $? +} + +echo "I:checking automatic key reloading interval ($n)" +ret=0 +check_interval ns1 3600 || ret=1 +check_interval ns2 1800 || ret=1 +check_interval ns3 600 || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:exit status: $status" exit $status diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 21467e81c2..519cb2e054 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -5060,6 +5060,7 @@ badresp:1,adberr:0,findfail:0,valfail:0] allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; dnssec-dnskey-kskonly yes_or_no; + dnssec-loadkeys-interval number; dnssec-secure-to-insecure yes_or_no ; try-tcp-refresh yes_or_no; allow-v6-synthesis { address_match_list }; @@ -6884,6 +6885,26 @@ options { + + dnssec-loadkeys-interval + + + When a zone is configured with auto-dnssec + maintain; its key repository must be checked + periodically to see if any new keys have been added + or any existing keys' timing metadata has been updated + (see and + ). The + dnssec-loadkeys-interval option + sets the frequency of autoatic repository checks, in + minutes. The default is 60 (1 hour), + the minimum is 1 (1 minute), and the + maximum is 1440 (24 hours); any higher + value is silently reduced. + + + + try-tcp-refresh @@ -10024,6 +10045,7 @@ zone zone_name class allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; dnssec-dnskey-kskonly yes_or_no; + dnssec-loadkeys-interval number; dnssec-secure-to-insecure yes_or_no ; try-tcp-refresh yes_or_no; also-notify { ip_addr port ip_port ; @@ -11119,7 +11141,12 @@ example.com. NS ns2.example.net. named to load keys from the key repository and schedule key maintenance events to occur in the future, but it does not sign the full zone - immediately. + immediately. Note: once keys have been loaded for a + zone the first time, the repository will be searched + for changes periodically, regardless of whether + rndc loadkeys is used. The recheck + interval is defined by + dnssec-loadkeys-interval.) auto-dnssec create; includes the diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 96b386ee29..84c9c974b3 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.128 2011/03/11 17:19:05 each Exp $ */ +/* $Id: check.c,v 1.129 2011/04/29 21:37:15 each Exp $ */ /*! \file */ @@ -1307,6 +1307,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, REDIRECTZONE }, { "update-check-ksk", MASTERZONE }, { "dnssec-dnskey-kskonly", MASTERZONE }, + { "dnssec-loadkeys-interval", MASTERZONE }, { "auto-dnssec", MASTERZONE }, { "try-tcp-refresh", SLAVEZONE | STREDIRECTZONE }, { "server-addresses", STATICSTUBZONE }, diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index 2914ce4579..629a5bebfc 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.186 2011/03/21 18:38:40 each Exp $ */ +/* $Id: zone.h,v 1.187 2011/04/29 21:37:15 each Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -1871,6 +1871,18 @@ dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze); * \li 'zone' to be valid. */ +isc_result_t +dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval); +/*% + * Sets the frequency, in minutes, with which the key repository will be + * checked to see if the keys for this zone have been updated. Any value + * higher than 1440 minutes (24 hours) will be silently reduced. A + * value of zero will return an out-of-range error. + * + * Requires: + * \li 'zone' to be valid. + */ + ISC_LANG_ENDDECLS #endif /* DNS_ZONE_H */ diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 8d8b2f429b..d1f2b6436d 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.601 2011/03/25 23:53:02 each Exp $ */ +/* $Id: zone.c,v 1.602 2011/04/29 21:37:15 each Exp $ */ /*! \file */ @@ -207,6 +207,7 @@ struct dns_zone { isc_time_t signingtime; isc_time_t nsec3chaintime; isc_time_t refreshkeytime; + isc_uint32_t refreshkeyinterval; isc_uint32_t refreshkeycount; isc_uint32_t refresh; isc_uint32_t retry; @@ -770,6 +771,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { isc_time_settoepoch(&zone->signingtime); isc_time_settoepoch(&zone->nsec3chaintime); isc_time_settoepoch(&zone->refreshkeytime); + zone->refreshkeyinterval = 0; zone->refreshkeycount = 0; zone->refresh = DNS_ZONE_DEFAULTREFRESH; zone->retry = DNS_ZONE_DEFAULTRETRY; @@ -14172,48 +14174,52 @@ zone_rekey(dns_zone_t *zone) { UNLOCK_ZONE(zone); } + /* + * If we are doing automatic key maintenance and the key metadata + * indicates there is a key change event scheduled in the future, + * set the key refresh timer. + */ isc_stdtime_get(&now); TIME_NOW(&timenow); isc_time_settoepoch(&zone->refreshkeytime); - for (key = ISC_LIST_HEAD(dnskeys); - key != NULL; - key = ISC_LIST_NEXT(key, link)) { - isc_stdtime_t then; - isc_time_t timethen; - - /* - * If we are doing automatic key maintenance and the - * key metadata indicates there is a key change event - * scheduled in the future, set the key refresh timer. - */ - if (!DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) - break; - - then = now; - result = next_keyevent(key->key, &then); - if (result != ISC_R_SUCCESS) - continue; - - DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen); - LOCK_ZONE(zone); - if (isc_time_isepoch(&zone->refreshkeytime) || - isc_time_compare(&timethen, &zone->refreshkeytime) < 0) { - zone->refreshkeytime = timethen; - zone_settimer(zone, &timenow); - } - UNLOCK_ZONE(zone); - } /* - * If no key event is scheduled, we should still check the key - * repository for updates every so often. (Currently this is - * hard-coded to 12 hours, but it could be configurable.) + * If we're doing key maintenance, set the key refresh timer to + * the next scheduled key event or to 'dnssec-loadkeys-interval' + * seconds in the future, whichever is sooner. */ - if (isc_time_isepoch(&zone->refreshkeytime)) - DNS_ZONE_TIME_ADD(&timenow, (3600 * 12), &zone->refreshkeytime); + if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) { + isc_time_t timethen; + isc_stdtime_t then; - isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80); - dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf); + LOCK_ZONE(zone); + DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval, + &timethen); + zone->refreshkeytime = timethen; + UNLOCK_ZONE(zone); + + for (key = ISC_LIST_HEAD(dnskeys); + key != NULL; + key = ISC_LIST_NEXT(key, link)) { + then = now; + result = next_keyevent(key->key, &then); + if (result != ISC_R_SUCCESS) + continue; + + DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen); + LOCK_ZONE(zone); + if (isc_time_compare(&timethen, + &zone->refreshkeytime) < 0) { + zone->refreshkeytime = timethen; + } + UNLOCK_ZONE(zone); + } + + zone_settimer(zone, &timenow); + + isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80); + dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf); + } failure: dns_diff_clear(&diff); @@ -14306,3 +14312,16 @@ dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) UNLOCK_ZONE(zone); return result; } + +isc_result_t +dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) { + REQUIRE(DNS_ZONE_VALID(zone)); + if (interval == 0) + return (ISC_R_RANGE); + /* Maximum value: 24 hours (3600 minutes) */ + if (interval > (24 * 60)) + interval = (24 * 60); + /* Multiply by 60 for seconds */ + zone->refreshkeyinterval = interval * 60; + return (ISC_R_SUCCESS); +} diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index a1c0aa7746..8546878aa2 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.134 2011/03/11 06:11:27 marka Exp $ */ +/* $Id: namedconf.c,v 1.135 2011/04/29 21:37:15 each Exp $ */ /*! \file */ @@ -1341,6 +1341,7 @@ zone_clauses[] = { { "check-wildcard", &cfg_type_boolean, 0 }, { "dialup", &cfg_type_dialuptype, 0 }, { "dnssec-dnskey-kskonly", &cfg_type_boolean, 0 }, + { "dnssec-loadkeys-interval", &cfg_type_uint32, 0 }, { "dnssec-secure-to-insecure", &cfg_type_boolean, 0 }, { "forward", &cfg_type_forwardtype, 0 }, { "forwarders", &cfg_type_portiplist, 0 },