+3356. [bug] Cap the TTL of signed RRsets when RRSIGs are
+ approaching their expiry, so they don't remain
+ in caches after expiry. [RT #26429]
+
--- 9.7.7b1 released ---
3354. [func] Improve OpenSSL error logging. [RT #29932]
#include <isc/hex.h>
#include <isc/mem.h>
+#include <isc/serial.h>
#include <isc/stats.h>
#include <isc/util.h>
*/
static void
mark_secure(ns_client_t *client, dns_db_t *db, dns_name_t *name,
- isc_uint32_t ttl, dns_rdataset_t *rdataset,
+ dns_rdata_rrsig_t *rrsig, dns_rdataset_t *rdataset,
dns_rdataset_t *sigrdataset)
{
isc_result_t result;
dns_dbnode_t *node = NULL;
+ dns_clientinfomethods_t cm;
+ dns_clientinfo_t ci;
+ isc_stdtime_t now;
+
rdataset->trust = dns_trust_secure;
sigrdataset->trust = dns_trust_secure;
result = dns_db_findnode(db, name, ISC_TRUE, &node);
if (result != ISC_R_SUCCESS)
return;
- /*
- * Bound the validated ttls then minimise.
- */
- if (sigrdataset->ttl > ttl)
- sigrdataset->ttl = ttl;
- if (rdataset->ttl > ttl)
- rdataset->ttl = ttl;
- if (rdataset->ttl > sigrdataset->ttl)
- rdataset->ttl = sigrdataset->ttl;
- else
- sigrdataset->ttl = rdataset->ttl;
+
+ isc_stdtime_get(&now);
+ dns_rdataset_trimttl(rdataset, sigrdataset, rrsig, now,
+ client->view->acceptexpired);
(void)dns_db_addrdataset(db, node, NULL, client->now, rdataset,
0, NULL);
client->view->acceptexpired)) {
dst_key_free(&key);
dns_rdataset_disassociate(&keyrdataset);
- mark_secure(client, db, name,
- rrsig.originalttl,
+ mark_secure(client, db, name, &rrsig,
rdataset, sigrdataset);
return (ISC_TRUE);
}
LOWER NS NS.LOWER
NS.LOWER A 10.53.0.3
+
+expiring NS ns.expiring
+ns.expiring A 10.53.0.3
for subdomain in secure bogus dynamic keyless nsec3 optout nsec3-unknown \
optout-unknown multiple rsasha256 rsasha512 kskonly update-nsec3 \
- auto-nsec auto-nsec3 secure.below-cname ttlpatch expired upper lower
+ auto-nsec auto-nsec3 secure.below-cname ttlpatch expired expiring upper \
+ lower
do
cp ../ns3/dsset-$subdomain.example. .
done
3600 ; minimum (1 hour)
)
NS ns
+ MX 10 mx
ns A 10.53.0.3
+mx A 10.0.0.30
a A 10.0.0.1
b A 10.0.0.2
normalthenrrsig A 10.0.0.28
rrsigonly A 10.0.0.29
+
+
3600 ; minimum (1 hour)
)
NS ns
+ MX 10 mx
ns A 10.53.0.3
+mx A 10.0.0.30
a A 10.0.0.1
b A 10.0.0.2
zskname=`$KEYGEN -q -r $RANDFILE -f KSK $zone`
cp $infile $zonefile
$SIGNER -S -r $RANDFILE -e now+1mi -o $zone $zonefile > /dev/null 2>&1
-rm -f ${zskname}.private ${kskname}.private
+mv -f ${zskname}.private ${zskname}.private.moved
+mv -f ${kskname}.private ${kskname}.private.moved
#
# A zone where the signer's name has been forced to uppercase.
--- /dev/null
+/*
+ * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: named2.conf,v 1.3 2011/01/04 23:47:13 tbox Exp $ */
+
+// NS4
+
+controls { /* empty */ };
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port 5300;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ acache-enable yes;
+ dnssec-enable yes;
+ dnssec-validation auto;
+ bindkeys-file "managed.conf";
+ dnssec-accept-expired yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-md5;
+};
+
+controls {
+ inet 10.53.0.4 port 9953 allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../common/root.hint";
+};
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
+echo "I:testing TTL is capped at RRSIG expiry time ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 freeze expiring.example 2>&1 | sed 's/^/I:ns3 /'
+(
+cd ns3
+RANDFILE=../random.data
+for file in K*.moved; do
+ mv $file `basename $file .moved`
+done
+$SIGNER -S -r $RANDFILE -N increment -e now+1mi -o expiring.example expiring.example.db > /dev/null 2>&1
+) || ret=1
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reload expiring.example 2>&1 | sed 's/^/I:ns3 /'
+
+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 flush
+$DIG +noall +answer +dnssec +cd -p 5300 expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
+$DIG +noall +answer +dnssec -p 5300 expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
+ttls=`awk '{print $2}' dig.out.ns4.1.$n`
+ttls2=`awk '{print $2}' dig.out.ns4.2.$n`
+for ttl in $ttls; do
+ [ $ttl -eq 300 ] || ret=1
+done
+for ttl in $ttls2; do
+ [ $ttl -le 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:testing TTL is capped at RRSIG expiry time for records in the additional section ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 flush
+$DIG +noall +additional +dnssec +cd -p 5300 expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
+$DIG +noall +additional +dnssec -p 5300 expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
+ttls=`awk '{print $2}' dig.out.ns4.1.$n`
+ttls2=`awk '{print $2}' dig.out.ns4.2.$n`
+for ttl in $ttls; do
+ [ $ttl -eq 300 ] || ret=1
+done
+for ttl in $ttls2; do
+ [ $ttl -le 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+cp ns4/named3.conf ns4/named.conf
+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 reconfig 2>&1 | sed 's/^/I:ns4 /'
+sleep 3
+
+echo "I:testing TTL of about to expire RRsets with dnssec-accept-expired yes; ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 flush
+$DIG +noall +answer +dnssec +cd -p 5300 expiring.example soa @10.53.0.4 > dig.out.ns4.1.$n
+$DIG +noall +answer +dnssec -p 5300 expiring.example soa @10.53.0.4 > dig.out.ns4.2.$n
+ttls=`awk '{print $2}' dig.out.ns4.1.$n`
+ttls2=`awk '{print $2}' dig.out.ns4.2.$n`
+for ttl in $ttls; do
+ [ $ttl -eq 300 ] || ret=1
+done
+for ttl in $ttls2; do
+ [ $ttl -le 120 -a $ttl -gt 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)"
+ret=0
+$DIG +noall +answer +dnssec +cd -p 5300 expired.example soa @10.53.0.4 > dig.out.ns4.1.$n
+$DIG +noall +answer +dnssec -p 5300 expired.example soa @10.53.0.4 > dig.out.ns4.2.$n
+ttls=`awk '{print $2}' dig.out.ns4.1.$n`
+ttls2=`awk '{print $2}' dig.out.ns4.2.$n`
+for ttl in $ttls; do
+ [ $ttl -eq 300 ] || ret=1
+done
+for ttl in $ttls2; do
+ [ $ttl -le 120 -a $ttl -gt 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+echo "I:testing TTL is capped at RRSIG expiry time for records in the additional section with dnssec-accept-expired yes; ($n)"
+ret=0
+$RNDC -c ../common/rndc.conf -s 10.53.0.4 -p 9953 flush
+$DIG +noall +additional +dnssec +cd -p 5300 expiring.example mx @10.53.0.4 > dig.out.ns4.1.$n
+$DIG +noall +additional +dnssec -p 5300 expiring.example mx @10.53.0.4 > dig.out.ns4.2.$n
+ttls=`awk '{print $2}' dig.out.ns4.1.$n`
+ttls2=`awk '{print $2}' dig.out.ns4.2.$n`
+for ttl in $ttls; do
+ [ $ttl -eq 300 ] || ret=1
+done
+for ttl in $ttls2; do
+ [ $ttl -le 120 -a $ttl -gt 60 ] || ret=1
+done
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
echo "I:exit status: $status"
exit $status
#include <isc/stdtime.h>
#include <dns/types.h>
+#include <dns/rdatastruct.h>
ISC_LANG_BEGINDECLS
* Mark the rdataset to be expired in the backing database.
*/
+void
+dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
+ isc_boolean_t acceptexpired);
+/*%<
+ * Trim the ttl of 'rdataset' and 'sigrdataset' so that they will expire
+ * at or before 'rrsig->expiretime'. If 'acceptexpired' is true and the
+ * signature has expired or will expire in the next 120 seconds, limit
+ * the ttl to be no more than 120 seconds.
+ *
+ * The ttl is further limited by the original ttl as stored in 'rrsig'
+ * and the original ttl values of 'rdataset' and 'sigrdataset'.
+ *
+ * Requires:
+ * \li 'rdataset' is a valid rdataset.
+ * \li 'sigrdataset' is a valid rdataset.
+ * \li 'rrsig' is non NULL.
+ */
+
const char *
dns_trust_totext(dns_trust_t trust);
/*%<
#include <isc/buffer.h>
#include <isc/mem.h>
#include <isc/random.h>
+#include <isc/serial.h>
#include <isc/util.h>
#include <dns/name.h>
if (rdataset->methods->expire != NULL)
(rdataset->methods->expire)(rdataset);
}
+
+void
+dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,
+ dns_rdata_rrsig_t *rrsig, isc_stdtime_t now,
+ isc_boolean_t acceptexpired)
+{
+ isc_uint32_t ttl = 0;
+
+ REQUIRE(DNS_RDATASET_VALID(rdataset));
+ REQUIRE(DNS_RDATASET_VALID(sigrdataset));
+ REQUIRE(rrsig != NULL);
+
+ /*
+ * If we accept expired RRsets keep them for no more than 120 seconds.
+ */
+ if (acceptexpired &&
+ (isc_serial_le(rrsig->timeexpire, ((now + 120) & 0xffffffff)) ||
+ isc_serial_le(rrsig->timeexpire, now)))
+ ttl = 120;
+ else if (isc_serial_ge(rrsig->timeexpire, now))
+ ttl = rrsig->timeexpire - now;
+
+ ttl = ISC_MIN(ISC_MIN(rdataset->ttl, sigrdataset->ttl),
+ ISC_MIN(rrsig->originalttl, ttl));
+ rdataset->ttl = ttl;
+ sigrdataset->ttl = ttl;
+}
LIBS = @LIBS@ @ATFLIBS@
OBJS = dnstest.@O@
+<<<<<<< HEAD
SRCS = dnstest.c master_test.c time_test.c dbiterator_test.c \
- dbversion_test.c zonemgr_test.c nsec3_test.c
+ dbversion_test.c zonemgr_test.c nsec3_test.c rdataset_test.c
SUBDIRS =
TARGETS = master_test@EXEEXT@ time_test@EXEEXT@ dbiterator_test@EXEEXT@ \
- dbversion_test@EXEEXT@ zonemgr_test@EXEEXT@ nsec3_test@EXEEXT@
+ dbversion_test@EXEEXT@ zonemgr_test@EXEEXT@ nsec3_test@EXEEXT@ \
+ rdataset_test@EXEEXT@
@BIND9_MAKE_RULES@
${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
nsec3_test.@O@ dnstest.@O@ ${DNSLIBS} \
${ISCLIBS} ${LIBS}
+
+rdataset_test@EXEEXT@: rdataset_test.@O@ dnstest.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ rdataset_test.@O@ dnstest.@O@ ${DNSLIBS} \
+ ${ISCLIBS} ${LIBS}
unit::
sh ${top_srcdir}/unit/unittest.sh
--- /dev/null
+/*
+ * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <atf-c.h>
+
+#include <unistd.h>
+
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+
+#include "dnstest.h"
+
+
+/*
+ * Individual unit tests
+ */
+
+/* Successful load test */
+ATF_TC(trimttl);
+ATF_TC_HEAD(trimttl, tc) {
+ atf_tc_set_md_var(tc, "descr", "dns_master_loadfile() loads a "
+ "valid master file and returns success");
+}
+ATF_TC_BODY(trimttl, tc) {
+ isc_result_t result;
+ dns_rdataset_t rdataset, sigrdataset;
+ dns_rdata_rrsig_t rrsig;
+ isc_stdtime_t ttltimenow, ttltimeexpire;
+
+ ttltimenow = 10000000;
+ ttltimeexpire = ttltimenow + 800;
+
+ UNUSED(tc);
+
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigrdataset);
+
+ result = dns_test_begin(NULL, ISC_FALSE);
+ ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+ rdataset.ttl = 900;
+ sigrdataset.ttl = 1000;
+ rrsig.timeexpire = ttltimeexpire;
+ rrsig.originalttl = 1000;
+
+ dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow,
+ ISC_TRUE);
+ ATF_REQUIRE_EQ(rdataset.ttl, 800);
+ ATF_REQUIRE_EQ(sigrdataset.ttl, 800);
+
+ rdataset.ttl = 900;
+ sigrdataset.ttl = 1000;
+ rrsig.timeexpire = ttltimenow - 200;
+ rrsig.originalttl = 1000;
+
+ dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow,
+ ISC_TRUE);
+ ATF_REQUIRE_EQ(rdataset.ttl, 120);
+ ATF_REQUIRE_EQ(sigrdataset.ttl, 120);
+
+ rdataset.ttl = 900;
+ sigrdataset.ttl = 1000;
+ rrsig.timeexpire = ttltimenow - 200;
+ rrsig.originalttl = 1000;
+
+ dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow,
+ ISC_FALSE);
+ ATF_REQUIRE_EQ(rdataset.ttl, 0);
+ ATF_REQUIRE_EQ(sigrdataset.ttl, 0);
+
+ sigrdataset.ttl = 900;
+ rdataset.ttl = 1000;
+ rrsig.timeexpire = ttltimeexpire;
+ rrsig.originalttl = 1000;
+
+ dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow,
+ ISC_TRUE);
+ ATF_REQUIRE_EQ(rdataset.ttl, 800);
+ ATF_REQUIRE_EQ(sigrdataset.ttl, 800);
+
+ sigrdataset.ttl = 900;
+ rdataset.ttl = 1000;
+ rrsig.timeexpire = ttltimenow - 200;
+ rrsig.originalttl = 1000;
+
+ dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow,
+ ISC_TRUE);
+ ATF_REQUIRE_EQ(rdataset.ttl, 120);
+ ATF_REQUIRE_EQ(sigrdataset.ttl, 120);
+
+ sigrdataset.ttl = 900;
+ rdataset.ttl = 1000;
+ rrsig.timeexpire = ttltimenow - 200;
+ rrsig.originalttl = 1000;
+
+ dns_rdataset_trimttl(&rdataset, &sigrdataset, &rrsig, ttltimenow,
+ ISC_FALSE);
+ ATF_REQUIRE_EQ(rdataset.ttl, 0);
+ ATF_REQUIRE_EQ(sigrdataset.ttl, 0);
+
+ dns_test_end();
+}
+
+/*
+ * Main
+ */
+ATF_TP_ADD_TCS(tp) {
+ ATF_TP_ADD_TC(tp, trimttl);
+
+ return (atf_no_error());
+}
+
validator_log(val, ISC_LOG_DEBUG(3),
"failed to verify rdataset");
else {
- isc_uint32_t ttl;
isc_stdtime_t now;
isc_stdtime_get(&now);
- ttl = ISC_MIN(event->rdataset->ttl,
- ISC_MIN(val->siginfo->originalttl,
- val->siginfo->timeexpire - now));
- event->rdataset->ttl = ttl;
- event->sigrdataset->ttl = ttl;
+ dns_rdataset_trimttl(event->rdataset,
+ event->sigrdataset,
+ val->siginfo, now,
+ val->view->acceptexpired);
}
if (val->keynode != NULL)