diff --git a/CHANGES b/CHANGES index 68da4cf442..c847acedbf 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +3085. [func] New '-R' option in dnssec-signzone forces removal + of signatures which have not yet expired but + were generated by a key that no longer exists. + [RT #22471] + 3084. [func] A new command "rndc sync" dumps pending changes in a dynamic zone to disk; "rndc sync -clean" also removes the journal file after syncing. Also, diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 717122653a..51b5a84af1 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -29,7 +29,7 @@ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dnssec-signzone.c,v 1.271 2011/03/11 12:37:01 marka Exp $ */ +/* $Id: dnssec-signzone.c,v 1.272 2011/03/21 07:26:47 each Exp $ */ /*! \file */ @@ -172,6 +172,7 @@ static isc_boolean_t update_chain = ISC_FALSE; static isc_boolean_t set_keyttl = ISC_FALSE; static dns_ttl_t keyttl; static isc_boolean_t smartsign = ISC_FALSE; +static isc_boolean_t remove_orphans = ISC_FALSE; static isc_boolean_t output_dnssec_only = ISC_FALSE; #define INCSTAT(counter) \ @@ -316,6 +317,12 @@ issigningkey(dns_dnsseckey_t *key) { return (key->force_sign || key->hint_sign); } +static inline isc_boolean_t +ispublishedkey(dns_dnsseckey_t *key) { + return ((key->force_publish || key->hint_publish) && + !key->hint_remove); +} + static inline isc_boolean_t iszonekey(dns_dnsseckey_t *key) { return (ISC_TF(dns_name_equal(dst_key_name(key->key), gorigin) && @@ -362,6 +369,8 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { isc_result_t result; dst_key_t *pubkey = NULL, *privkey = NULL; dns_dnsseckey_t *key = NULL; + isc_stdtime_t delete; + isc_boolean_t delset; isc_rwlock_lock(&keylist_lock, isc_rwlocktype_read); key = keythatsigned_unlocked(rrsig); @@ -401,7 +410,16 @@ keythatsigned(dns_rdata_rrsig_t *rrsig) { } else { dns_dnsseckey_create(mctx, &pubkey, &key); } - key->force_publish = ISC_TRUE; + + result = dst_key_gettime(key->key, DST_TIME_DELETE, &delete); + if (result == ISC_R_SUCCESS) + delset = ISC_TRUE; + + if (delset && delete <= now) + key->force_publish = ISC_FALSE; + else + key->force_publish = ISC_TRUE; + key->force_sign = ISC_FALSE; ISC_LIST_APPEND(keylist, key, link); @@ -544,10 +562,9 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, "private dnskey not found\n", sigstr); } else if (key == NULL || future) { + keep = (!expired && !remove_orphans); vbprintf(2, "\trrsig by %s %s - dnskey not found\n", - expired ? "retained" : "dropped", sigstr); - if (!expired) - keep = ISC_TRUE; + keep ? "retained" : "dropped", sigstr); } else if (issigningkey(key)) { if (!expired && rrsig.originalttl == set->ttl && setverifies(name, set, key->key, &sigrdata)) { @@ -563,6 +580,9 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, wassignedby[key->index] = ISC_TRUE; resign = ISC_TRUE; } + } else if (!ispublishedkey(key) && remove_orphans) { + vbprintf(2, "\trrsig by %s dropped - dnskey removed\n", + sigstr); } else if (iszonekey(key)) { if (!expired && rrsig.originalttl == set->ttl && setverifies(name, set, key->key, &sigrdata)) { @@ -639,7 +659,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, key != NULL; key = ISC_LIST_NEXT(key, link)) { - if (nowsignedby[key->index]) + if (nowsignedby[key->index] && !ispublishedkey(key)) continue; if (!issigningkey(key)) @@ -3457,7 +3477,7 @@ main(int argc, char *argv[]) { isc_boolean_t set_iter = ISC_FALSE; #define CMDLINE_FLAGS \ - "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:pPr:s:ST:tuUv:X:xz" + "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:l:m:n:N:o:O:PpRr:s:ST:tuUv:X:xz" /* * Process memory debugging argument first. @@ -3647,6 +3667,10 @@ main(int argc, char *argv[]) { pseudorandom = ISC_TRUE; break; + case 'R': + remove_orphans = ISC_TRUE; + break; + case 'r': setup_entropy(mctx, isc_commandline_argument, &ectx); break; diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook index dcf5c617fd..342c498651 100644 --- a/bin/dnssec/dnssec-signzone.docbook +++ b/bin/dnssec/dnssec-signzone.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + June 05, 2009 @@ -76,8 +76,9 @@ - + + @@ -465,6 +466,24 @@ + + -R + + + Remove signatures from keys that no longer exist. + + + Normally, when a previously-signed zone is passed as input + to the signer, and a DNSKEY record has been removed and + replaced with a new one, signatures from the old key + that are still within their validity period are retained. + This allows the zone to continue to validate with cached + copies of the old DNSKEY RRset. The forces + dnssec-signzone to remove all orphaned + signatures. + + + -r randomdev diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 5ef40d9e04..0e2e520f70 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -15,11 +15,13 @@ # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -# $Id: tests.sh,v 1.84 2011/03/21 03:30:48 marka Exp $ +# $Id: tests.sh,v 1.85 2011/03/21 07:26:47 each Exp $ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh +RANDFILE=random.data + status=0 n=1 @@ -930,12 +932,11 @@ status=`expr $status + $ret` echo "I:checking that we can sign a zone with out-of-zone records ($n)" ret=0 +zone=example +key1=`$KEYGEN -K signer -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone` +key2=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone` ( cd signer -RANDFILE=../random.data -zone=example -key1=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone` -key2=`$KEYGEN -q -r $RANDFILE -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone` cat example.db.in $key1.key $key2.key > example.db $SIGNER -o example -f example.db example.db > /dev/null 2>&1 ) || ret=1 @@ -945,12 +946,11 @@ status=`expr $status + $ret` echo "I:checking that we can sign a zone (NSEC3) with out-of-zone records ($n)" ret=0 +zone=example +key1=`$KEYGEN -K signer -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone` +key2=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone` ( cd signer -RANDFILE=../random.data -zone=example -key1=`$KEYGEN -q -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone` -key2=`$KEYGEN -q -r $RANDFILE -f KSK -a NSEC3RSASHA1 -b 1024 -n zone $zone` cat example.db.in $key1.key $key2.key > example.db $SIGNER -3 - -H 10 -o example -f example.db example.db > /dev/null 2>&1 awk '/^IQF9LQTLK/ { @@ -969,12 +969,11 @@ status=`expr $status + $ret` echo "I:checking that dnsssec-signzone updates originalttl on ttl changes ($n)" ret=0 +zone=example +key1=`$KEYGEN -K signer -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone` +key2=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a RSASHA1 -b 1024 -n zone $zone` ( cd signer -RANDFILE=../random.data -zone=example -key1=`$KEYGEN -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone` -key2=`$KEYGEN -q -r $RANDFILE -f KSK -a RSASHA1 -b 1024 -n zone $zone` cat example.db.in $key1.key $key2.key > example.db $SIGNER -o example -f example.db.before example.db > /dev/null 2>&1 sed 's/60.IN.SOA./50 IN SOA /' example.db.before > example.db.changed @@ -985,6 +984,42 @@ n=`expr $n + 1` if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:checking dnssec-signzone keeps valid signatures from removed keys" +ret=0 +zone=example +key1=`$KEYGEN -K signer -q -r $RANDFILE -f KSK -a RSASHA1 -b 1024 -n zone $zone` +key2=`$KEYGEN -K signer -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone` +keyid2=`echo $key2 | sed 's/^Kexample.+005+0*//'` +key3=`$KEYGEN -K signer -q -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone` +keyid3=`echo $key3 | sed 's/^Kexample.+005+0*//'` +( +cd signer +cat example.db.in $key1.key $key2.key > example.db +$SIGNER -D -o example example.db > /dev/null 2>&1 + +# now switch out key2 for key3 and resign the zone +cat example.db.in $key1.key $key3.key > example.db +echo '$INCLUDE "example.db.signed"' >> example.db +$SIGNER -D -o example example.db > /dev/null 2>&1 +) || ret=1 +grep " $keyid2 " signer/example.db.signed > /dev/null 2>&1 || ret=1 +grep " $keyid3 " signer/example.db.signed > /dev/null 2>&1 || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +echo "I:checking dnssec-signzone -R purges signatures from removed keys" +ret=0 +( +cd signer +$SIGNER -RD -o example example.db > /dev/null 2>&1 +) || ret=1 +grep " $keyid2 " signer/example.db.signed > /dev/null 2>&1 && ret=1 +grep " $keyid3 " signer/example.db.signed > /dev/null 2>&1 || ret=1 +n=`expr $n + 1` +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + echo "I:checking validated data are not cached longer than originalttl ($n)" ret=0 $DIG $DIGOPTS +ttl +noauth a.ttlpatch.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1