From: Evan Hunt Date: Tue, 10 Feb 2015 21:12:55 +0000 (-0800) Subject: [v9_9] 5011 fixes X-Git-Tag: v9.9.7rc2~18 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=efe260cc94b0d85dd2fe4f44b47a17d286d3385e;p=thirdparty%2Fbind9.git [v9_9] 5011 fixes 4056. [bug] Fixed several small bugs in automatic trust anchor management, including a memory leak and a possible loss of key state information. [RT #38458] --- diff --git a/CHANGES b/CHANGES index e7e62df715f..ef3d5bc7335 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +4056. [bug] Fixed several small bugs in automatic trust anchor + management, including a memory leak and a possible + loss of key state information. [RT #38458] + 4057. [bug] 'dnssec-dsfromkey -T 0' failed to add ttl field. [RT #38565] diff --git a/bin/named/main.c b/bin/named/main.c index b6c92c9d7ff..6e340cc13c4 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -100,6 +100,10 @@ #define BACKTRACE_MAXFRAME 128 #endif +extern unsigned int dns_zone_mkey_hour; +extern unsigned int dns_zone_mkey_day; +extern unsigned int dns_zone_mkey_month; + static isc_boolean_t want_stats = ISC_FALSE; static char program_name[ISC_DIR_NAMEMAX] = "named"; static char absolute_conffile[ISC_DIR_PATHMAX]; @@ -536,7 +540,38 @@ parse_command_line(int argc, char *argv[]) { ns_g_nosyslog = ISC_TRUE; else if (!strcmp(isc_commandline_argument, "nonearest")) ns_g_nonearest = ISC_TRUE; - else if (!strcmp(isc_commandline_argument, "notcp")) + else if (!strncmp(isc_commandline_argument, + "mkeytimers=", 11)) + { + p = strtok(isc_commandline_argument + 11, "/"); + if (p == NULL) + ns_main_earlyfatal("bad mkeytimer"); + dns_zone_mkey_hour = atoi(p); + if (dns_zone_mkey_hour == 0) + ns_main_earlyfatal("bad mkeytimer"); + + p = strtok(NULL, "/"); + if (p == NULL) { + dns_zone_mkey_day = + (24 * dns_zone_mkey_hour); + dns_zone_mkey_month = + (30 * dns_zone_mkey_day); + break; + } + dns_zone_mkey_day = atoi(p); + if (dns_zone_mkey_day < dns_zone_mkey_hour) + ns_main_earlyfatal("bad mkeytimer"); + + p = strtok(NULL, "/"); + if (p == NULL) { + dns_zone_mkey_month = + (30 * dns_zone_mkey_day); + break; + } + dns_zone_mkey_month = atoi(p); + if (dns_zone_mkey_month < dns_zone_mkey_day) + ns_main_earlyfatal("bad mkeytimer"); + } else if (!strcmp(isc_commandline_argument, "notcp")) ns_g_notcp = ISC_TRUE; else fprintf(stderr, "unknown -T flag '%s\n", diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh index 713dc78f8fb..feeef5536df 100644 --- a/bin/tests/system/dnssec/clean.sh +++ b/bin/tests/system/dnssec/clean.sh @@ -16,7 +16,8 @@ # PERFORMANCE OF THIS SOFTWARE. rm -f */K* */keyset-* */dsset-* */dlvset-* */signedkey-* */*.signed -rm -f */trusted.conf */managed.conf */tmp* */*.jnl */*.bk +rm -f */trusted.conf */managed.conf */revoked.conf +rm -f */tmp* */*.jnl */*.bk */*.jbk rm -f ns1/root.db ns2/example.db ns3/secure.example.db rm -f ns3/unsecure.example.db ns3/bogus.example.db ns3/keyless.example.db rm -f ns3/dynamic.example.db ns3/dynamic.example.db.signed.jnl @@ -50,7 +51,7 @@ rm -f signer/*.db rm -f signer/signer.out.* rm -f ns2/algroll.db rm -f ns3/kskonly.example.db -rm -f ns4/named.conf +rm -f ns4/named.conf ns5/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 @@ -79,3 +80,4 @@ rm -f ns3/dnskey-nsec3-unknown.example.db rm -f ns3/dnskey-nsec3-unknown.example.db.tmp rm -f ns3/dnskey-unknown.example.db rm -f ns3/dnskey-unknown.example.db.tmp +rm -f named.secroots.test* diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh index 9d8108cc1a9..614b3bb2fd1 100644 --- a/bin/tests/system/dnssec/ns3/sign.sh +++ b/bin/tests/system/dnssec/ns3/sign.sh @@ -15,8 +15,6 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: sign.sh,v 1.43 2011/11/04 05:36:28 each Exp $ - SYSTEMTESTTOP=../.. . $SYSTEMTESTTOP/conf.sh @@ -505,5 +503,5 @@ zonefile=future.example.db kskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone` zskname=`$KEYGEN -q -r $RANDFILE $zone` cat $infile $kskname.key $zskname.key >$zonefile -$SIGNER -P -s +3600 -r $RANDFILE -o $zone $zonefile # > /dev/null 2>&1 +$SIGNER -P -s +3600 -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1 cp -f $kskname.key trusted-future.key diff --git a/bin/tests/system/dnssec/ns5/named.conf b/bin/tests/system/dnssec/ns5/named1.conf similarity index 89% rename from bin/tests/system/dnssec/ns5/named.conf rename to bin/tests/system/dnssec/ns5/named1.conf index 64892ca10fb..1a13a9f7764 100644 --- a/bin/tests/system/dnssec/ns5/named.conf +++ b/bin/tests/system/dnssec/ns5/named1.conf @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: named.conf,v 1.25 2007/06/18 23:47:28 tbox Exp $ */ - // NS5 controls { /* empty */ }; @@ -35,6 +33,16 @@ options { dnssec-validation yes; }; +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; }; +}; + + zone "." { type hint; file "../../common/root.hint"; diff --git a/bin/tests/system/dnssec/ns5/named2.conf b/bin/tests/system/dnssec/ns5/named2.conf new file mode 100644 index 00000000000..5b60285e279 --- /dev/null +++ b/bin/tests/system/dnssec/ns5/named2.conf @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2004, 2006, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2000, 2001 Internet Software Consortium. + * + * 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. + */ + +// NS5 + +controls { /* empty */ }; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.5 port 9953 allow { any; } keys { rndc_key; }; +}; + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port 5300; + pid-file "named.pid"; + listen-on { 10.53.0.5; 127.0.0.1; }; + listen-on-v6 { none; }; + recursion yes; +}; + +view root { + match-destinations { 127.0.0.1; }; + + zone "." { + type master; + file "root.db.signed"; + }; +}; + +view other { +include "revoked.conf"; + + zone "." { + type static-stub; + server-addresses { 127.0.0.1; }; + }; +}; diff --git a/bin/tests/system/dnssec/ns5/sign.sh b/bin/tests/system/dnssec/ns5/sign.sh new file mode 100644 index 00000000000..16fe760d8b4 --- /dev/null +++ b/bin/tests/system/dnssec/ns5/sign.sh @@ -0,0 +1,42 @@ +#!/bin/sh -e +# +# Copyright (C) 2015 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. + +SYSTEMTESTTOP=../.. +. $SYSTEMTESTTOP/conf.sh + +zone=. +infile=../ns1/root.db.in +zonefile=root.db.signed + +keyname=`$KEYGEN -r $RANDFILE -qfk $zone` + +# copy the KSK out first, then revoke it +cat $keyname.key | grep -v '^; ' | $PERL -n -e ' +local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split; +local $key = join("", @rest); +print < revoked.conf + +$SETTIME -R now ${keyname}.key > /dev/null + +# create a current set of keys, and sign the root zone +$KEYGEN -r $RANDFILE -q $zone > /dev/null +$KEYGEN -r $RANDFILE -qfk $zone > /dev/null +$SIGNER -S -r $RANDFILE -o $zone -f $zonefile $infile > /dev/null 2>&1 diff --git a/bin/tests/system/dnssec/setup.sh b/bin/tests/system/dnssec/setup.sh index 797e011a063..b376ed007c5 100644 --- a/bin/tests/system/dnssec/setup.sh +++ b/bin/tests/system/dnssec/setup.sh @@ -28,4 +28,8 @@ echo "a.bogus.example. A 10.0.0.22" >>../ns3/bogus.example.db.signed cd ../ns3 && cp -f siginterval1.conf siginterval.conf cd ../ns4 && cp -f named1.conf named.conf -cd ../ns5 && cp -f trusted.conf.bad trusted.conf +cd ../ns5 && { + cp -f trusted.conf.bad trusted.conf + cp -f named1.conf named.conf + $SHELL sign.sh +} diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 0c9ef4639bd..1cf0cd8d4eb 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -15,8 +15,6 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id$ - SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh @@ -1530,9 +1528,10 @@ echo "I:checking rndc secroots ($n)" ret=0 $RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 secroots 2>&1 | sed 's/^/I:ns1 /' keyid=`cat ns1/managed.key.id` -linecount=`grep "./RSAMD5/$keyid ; trusted" ns4/named.secroots | wc -l` +cp ns4/named.secroots named.secroots.test$n +linecount=`grep "./RSAMD5/$keyid ; trusted" named.secroots.test$n | wc -l` [ "$linecount" -eq 1 ] || ret=1 -linecount=`cat ns4/named.secroots | wc -l` +linecount=`cat named.secroots.test$n | wc -l` [ "$linecount" -eq 5 ] || ret=1 n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi @@ -2299,10 +2298,11 @@ if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` echo "I:check KEYDATA records are printed in human readable form in key zone ($n)" -# force the zone to be written out +# force the managed-keys zone to be written out $PERL $SYSTEMTESTTOP/stop.pl --use-rndc . ns4 ret=0 grep KEYDATA ns4/managed-keys.bind > /dev/null || ret=1 +grep "next refresh:" ns4/managed-keys.bind > /dev/null || ret=1 # restart the server $PERL $SYSTEMTESTTOP/start.pl --noclean --restart . ns4 n=`expr $n + 1` @@ -2504,5 +2504,16 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:checking initialization with a revoked managed key ($n)" +ret=0 +cp ns5/named2.conf ns5/named.conf +$RNDC -c ../common/rndc.conf -s 10.53.0.5 -p 9953 reconfig 2>&1 | sed 's/^/I:ns5 /' +sleep 3 +$DIG $DIGOPTS +dnssec -p 5300 @10.53.0.5 SOA . > dig.out.ns5.test$n +grep "status: NOERROR" 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` + echo "I:exit status: $status" exit $status diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index fd844907f69..6960bda51b1 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -262,6 +262,13 @@ processes to grow to very large sizes. [RT #38454] + + + Fixed some bugs in RFC 5011 trust anchor management, + including a memory leak and a possible loss of state + information.[RT #38458] + + diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c index fae2bce8dbe..1e5741863fa 100644 --- a/lib/dns/rdata/generic/keydata_65533.c +++ b/lib/dns/rdata/generic/keydata_65533.c @@ -14,11 +14,12 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - #ifndef GENERIC_KEYDATA_65533_C #define GENERIC_KEYDATA_65533_C 1 +#include +#include + #include #define RRTYPE_KEYDATA_ATTRIBUTES (0) @@ -97,7 +98,7 @@ totext_keydata(ARGS_TOTEXT) { char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; - unsigned long when; + unsigned long refresh, add, remove; char algbuf[DNS_NAME_FORMATSIZE]; const char *keyinfo; @@ -109,21 +110,21 @@ totext_keydata(ARGS_TOTEXT) { dns_rdata_toregion(rdata, &sr); /* refresh timer */ - when = uint32_fromregion(&sr); + refresh = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(dns_time32_totext(when, target)); + RETERR(dns_time32_totext(refresh, target)); RETERR(str_totext(" ", target)); /* add hold-down */ - when = uint32_fromregion(&sr); + add = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(dns_time32_totext(when, target)); + RETERR(dns_time32_totext(add, target)); RETERR(str_totext(" ", target)); /* remove hold-down */ - when = uint32_fromregion(&sr); + remove = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(dns_time32_totext(when, target)); + RETERR(dns_time32_totext(remove, target)); RETERR(str_totext(" ", target)); /* flags */ @@ -176,6 +177,10 @@ totext_keydata(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { isc_region_t tmpr; + char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + isc_time_t t; RETERR(str_totext(" ; ", target)); RETERR(str_totext(keyinfo, target)); @@ -189,6 +194,47 @@ totext_keydata(ARGS_TOTEXT) { isc_region_consume(&tmpr, 12); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + isc_stdtime_t now; + + isc_stdtime_get(&now); + + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; next refresh: ", target)); + isc_time_set(&t, refresh, 0); + isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf)); + RETERR(str_totext(rbuf, target)); + + if (add == 0) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; no trust", target)); + } else { + RETERR(str_totext(tctx->linebreak, target)); + if (add < now) { + RETERR(str_totext("; trusted since: ", + target)); + } else { + RETERR(str_totext("; trust pending: ", + target)); + } + isc_time_set(&t, add, 0); + isc_time_formathttptimestamp(&t, abuf, + sizeof(abuf)); + RETERR(str_totext(abuf, target)); + } + + if (remove != 0) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; removal pending: ", + target)); + isc_time_set(&t, remove, 0); + isc_time_formathttptimestamp(&t, dbuf, + sizeof(dbuf)); + RETERR(str_totext(dbuf, target)); + } + } + } return (ISC_R_SUCCESS); } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index edefe8bcb00..ecd424f4b82 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -661,6 +661,16 @@ struct dns_asyncload { #define DAY (24*HOUR) #define MONTH (30*DAY) +/* + * These can be overridden by the -T mkeytimers option on the command + * line, so that we can test with shorter periods than specified in + * RFC 5011. + */ +unsigned int dns_zone_mkey_hour = HOUR; +unsigned int dns_zone_mkey_day = (24 * HOUR); +unsigned int dns_zone_mkey_month = (30 * DAY); + + #define SEND_BUFFER_SIZE 2048 static void zone_settimer(dns_zone_t *, isc_time_t *); @@ -3189,7 +3199,7 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { */ static void set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key, - isc_stdtime_t now) + isc_stdtime_t now, isc_boolean_t force) { const char me[] = "set_refreshkeytimer"; isc_stdtime_t then; @@ -3198,6 +3208,8 @@ set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key, ENTER; then = key->refresh; + if (force) + then = now; if (key->addhd > now && key->addhd < then) then = key->addhd; if (key->removehd > now && key->removehd < then) @@ -3277,8 +3289,9 @@ create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, dst_key_name(key), 0, &rdata)); *changed = ISC_TRUE; + /* Refresh new keys from the zone apex as soon as possible. */ - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_TRUE); skip: result = dns_keytable_nextkeynode(keytable, keynode, &nextnode); @@ -3434,8 +3447,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { continue; RUNTIME_CHECK(result == ISC_R_SUCCESS); - /* Set the key refresh timer. */ - set_refreshkeytimer(zone, &keydata, now); + /* Set the key refresh timer to force a fast refresh. */ + set_refreshkeytimer(zone, &keydata, now, ISC_TRUE); /* If the removal timer is nonzero, this key was revoked. */ if (keydata.removehd != 0) { @@ -3703,7 +3716,8 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { result = dns_keytable_find(sr, rrname, &keynode); if ((result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) || - dns_keynode_managed(keynode) == ISC_FALSE) { + dns_keynode_managed(keynode) == ISC_FALSE) + { CHECK(delete_keydata(db, ver, &diff, rrname, rdataset)); changed = ISC_TRUE; @@ -7910,7 +7924,8 @@ zone_sign(dns_zone_t *zone) { static isc_result_t normalize_key(dns_rdata_t *rr, dns_rdata_t *target, - unsigned char *data, int size) { + unsigned char *data, int size) +{ dns_rdata_dnskey_t dnskey; dns_rdata_keydata_t keydata; isc_buffer_t buf; @@ -8007,11 +8022,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) rdset = &kfetch->dnskeysigset; else - return (now + HOUR); + return (now + dns_zone_mkey_hour); result = dns_rdataset_first(rdset); if (result != ISC_R_SUCCESS) - return (now + HOUR); + return (now + dns_zone_mkey_hour); dns_rdataset_current(rdset, &sigrr); result = dns_rdata_tostruct(&sigrr, &sig, NULL); @@ -8026,11 +8041,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { t = exp; } - if (t > (15*DAY)) - t = (15*DAY); + if (t > (15 * dns_zone_mkey_day)) + t = (15 * dns_zone_mkey_day); - if (t < HOUR) - t = HOUR; + if (t < dns_zone_mkey_hour) + t = dns_zone_mkey_hour; } else { t = sig.originalttl / 10; @@ -8040,11 +8055,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { t = exp; } - if (t > DAY) - t = DAY; + if (t > dns_zone_mkey_day) + t = dns_zone_mkey_day; - if (t < HOUR) - t = HOUR; + if (t < dns_zone_mkey_hour) + t = dns_zone_mkey_hour; } return (now + t); @@ -8087,7 +8102,7 @@ minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) if (result != ISC_R_SUCCESS) goto failure; keydata.refresh = refresh_time(kfetch, ISC_TRUE); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); dns_rdata_reset(&rdata); isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); @@ -8130,8 +8145,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { /* Generate a key from keydata */ isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); dns_keydata_todnskey(keydata, &dnskey, NULL); - dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey, - &dnskey, &keyb); + dns_rdata_fromstruct(&rr, keydata->common.rdclass, + dns_rdatatype_dnskey, &dnskey, &keyb); result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (ISC_FALSE); @@ -8139,7 +8154,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { /* See if that key generated any of the signatures */ for (result = dns_rdataset_first(&kfetch->dnskeysigset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&kfetch->dnskeysigset)) { + result = dns_rdataset_next(&kfetch->dnskeysigset)) + { dns_fixedname_t fixed; dns_fixedname_init(&fixed); @@ -8149,8 +8165,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dst_key_alg(dstkey) == sig.algorithm && - (dst_key_id(dstkey) == sig.keyid || - dst_key_rid(dstkey) == sig.keyid)) { + dst_key_rid(dstkey) == sig.keyid) + { result = dns_dnssec_verify2(keyname, &kfetch->dnskeyset, dstkey, ISC_FALSE, mctx, &sigrr, @@ -8312,8 +8328,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_trust_secure; kfetch->dnskeysigset.trust = dns_trust_secure; - dns_keytable_detachkeynode(secroots, - &keynode); break; } } @@ -8324,6 +8338,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { keynode = nextnode; } + if (keynode != NULL) + dns_keytable_detachkeynode(secroots, &keynode); + if (kfetch->dnskeyset.trust == dns_trust_secure) break; } @@ -8368,31 +8385,34 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { isc_boolean_t deletekey = ISC_FALSE; if (!secure) { - if (now > keydata.removehd) + if (keydata.removehd != 0 && + keydata.removehd <= now) deletekey = ISC_TRUE; - } else if (now < keydata.addhd) { + } else if (keydata.addhd == 0) { + deletekey = ISC_TRUE; + } else if (keydata.addhd > now) { dns_zone_log(zone, ISC_LOG_WARNING, "Pending key unexpectedly missing " "from %s; restarting acceptance " "timer", namebuf); - keydata.addhd = now + MONTH; + if (keydata.addhd < now + dns_zone_mkey_month) + keydata.addhd = + now + dns_zone_mkey_month; keydata.refresh = refresh_time(kfetch, ISC_FALSE); - } else if (keydata.addhd == 0) { - keydata.addhd = now; } else if (keydata.removehd == 0) { dns_zone_log(zone, ISC_LOG_WARNING, "Active key unexpectedly missing " "from %s", namebuf); - keydata.refresh = now + HOUR; - } else if (now > keydata.removehd) { + keydata.refresh = now + dns_zone_mkey_hour; + } else if (keydata.removehd <= now) { deletekey = ISC_TRUE; } else { keydata.refresh = refresh_time(kfetch, ISC_FALSE); } - if (secure || deletekey) { + if (secure || deletekey) { /* Delete old version */ CHECK(update_one_rr(kfetch->db, ver, &diff, DNS_DIFFOP_DEL, keyname, 0, @@ -8413,7 +8433,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { DNS_DIFFOP_ADD, keyname, 0, &keydatarr)); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); } } @@ -8435,7 +8455,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { */ for (result = dns_rdataset_first(&kfetch->dnskeyset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&kfetch->dnskeyset)) { + result = dns_rdataset_next(&kfetch->dnskeyset)) + { isc_boolean_t revoked = ISC_FALSE; isc_boolean_t newkey = ISC_FALSE; isc_boolean_t updatekey = ISC_FALSE; @@ -8471,34 +8492,43 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_view_untrust(zone->view, keyname, &dnskey, mctx); + /* But ensure there's a null key */ + fail_secure(zone, keyname); + /* If initializing, delete now */ if (keydata.addhd == 0) deletekey = ISC_TRUE; - else - keydata.removehd = now + MONTH; + else { + keydata.removehd = now + + dns_zone_mkey_month; + keydata.flags |= + DNS_KEYFLAG_REVOKE; + } } else if (keydata.removehd < now) { /* Scheduled for removal */ deletekey = ISC_TRUE; } - } 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 (revoked && 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 * seems it used to be. * Remove it now and add it - * back as if it were a fresh key. + * back as if it were a fresh key, + * with a 30 day acceptance timer. */ deletekey = ISC_TRUE; newkey = ISC_TRUE; + keydata.removehd = 0; + keydata.addhd = + now + dns_zone_mkey_month; } else if (keydata.addhd > now) pending++; else if (keydata.addhd == 0) @@ -8506,6 +8536,13 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { if (keydata.addhd <= now) trustkey = ISC_TRUE; + } else if (keydata.addhd > now) { + /* + * Not secure, and key is pending: + * reset the acceptance timer + */ + pending++; + keydata.addhd = now + dns_zone_mkey_month; } if (!deletekey && !newkey) @@ -8567,7 +8604,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0, NULL); - keydata.addhd = initializing ? now : now + MONTH; + keydata.addhd = initializing + ? now : now + dns_zone_mkey_month; keydata.refresh = refresh_time(kfetch, ISC_FALSE); dns_rdata_reset(&keydatarr); isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); @@ -8590,7 +8628,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { if (secure && !deletekey) { INSIST(newkey || updatekey); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); } } @@ -8804,7 +8842,7 @@ zone_refreshkeys(dns_zone_t *zone) { char timebuf[80]; TIME_NOW(&timenow); - DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen); + DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen); zone->refreshkeytime = timethen; zone_settimer(zone, &timenow); diff --git a/lib/isc/httpd.c b/lib/isc/httpd.c index 46dab296f6a..966b6517486 100644 --- a/lib/isc/httpd.c +++ b/lib/isc/httpd.c @@ -648,7 +648,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) { isc_socketevent_t *sev = (isc_socketevent_t *)ev; isc_httpdurl_t *url; isc_time_t now; - char datebuf[32]; /* Only need 30, but safety first */ + char datebuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; ENTER("recv"); @@ -729,7 +729,7 @@ isc_httpd_recvdone(isc_task_t *task, isc_event_t *ev) { isc_httpd_addheader(httpd, "Expires", datebuf); if (url != NULL && url->isstatic) { - char loadbuf[32]; + char loadbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; isc_time_formathttptimestamp(&url->loadtime, loadbuf, sizeof(loadbuf)); isc_httpd_addheader(httpd, "Last-Modified", loadbuf); diff --git a/lib/isc/tests/time_test.c b/lib/isc/tests/time_test.c index caddec2bec4..eb56ff9fb65 100644 --- a/lib/isc/tests/time_test.c +++ b/lib/isc/tests/time_test.c @@ -29,7 +29,7 @@ ATF_TC_HEAD(isc_time_parsehttptimestamp, tc) { ATF_TC_BODY(isc_time_parsehttptimestamp, tc) { isc_result_t result; isc_time_t t, x; - char buf[100]; + char buf[ISC_FORMATHTTPTIMESTAMP_SIZE]; setenv("TZ", "PST8PDT", 1); result = isc_time_now(&t); diff --git a/lib/isc/unix/include/isc/time.h b/lib/isc/unix/include/isc/time.h index 2a83f099305..ade55247a93 100644 --- a/lib/isc/unix/include/isc/time.h +++ b/lib/isc/unix/include/isc/time.h @@ -43,6 +43,13 @@ struct isc_interval { extern const isc_interval_t * const isc_interval_zero; +/* + * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially + * more for other locales to handle longer national abbreviations when + * expanding strftime's %a and %b. + */ +#define ISC_FORMATHTTPTIMESTAMP_SIZE 50 + ISC_LANG_BEGINDECLS void diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c index 890b9192ba5..ea1ddc0ae03 100644 --- a/lib/isc/unix/time.c +++ b/lib/isc/unix/time.c @@ -404,6 +404,9 @@ isc_time_formathttptimestamp(const isc_time_t *t, char *buf, unsigned int len) { REQUIRE(len > 0); + /* + * 5 spaces, 1 comma, 3 GMT, 2 %d, 4 %Y, 8 %H:%M:%S, 3+ %a, 3+ %b (29+) + */ now = (time_t)t->seconds; flen = strftime(buf, len, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); INSIST(flen < len); diff --git a/lib/isc/win32/include/isc/time.h b/lib/isc/win32/include/isc/time.h index fe842ab95bd..bfd5bc0d622 100644 --- a/lib/isc/win32/include/isc/time.h +++ b/lib/isc/win32/include/isc/time.h @@ -41,6 +41,13 @@ struct isc_interval { LIBISC_EXTERNAL_DATA extern const isc_interval_t * const isc_interval_zero; +/* + * ISC_FORMATHTTPTIMESTAMP_SIZE needs to be 30 in C locale and potentially + * more for other locales to handle longer national abbreviations when + * expanding strftime's %a and %b. + */ +#define ISC_FORMATHTTPTIMESTAMP_SIZE 50 + ISC_LANG_BEGINDECLS void