diff --git a/CHANGES b/CHANGES index 58d1190684..3b8bf9b723 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +3960. [bug] 'dig +sigchase' could loop forever. [RT #37220] + 3959. [bug] Updates could be lost if they arrived immediately after a rndc thaw. [RT #37233] diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 533266bcaf..846ccce4a3 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -4695,8 +4695,8 @@ get_trusted_key(isc_mem_t *mctx) dns_rdatacallbacks_init_stdio(&callbacks); callbacks.add = insert_trustedkey; return (dns_master_loadfile(filename, dns_rootname, dns_rootname, - current_lookup->rdclass, 0, &callbacks, - mctx)); + current_lookup->rdclass, DNS_MASTER_NOTTL, + &callbacks, mctx)); } @@ -4896,36 +4896,36 @@ child_of_zone(dns_name_t * name, dns_name_t * zone_name, } isc_result_t -grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) -{ - isc_result_t result; - dns_rdata_t sigrdata = DNS_RDATA_INIT; +grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) { dns_rdata_sig_t siginfo; + dns_rdataset_t mysigrdataset; + isc_result_t result; - result = dns_rdataset_first(sigrdataset); + dns_rdataset_init(&mysigrdataset); + dns_rdataset_clone(sigrdataset, &mysigrdataset); + + result = dns_rdataset_first(&mysigrdataset); check_result(result, "empty RRSIG dataset"); - dns_rdata_init(&sigrdata); do { - dns_rdataset_current(sigrdataset, &sigrdata); + dns_rdata_t sigrdata = DNS_RDATA_INIT; + + dns_rdataset_current(&mysigrdataset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); check_result(result, "sigrdata tostruct siginfo"); if (dns_name_compare(&siginfo.signer, zone_name) == 0) { - dns_rdata_freestruct(&siginfo); - dns_rdata_reset(&sigrdata); - return (ISC_R_SUCCESS); + result = ISC_R_SUCCESS; + goto cleanup; } + } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS); - dns_rdata_freestruct(&siginfo); - dns_rdata_reset(&sigrdata); + result = ISC_R_FAILURE; +cleanup: + dns_rdataset_disassociate(&mysigrdataset); - } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS); - - dns_rdata_reset(&sigrdata); - - return (ISC_R_FAILURE); + return (result); } @@ -5005,26 +5005,30 @@ contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, isc_mem_t *mctx) { - isc_result_t result; - dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_t myrdataset; dst_key_t *dnsseckey = NULL; int i; + isc_result_t result; if (name == NULL || rdataset == NULL) return (ISC_R_FAILURE); - result = dns_rdataset_first(rdataset); + dns_rdataset_init(&myrdataset); + dns_rdataset_clone(rdataset, &myrdataset); + + result = dns_rdataset_first(&myrdataset); check_result(result, "empty rdataset"); do { - dns_rdataset_current(rdataset, &rdata); + dns_rdata_t rdata = DNS_RDATA_INIT; + + dns_rdataset_current(&myrdataset, &rdata); INSIST(rdata.type == dns_rdatatype_dnskey); result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dnsseckey); check_result(result, "dns_dnssec_keyfromrdata"); - for (i = 0; i < tk_list.nb_tk; i++) { if (dst_key_compare(tk_list.key[i], dnsseckey) == ISC_TRUE) { @@ -5033,22 +5037,21 @@ contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset, printf(";; Ok, find a Trusted Key in the " "DNSKEY RRset: %d\n", dst_key_id(dnsseckey)); - if (sigchase_verify_sig_key(name, rdataset, - dnsseckey, - sigrdataset, - mctx) - == ISC_R_SUCCESS) { - dst_key_free(&dnsseckey); - dnsseckey = NULL; - return (ISC_R_SUCCESS); - } + result = sigchase_verify_sig_key(name, rdataset, + dnsseckey, + sigrdataset, + mctx); + if (result == ISC_R_SUCCESS) + goto cleanup; } } + dst_key_free(&dnsseckey); + } while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS); - dns_rdata_reset(&rdata); - if (dnsseckey != NULL) - dst_key_free(&dnsseckey); - } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS); +cleanup: + if (dnsseckey != NULL) + dst_key_free(&dnsseckey); + dns_rdataset_disassociate(&myrdataset); return (ISC_R_NOTFOUND); } @@ -5059,16 +5062,20 @@ sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, isc_mem_t *mctx) { - isc_result_t result; - dns_rdata_t keyrdata = DNS_RDATA_INIT; + dns_rdataset_t mykeyrdataset; dst_key_t *dnsseckey = NULL; + isc_result_t result; - result = dns_rdataset_first(keyrdataset); + dns_rdataset_init(&mykeyrdataset); + dns_rdataset_clone(keyrdataset, &mykeyrdataset); + + result = dns_rdataset_first(&mykeyrdataset); check_result(result, "empty DNSKEY dataset"); - dns_rdata_init(&keyrdata); do { - dns_rdataset_current(keyrdataset, &keyrdata); + dns_rdata_t keyrdata = DNS_RDATA_INIT; + + dns_rdataset_current(&mykeyrdataset, &keyrdata); INSIST(keyrdata.type == dns_rdatatype_dnskey); result = dns_dnssec_keyfromrdata(name, &keyrdata, @@ -5077,18 +5084,19 @@ sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset, result = sigchase_verify_sig_key(name, rdataset, dnsseckey, sigrdataset, mctx); - if (result == ISC_R_SUCCESS) { - dns_rdata_reset(&keyrdata); - dst_key_free(&dnsseckey); - return (ISC_R_SUCCESS); - } + if (result == ISC_R_SUCCESS) + goto cleanup; dst_key_free(&dnsseckey); - dns_rdata_reset(&keyrdata); - } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS); + } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS); - dns_rdata_reset(&keyrdata); + result = ISC_R_NOTFOUND; - return (ISC_R_NOTFOUND); + cleanup: + if (dnsseckey != NULL) + dst_key_free(&dnsseckey); + dns_rdataset_disassociate(&mykeyrdataset); + + return (result); } isc_result_t @@ -5096,16 +5104,23 @@ sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset, dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset, isc_mem_t *mctx) { - isc_result_t result; - dns_rdata_t sigrdata = DNS_RDATA_INIT; dns_rdata_sig_t siginfo; + dns_rdataset_t myrdataset; + dns_rdataset_t mysigrdataset; + isc_result_t result; - result = dns_rdataset_first(sigrdataset); + dns_rdataset_init(&myrdataset); + dns_rdataset_clone(rdataset, &myrdataset); + dns_rdataset_init(&mysigrdataset); + dns_rdataset_clone(sigrdataset, &mysigrdataset); + + result = dns_rdataset_first(&mysigrdataset); check_result(result, "empty RRSIG dataset"); - dns_rdata_init(&sigrdata); do { - dns_rdataset_current(sigrdataset, &sigrdata); + dns_rdata_t sigrdata = DNS_RDATA_INIT; + + dns_rdataset_current(&mysigrdataset, &sigrdata); result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL); check_result(result, "sigrdata tostruct siginfo"); @@ -5116,10 +5131,10 @@ sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset, */ if (siginfo.keyid == dst_key_id(dnsseckey)) { - result = dns_rdataset_first(rdataset); + result = dns_rdataset_first(&myrdataset); check_result(result, "empty DS dataset"); - result = dns_dnssec_verify(name, rdataset, dnsseckey, + result = dns_dnssec_verify(name, &myrdataset, dnsseckey, ISC_FALSE, mctx, &sigrdata); printf(";; VERIFYING "); @@ -5129,19 +5144,18 @@ sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset, printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey), isc_result_totext(result)); - if (result == ISC_R_SUCCESS) { - dns_rdata_reset(&sigrdata); - return (result); - } + if (result == ISC_R_SUCCESS) + goto cleanup; } - dns_rdata_freestruct(&siginfo); - dns_rdata_reset(&sigrdata); + } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS); - } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS); + result = ISC_R_NOTFOUND; - dns_rdata_reset(&sigrdata); + cleanup: + dns_rdataset_disassociate(&myrdataset); + dns_rdataset_disassociate(&mysigrdataset); - return (ISC_R_NOTFOUND); + return (result); } @@ -5149,27 +5163,35 @@ isc_result_t sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset, dns_rdataset_t *dsrdataset, isc_mem_t *mctx) { - isc_result_t result; - dns_rdata_t keyrdata = DNS_RDATA_INIT; - dns_rdata_t newdsrdata = DNS_RDATA_INIT; - dns_rdata_t dsrdata = DNS_RDATA_INIT; dns_rdata_ds_t dsinfo; + dns_rdataset_t mydsrdataset; + dns_rdataset_t mykeyrdataset; dst_key_t *dnsseckey = NULL; + isc_result_t result; unsigned char dsbuf[DNS_DS_BUFFERSIZE]; - result = dns_rdataset_first(dsrdataset); + dns_rdataset_init(&mydsrdataset); + dns_rdataset_clone(dsrdataset, &mydsrdataset); + dns_rdataset_init(&mykeyrdataset); + dns_rdataset_clone(keyrdataset, &mykeyrdataset); + + result = dns_rdataset_first(&mydsrdataset); check_result(result, "empty DSset dataset"); do { - dns_rdataset_current(dsrdataset, &dsrdata); + dns_rdata_t dsrdata = DNS_RDATA_INIT; + + dns_rdataset_current(&mydsrdataset, &dsrdata); result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL); check_result(result, "dns_rdata_tostruct for DS"); - result = dns_rdataset_first(keyrdataset); + result = dns_rdataset_first(&mykeyrdataset); check_result(result, "empty KEY dataset"); do { - dns_rdataset_current(keyrdataset, &keyrdata); + dns_rdata_t keyrdata = DNS_RDATA_INIT; + + dns_rdataset_current(&mykeyrdataset, &keyrdata); INSIST(keyrdata.type == dns_rdatatype_dnskey); result = dns_dnssec_keyfromrdata(name, &keyrdata, @@ -5181,6 +5203,7 @@ sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset, * id of DNSKEY referenced by the DS */ if (dsinfo.key_tag == dst_key_id(dnsseckey)) { + dns_rdata_t newdsrdata = DNS_RDATA_INIT; result = dns_ds_buildrdata(name, &keyrdata, dsinfo.digest_type, @@ -5188,14 +5211,9 @@ sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset, dns_rdata_freestruct(&dsinfo); if (result != ISC_R_SUCCESS) { - dns_rdata_reset(&keyrdata); - dns_rdata_reset(&newdsrdata); - dns_rdata_reset(&dsrdata); - dst_key_free(&dnsseckey); - dns_rdata_freestruct(&dsinfo); printf("Oops: impossible to build" " new DS rdata\n"); - return (result); + goto cleanup; } @@ -5212,34 +5230,26 @@ sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset, dnsseckey, chase_sigkeyrdataset, mctx); - if (result == ISC_R_SUCCESS) { - dns_rdata_reset(&keyrdata); - dns_rdata_reset(&newdsrdata); - dns_rdata_reset(&dsrdata); - dst_key_free(&dnsseckey); - - return (result); - } + if (result == ISC_R_SUCCESS) + goto cleanup; } else { printf(";; This DS is NOT the DS for" " the chasing KEY: FAILED\n"); } - - dns_rdata_reset(&newdsrdata); } dst_key_free(&dnsseckey); - dns_rdata_reset(&keyrdata); - dnsseckey = NULL; - } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS); - dns_rdata_reset(&dsrdata); + } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS); + } while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS); - } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS); + result = ISC_R_NOTFOUND; - dns_rdata_reset(&keyrdata); - dns_rdata_reset(&newdsrdata); - dns_rdata_reset(&dsrdata); + cleanup: + if (dnsseckey != NULL) + dst_key_free(&dnsseckey); + dns_rdataset_disassociate(&mydsrdataset); + dns_rdataset_disassociate(&mykeyrdataset); - return (ISC_R_NOTFOUND); + return (result); } /* @@ -5722,7 +5732,7 @@ getneededrr(dns_message_t *msg) dns_rdatatype_dnskey, &chase_sigkeylookedup); if (result == ISC_R_FAILURE) { - printf("\n;; RRSIG for DNSKEY is missing to continue" + printf("\n;; RRSIG for DNSKEY is missing to continue" " validation : FAILED\n\n"); free_name(&chase_signame, mctx); if (dns_name_dynamic(&chase_name)) @@ -5742,9 +5752,8 @@ getneededrr(dns_message_t *msg) if (chase_dsrdataset == NULL) { result = advanced_rrsearch(&chase_dsrdataset, &chase_signame, - dns_rdatatype_ds, - dns_rdatatype_any, - &chase_dslookedup); + dns_rdatatype_ds, dns_rdatatype_any, + &chase_dslookedup); if (result == ISC_R_FAILURE) { printf("\n;; WARNING There is no DS for the zone: "); dns_name_print(&chase_signame, stdout); @@ -6032,7 +6041,6 @@ prove_nx_domain(dns_message_t *msg, result = dns_rdataset_next(nsecset)) { dns_rdataset_current(nsecset, &nsec); - signsecset = chase_scanname_section(msg, nsecname, dns_rdatatype_rrsig, diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh index f53e9580ef..d2e381c578 100644 --- a/bin/tests/system/dnssec/clean.sh +++ b/bin/tests/system/dnssec/clean.sh @@ -76,3 +76,4 @@ rm -f delve.out* rm -f ns7/split-rrsig.db ns7/split-rrsig.db.unsplit rm -f Kexample.* rm -f keygen.err +rm -f ns3/future.example.db ns3/trusted-future.key diff --git a/bin/tests/system/dnssec/ns2/example.db.in b/bin/tests/system/dnssec/ns2/example.db.in index a9a9937547..36cc88b7b9 100644 --- a/bin/tests/system/dnssec/ns2/example.db.in +++ b/bin/tests/system/dnssec/ns2/example.db.in @@ -151,3 +151,6 @@ NS.LOWER A 10.53.0.3 expiring NS ns.expiring ns.expiring A 10.53.0.3 + +future NS ns.future +ns.future A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns3/future.example.db.in b/bin/tests/system/dnssec/ns3/future.example.db.in new file mode 100644 index 0000000000..e41d15b9af --- /dev/null +++ b/bin/tests/system/dnssec/ns3/future.example.db.in @@ -0,0 +1,45 @@ +; Copyright (C) 2006, 2008 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: optout.example.db.in,v 1.3 2008/09/25 04:02:38 tbox Exp $ + +$TTL 300 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + NS ns +ns A 10.53.0.3 + +a A 10.0.0.1 +b A 10.0.0.2 +d A 10.0.0.4 +z A 10.0.0.26 +a.a.a.a A 10.0.0.3 +*.wild A 10.0.0.6 +insecure NS ns.insecure +ns.insecure A 10.53.0.3 +secure NS ns.secure +ns.secure A 10.53.0.3 +nsec3 NS ns.nsec3 +ns.nsec3 A 10.53.0.3 +optout NS ns.optout +ns.optout A 10.53.0.3 +child NS ns2.example. +insecure.empty NS ns.insecure.empty +ns.insecure.empty A 10.53.0.3 +foo.*.empty-wild NS ns diff --git a/bin/tests/system/dnssec/ns3/named.conf b/bin/tests/system/dnssec/ns3/named.conf index ed7cb8df0e..7ae4bf6d4f 100644 --- a/bin/tests/system/dnssec/ns3/named.conf +++ b/bin/tests/system/dnssec/ns3/named.conf @@ -276,6 +276,11 @@ zone "publish-inactive.example" { update-policy local; }; +zone "future.example" { + type master; + file "future.example.db.signed"; +}; + include "siginterval.conf"; include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh index 3b2b250e7c..4dafbf4200 100644 --- a/bin/tests/system/dnssec/ns3/sign.sh +++ b/bin/tests/system/dnssec/ns3/sign.sh @@ -474,3 +474,15 @@ cat $infile $keyname.key >$zonefile $SIGNER -P -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1 sed -e 's/bogus/badds/g' < dsset-bogus.example. > dsset-badds.example. + +# +# A zone with future signatures. +# +zone=future.example +infile=future.example.db.in +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 +cp -f $kskname.key trusted-future.key diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 926dc11042..ab65200677 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -2687,5 +2687,28 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +# +# Test for +sigchase with a null set of trusted keys. +# +$DIG -p 5300 @10.53.0.3 +sigchase +trusted-key=/dev/null > dig.out.ns3.test$n 2>&1 +if grep "Invalid option: +sigchase" dig.out.ns3.test$n > /dev/null +then + echo "I:Skipping 'dig +sigchase' tests" + n=`expr $n + 1` +else + echo "I:checking that 'dig +sigchase' doesn't loop with future inception ($n)" + ret=0 + $DIG -p 5300 @10.53.0.3 dnskey future.example +sigchase \ + +trusted-key=ns3/trusted-future.key > dig.out.ns3.test$n & + pid=$! + sleep 1 + kill -9 $pid 2> /dev/null + wait $pid + grep ";; No DNSKEY is valid to check the RRSIG of the RRset: FAILED" dig.out.ns3.test$n > /dev/null || ret=1 + if [ $ret != 0 ]; then echo "I:failed"; fi + status=`expr $status + $ret` + n=`expr $n + 1` +fi + echo "I:exit status: $status" exit $status