diff --git a/CHANGES b/CHANGES index c3cd92603c..bced985a9c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +3686. [func] "dnssec-signzone -Q" drops signatures from keys + that are still published but no longer active. + [RT #34990] + 3685. [bug] "rndc refresh" didn't work correctly with slave zones using inline-signing. [RT #35105] diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 5a2e25417f..3826c07a98 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -175,7 +175,8 @@ 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 remove_orphansigs = ISC_FALSE; +static isc_boolean_t remove_inactkeysigs = ISC_FALSE; static isc_boolean_t output_dnssec_only = ISC_FALSE; static isc_boolean_t output_stdout = ISC_FALSE; @@ -554,9 +555,14 @@ 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); + keep = (!expired && !remove_orphansigs); vbprintf(2, "\trrsig by %s %s - dnskey not found\n", keep ? "retained" : "dropped", sigstr); + } else if (!dns_dnssec_keyactive(key->key, now) && + remove_inactkeysigs) { + keep = ISC_FALSE; + vbprintf(2, "\trrsig by %s dropped - key inactive\n", + sigstr); } else if (issigningkey(key)) { wassignedby[key->index] = ISC_TRUE; @@ -571,7 +577,7 @@ signset(dns_diff_t *del, dns_diff_t *add, dns_dbnode_t *node, dns_name_t *name, "ttl change" : "failed to verify"); resign = ISC_TRUE; } - } else if (!ispublishedkey(key) && remove_orphans) { + } else if (!ispublishedkey(key) && remove_orphansigs) { vbprintf(2, "\trrsig by %s dropped - dnskey removed\n", sigstr); } else if (iszonekey(key)) { @@ -2949,6 +2955,9 @@ usage(void) { fprintf(stderr, "use pseudorandom data (faster but less secure)\n"); fprintf(stderr, "\t-P:\t"); fprintf(stderr, "disable post-sign verification\n"); + fprintf(stderr, "\t-Q:\t"); + fprintf(stderr, "remove signatures from keys that are no " + "longer active\n"); fprintf(stderr, "\t-R:\t"); fprintf(stderr, "remove signatures from keys that no longer exist\n"); fprintf(stderr, "\t-T TTL:\tTTL for newly added DNSKEYs\n"); @@ -3049,11 +3058,12 @@ main(int argc, char *argv[]) { isc_boolean_t make_keyset = ISC_FALSE; isc_boolean_t set_salt = ISC_FALSE; isc_boolean_t set_optout = ISC_FALSE; - isc_boolean_t set_iter = ISC_FALSE; + isc_boolean_t set_iter = ISC_FALSE; isc_boolean_t nonsecify = ISC_FALSE; + /* Unused letters: Bb G J M q Yy (and F is reserved). */ #define CMDLINE_FLAGS \ - "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpRr:s:ST:tuUv:X:xzZ:" + "3:AaCc:Dd:E:e:f:FghH:i:I:j:K:k:L:l:m:n:N:o:O:PpQRr:s:ST:tuUv:X:xzZ:" /* * Process memory debugging argument first. @@ -3256,8 +3266,12 @@ main(int argc, char *argv[]) { pseudorandom = ISC_TRUE; break; + case 'Q': + remove_inactkeysigs = ISC_TRUE; + break; + case 'R': - remove_orphans = ISC_TRUE; + remove_orphansigs = ISC_TRUE; break; case 'r': @@ -3343,8 +3357,7 @@ main(int argc, char *argv[]) { result = dst_lib_init2(mctx, ectx, engine, eflags); if (result != ISC_R_SUCCESS) fatal("could not initialize dst: %s", - isc_result_totext(result)); - + isc_result_totext(result)); isc_stdtime_get(&now); if (startstr != NULL) { diff --git a/bin/dnssec/dnssec-signzone.docbook b/bin/dnssec/dnssec-signzone.docbook index 3769968549..a1adafd042 100644 --- a/bin/dnssec/dnssec-signzone.docbook +++ b/bin/dnssec/dnssec-signzone.docbook @@ -490,10 +490,10 @@ - -R + -Q - Remove signatures from keys that no longer exist. + Remove signatures from keys that are no longer active. Normally, when a previously-signed zone is passed as input @@ -501,9 +501,26 @@ 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. + copies of the old DNSKEY RRset. The + forces dnssec-signzone to remove + signatures from keys that are no longer active. This + enables ZSK rollover using the procedure described in + RFC 4641, section 4.2.1.1 ("Pre-Publish Key Rollover"). + + + + + -R + + + Remove signatures from keys that are no longer published. + + + This option is similar to , except it + forces dnssec-signzone to signatures from + keys that are no longer published. This enables ZSK rollover + using the procedure described in RFC 4641, section 4.2.1.2 + ("Double Signature Zone Signing Key Rollover"). @@ -766,7 +783,7 @@ db.example.com.signed dnssec-keygen8 , BIND 9 Administrator Reference Manual, - RFC 4033. + RFC 4033, RFC 4641. diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 2553ad8bad..0336ea98d7 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -1366,6 +1366,36 @@ 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 inactive keys ($n)" +ret=0 +zone=example +( +cd signer +cp -f example.db.in example.db +$SIGNER -SD -o example example.db > /dev/null 2>&1 +echo '$INCLUDE "example.db.signed"' >> example.db +# now retire key2 and resign the zone +$SETTIME -I now $key2 > /dev/null 2>&1 +$SIGNER -SD -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 inactive keys ($n)" +ret=0 +( +cd signer +$SIGNER -SDQ -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 retains unexpired signatures ($n)" ret=0 ( diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index cf9740406a..2a4ab4f6cf 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -609,8 +609,8 @@ dns_dnssec_verify(dns_name_t *name, dns_rdataset_t *set, dst_key_t *key, return (result); } -static isc_boolean_t -key_active(dst_key_t *key, isc_stdtime_t now) { +isc_boolean_t +dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now) { isc_result_t result; isc_stdtime_t publish, active, revoke, inactive, delete; isc_boolean_t pubset = ISC_FALSE, actset = ISC_FALSE; @@ -764,7 +764,7 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, /* * If a key is marked inactive, skip it */ - if (!key_active(keys[count], now)) { + if (!dns_dnssec_keyactive(keys[count], now)) { dst_key_setinactive(pubkey, ISC_TRUE); dst_key_free(&keys[count]); keys[count] = pubkey; diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h index e443f91b63..0625e89c1e 100644 --- a/lib/dns/include/dns/dnssec.h +++ b/lib/dns/include/dns/dnssec.h @@ -174,6 +174,7 @@ dns_dnssec_findzonekeys(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node, dns_name_t *name, isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys, unsigned int *nkeys); + isc_result_t dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node, dns_name_t *name, @@ -186,6 +187,20 @@ dns_dnssec_findzonekeys2(dns_db_t *db, dns_dbversion_t *ver, */ /*@}*/ +isc_boolean_t +dns_dnssec_keyactive(dst_key_t *key, isc_stdtime_t now); +/*%< + * + * Returns ISC_TRUE if 'key' is active as of the time specified + * in 'now' (i.e., if the activation date has passed, inactivation or + * deletion date has not yet been reached, and the key is not revoked + * -- or if it is a legacy key without metadata). Otherwise returns + * ISC_FALSE. + * + * Requires: + *\li 'key' is a valid key + */ + isc_result_t dns_dnssec_signmessage(dns_message_t *msg, dst_key_t *key); /*%< diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index 4d6f0c8ff8..ede70a5ee2 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -214,6 +214,7 @@ dns_dns64_unlink dns_dnssec_findmatchingkeys dns_dnssec_findzonekeys dns_dnssec_findzonekeys2 +dns_dnssec_keyactive dns_dnssec_keyfromrdata dns_dnssec_keylistfromrdataset dns_dnssec_selfsigns