diff --git a/doc/operation.rst b/doc/operation.rst index 2202b42ce70bb65182e807b476b5c9818aa99748..57478612c482bcc57e39aaa3a3bc8621b34712cd 100644 --- a/doc/operation.rst +++ b/doc/operation.rst @@ -757,9 +757,10 @@ For the ZSK side (i.e. the operator of the DNS server), the pre-requisites are: For the KSK side (i.e. the operator of the KSK signer), the pre-requisites are: -- Knot configuration equal to the ZSK side (at least relevant parts of corresponding - :ref:`policy <Policy section>`, :ref:`zone <Zone section>`, and :ref:`template <Template section>` - sections must be identical) +- a properly configured :ref:`DNSSEC policy <Policy section>` +- :ref:`manual <policy_manual>` set to `on` +- :ref:`offline-ksk <policy_offline-ksk>` set to `on` +- :ref:`dnskey-ttl <policy_dnskey-ttl>` equal to ZSK side - a KASP DB with the KSK(s) Generating and signing future ZSKs diff --git a/src/knot/dnssec/rrset-sign.c b/src/knot/dnssec/rrset-sign.c index ccaa23c37a6b265fda36411a416f40ef4c3cefa1..7476deb089a82a180915cb402aa033c031d8e408 100644 --- a/src/knot/dnssec/rrset-sign.c +++ b/src/knot/dnssec/rrset-sign.c @@ -364,6 +364,7 @@ int knot_check_signature(const knot_rrset_t *covered, const dnssec_key_t *key, dnssec_sign_ctx_t *sign_ctx, const kdnssec_ctx_t *dnssec_ctx, + knot_timediff_t refresh, bool skip_crypto) { if (knot_rrset_empty(covered) || knot_rrset_empty(rrsigs) || !key || @@ -374,9 +375,6 @@ int knot_check_signature(const knot_rrset_t *covered, knot_rdata_t *rrsig = knot_rdataset_at(&rrsigs->rrs, pos); assert(rrsig); - // consider signature invalid even if validity ends in refresh - in order to refresh it soon enough - knot_timediff_t refresh = dnssec_ctx->policy->rrsig_refresh_before + - dnssec_ctx->policy->rrsig_prerefresh; if (!(dnssec_ctx->policy->unsafe & UNSAFE_EXPIRED) && is_expired_signature(rrsig, dnssec_ctx->now, refresh)) { return DNSSEC_INVALID_SIGNATURE; diff --git a/src/knot/dnssec/rrset-sign.h b/src/knot/dnssec/rrset-sign.h index 7114cb184cd021e98ae8975ccd1a270caaeb1009..b5ef5afd518f24a0228346794c2e19677266c574 100644 --- a/src/knot/dnssec/rrset-sign.h +++ b/src/knot/dnssec/rrset-sign.h @@ -103,6 +103,7 @@ int knot_synth_rrsig(uint16_t type, const knot_rdataset_t *rrsig_rrs, * \param key Signing key. * \param sign_ctx Signing context. * \param dnssec_ctx DNSSEC context. + * \param refresh Consider RRSIG expired when gonna expire this soon. * \param skip_crypto All RRSIGs in this node have been verified, just check validity. * * \return Error code, KNOT_EOK if successful and the signature is valid. @@ -113,4 +114,5 @@ int knot_check_signature(const knot_rrset_t *covered, const dnssec_key_t *key, dnssec_sign_ctx_t *sign_ctx, const kdnssec_ctx_t *dnssec_ctx, + knot_timediff_t refresh, bool skip_crypto); diff --git a/src/knot/dnssec/zone-sign.c b/src/knot/dnssec/zone-sign.c index a945abad4e05197bc4c770a14605805c8147f42d..781814c8d8dd39109e11e3a67bb245f34b3a0841 100644 --- a/src/knot/dnssec/zone-sign.c +++ b/src/knot/dnssec/zone-sign.c @@ -98,6 +98,7 @@ static bool apex_dnssec_changed(zone_update_t *update) * \param ctx Signing context. * \param policy DNSSEC policy. * \param skip_crypto All RRSIGs in this node have been verified, just check validity. + * \param refresh Consider RRSIG expired when gonna expire this soon. * \param found_invalid Out: some matching but expired%invalid RRSIG found. * \param at Out: RRSIG position. * @@ -108,6 +109,7 @@ static bool valid_signature_exists(const knot_rrset_t *covered, const dnssec_key_t *key, dnssec_sign_ctx_t *ctx, const kdnssec_ctx_t *dnssec_ctx, + knot_timediff_t refresh, bool skip_crypto, int *found_invalid, uint16_t *at) @@ -134,7 +136,7 @@ static bool valid_signature_exists(const knot_rrset_t *covered, } int ret = knot_check_signature(covered, rrsigs, i, key, ctx, - dnssec_ctx, skip_crypto); + dnssec_ctx, refresh, skip_crypto); if (ret == KNOT_EOK) { if (at != NULL) { *at = i; @@ -173,9 +175,12 @@ static bool all_signatures_exist(const knot_rrset_t *covered, continue; } + knot_timediff_t refresh = sign_ctx->dnssec_ctx->policy->rrsig_refresh_before + + sign_ctx->dnssec_ctx->policy->rrsig_prerefresh; if (!valid_signature_exists(covered, rrsigs, key->key, sign_ctx->sign_ctxs[i], - sign_ctx->dnssec_ctx, false, NULL, NULL)) { + sign_ctx->dnssec_ctx, refresh, + false, NULL, NULL)) { return false; } } @@ -271,8 +276,10 @@ static int add_missing_rrsigs(const knot_rrset_t *covered, } uint16_t valid_at; + knot_timediff_t refresh = sign_ctx->dnssec_ctx->policy->rrsig_refresh_before + + sign_ctx->dnssec_ctx->policy->rrsig_prerefresh; if (valid_signature_exists(covered, rrsigs, key->key, sign_ctx->sign_ctxs[i], - sign_ctx->dnssec_ctx, skip_crypto, NULL, &valid_at)) { + sign_ctx->dnssec_ctx, refresh, skip_crypto, NULL, &valid_at)) { knot_rdata_t *valid_rr = knot_rdataset_at(&rrsigs->rrs, valid_at); result = knot_rdataset_remove(&to_remove.rrs, valid_rr, NULL); note_earliest_expiration(valid_rr, expires_at); @@ -341,7 +348,7 @@ int knot_validate_rrsigs(const knot_rrset_t *covered, uint16_t valid_at; if (valid_signature_exists(covered, rrsigs, key->key, sign_ctx->sign_ctxs[i], - sign_ctx->dnssec_ctx, skip_crypto, &ret, &valid_at)) { + sign_ctx->dnssec_ctx, 0, skip_crypto, &ret, &valid_at)) { valid_exists = true; } } diff --git a/tests-extra/tests/dnssec/offline_ksk/test.py b/tests-extra/tests/dnssec/offline_ksk/test.py index 5335334b5a39117875739ea94188f324d0da07ca..07813738a9c3273dde028ff6db70fe127ef463fa 100644 --- a/tests-extra/tests/dnssec/offline_ksk/test.py +++ b/tests-extra/tests/dnssec/offline_ksk/test.py @@ -109,6 +109,7 @@ ZONE = "example.com." FUTURE = 55 TICK = 5 STARTUP = 10 +NONSENSE = 4396 zone = t.zone(ZONE) t.link(zone, knot) @@ -117,13 +118,13 @@ knot.zonefile_sync = 24 * 60 * 60 knot.dnssec(zone).enable = True knot.dnssec(zone).manual = True +knot.dnssec(zone).offline_ksk = True knot.dnssec(zone).alg = "ECDSAP384SHA384" knot.dnssec(zone).dnskey_ttl = 2 knot.dnssec(zone).zone_max_ttl = 3 knot.dnssec(zone).zsk_lifetime = STARTUP + 6 * TICK # see ksk1 lifetime -knot.dnssec(zone).ksk_lifetime = 300 # this can be possibly left also infinity +knot.dnssec(zone).ksk_lifetime = NONSENSE knot.dnssec(zone).propagation_delay = TICK - 2 -knot.dnssec(zone).offline_ksk = "on" knot.dnssec(zone).cds_publish = "rollover" knot.dnssec(zone).rrsig_lifetime = 15 knot.dnssec(zone).rrsig_refresh = 5 @@ -134,7 +135,22 @@ knot.gen_confile() signer = t.server("knot") t.link(zone, signer) -signer.zones[ZONE].dnssec = knot.zones[ZONE].dnssec + +# mandatory options +signer.dnssec(zone).enable = True +signer.dnssec(zone).manual = True +signer.dnssec(zone).offline_ksk = True +# needed options +signer.dnssec(zone).alg = "ECDSAP384SHA384" +signer.dnssec(zone).dnskey_ttl = 2 +# options without any effect +signer.dnssec(zone).zone_max_ttl = NONSENSE +signer.dnssec(zone).ksk_lifetime = NONSENSE * 2 +signer.dnssec(zone).propagation_delay = int(NONSENSE / 10) +signer.dnssec(zone).cds_publish = random.choice(["none", "rollover"]) +signer.dnssec(zone).rrsig_lifetime = 6 +signer.dnssec(zone).rrsig_refresh = 2 +signer.dnssec(zone).rrsig_prerefresh = 1 # needed for keymgr signer.gen_confile()