From 104eabdc2e9148075f2bcf41faa6c75e54980ee2 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 31 Jan 2024 16:52:32 +0100 Subject: [PATCH 1/6] Add signatures-jitter option Add an option to speficy signatures jitter. (cherry picked from commit 2a4daaedca0f5e24d362acf1e12c1710489e9a86) --- bin/named/config.c | 1 + bin/tests/system/checkconf/good-kasp.conf | 1 + bin/tests/system/checkconf/good.conf | 1 + doc/arm/reference.rst | 10 +++++++++ doc/misc/dnssec-policy.default.conf | 1 + doc/misc/options | 1 + lib/dns/include/dns/kasp.h | 26 +++++++++++++++++++++++ lib/dns/kasp.c | 16 ++++++++++++++ lib/isccfg/kaspconf.c | 6 +++++- lib/isccfg/namedconf.c | 1 + 10 files changed, 63 insertions(+), 1 deletion(-) diff --git a/bin/named/config.c b/bin/named/config.c index f95e4336ed..6bf0b3ca81 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -309,6 +309,7 @@ dnssec-policy \"default\" {\n\ publish-safety " DNS_KASP_PUBLISH_SAFETY "; \n\ retire-safety " DNS_KASP_RETIRE_SAFETY "; \n\ purge-keys " DNS_KASP_PURGE_KEYS "; \n\ + signatures-jitter " DNS_KASP_SIG_JITTER "; \n\ signatures-refresh " DNS_KASP_SIG_REFRESH "; \n\ signatures-validity " DNS_KASP_SIG_VALIDITY "; \n\ signatures-validity-dnskey " DNS_KASP_SIG_VALIDITY_DNSKEY "; \n\ diff --git a/bin/tests/system/checkconf/good-kasp.conf b/bin/tests/system/checkconf/good-kasp.conf index 17309e5ea6..c7dd9efbd8 100644 --- a/bin/tests/system/checkconf/good-kasp.conf +++ b/bin/tests/system/checkconf/good-kasp.conf @@ -29,6 +29,7 @@ dnssec-policy "test" { parent-propagation-delay PT1H; publish-safety PT3600S; retire-safety PT3600S; + signatures-jitter PT12H; signatures-refresh P3D; signatures-validity P2W; signatures-validity-dnskey P14D; diff --git a/bin/tests/system/checkconf/good.conf b/bin/tests/system/checkconf/good.conf index f8d04089f0..7e0f87901c 100644 --- a/bin/tests/system/checkconf/good.conf +++ b/bin/tests/system/checkconf/good.conf @@ -30,6 +30,7 @@ dnssec-policy "test" { publish-safety PT3600S; purge-keys P90D; retire-safety PT3600S; + signatures-jitter PT12H; signatures-refresh P3D; signatures-validity P2W; signatures-validity-dnskey P14D; diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 3dab21be42..214f64edfe 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -6509,6 +6509,16 @@ The following options can be specified in a :any:`dnssec-policy` statement: unforeseen events. This increases the time a key remains published after it is no longer active. The default is ``PT1H`` (1 hour). +.. namedconf:statement:: signatures-jitter + :tags: dnssec + :short: Specifies a range for signatures expirations. + + To prevent all signatures from expiring at the same moment, BIND 9 may + vary the validity interval of individual signatures. The validity of a + newly generated signatures is in range between :any:`signatures-validity` + (maximum) and :any:`signatures-validity` minus :any:`signatures-jitter` + (minimum). The default jitter is 12 hours. + .. namedconf:statement:: signatures-refresh :tags: dnssec :short: Specifies how frequently an RRSIG record is refreshed. diff --git a/doc/misc/dnssec-policy.default.conf b/doc/misc/dnssec-policy.default.conf index 00b8a14656..afe570ad70 100644 --- a/doc/misc/dnssec-policy.default.conf +++ b/doc/misc/dnssec-policy.default.conf @@ -24,6 +24,7 @@ dnssec-policy "default" { purge-keys P90D; // Signature timings + signatures-jitter 12h; signatures-refresh 5d; signatures-validity 14d; signatures-validity-dnskey 14d; diff --git a/doc/misc/options b/doc/misc/options index da2847708f..56cbf323b6 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -21,6 +21,7 @@ dnssec-policy { publish-safety ; purge-keys ; retire-safety ; + signatures-jitter ; signatures-refresh ; signatures-validity ; signatures-validity-dnskey ; diff --git a/lib/dns/include/dns/kasp.h b/lib/dns/include/dns/kasp.h index 4f560a037f..3dfd922720 100644 --- a/lib/dns/include/dns/kasp.h +++ b/lib/dns/include/dns/kasp.h @@ -75,6 +75,7 @@ struct dns_kasp { ISC_LINK(struct dns_kasp) link; /* Configuration: signatures */ + uint32_t signatures_jitter; uint32_t signatures_refresh; uint32_t signatures_validity; uint32_t signatures_validity_dnskey; @@ -105,6 +106,7 @@ struct dns_kasp { #define DNS_KASP_VALID(kasp) ISC_MAGIC_VALID(kasp, DNS_KASP_MAGIC) /* Defaults */ +#define DNS_KASP_SIG_JITTER "PT12H" #define DNS_KASP_SIG_REFRESH "P5D" #define DNS_KASP_SIG_VALIDITY "P14D" #define DNS_KASP_SIG_VALIDITY_DNSKEY "P14D" @@ -233,6 +235,30 @@ dns_kasp_signdelay(dns_kasp_t *kasp); *\li signature refresh interval. */ +uint32_t +dns_kasp_sigjitter(dns_kasp_t *kasp); +/*%< + * Get signature jitter value. + * + * Requires: + * + *\li 'kasp' is a valid, frozen kasp. + * + * Returns: + * + *\li signature jitter value. + */ + +void +dns_kasp_setsigjitter(dns_kasp_t *kasp, uint32_t value); +/*%< + * Set signature jitter value. + * + * Requires: + * + *\li 'kasp' is a valid, thawed kasp. + */ + uint32_t dns_kasp_sigrefresh(dns_kasp_t *kasp); /*%< diff --git a/lib/dns/kasp.c b/lib/dns/kasp.c index d53abfb64c..f90f76065c 100644 --- a/lib/dns/kasp.c +++ b/lib/dns/kasp.c @@ -127,6 +127,22 @@ dns_kasp_signdelay(dns_kasp_t *kasp) { return (kasp->signatures_validity - kasp->signatures_refresh); } +uint32_t +dns_kasp_sigjitter(dns_kasp_t *kasp) { + REQUIRE(DNS_KASP_VALID(kasp)); + REQUIRE(kasp->frozen); + + return (kasp->signatures_jitter); +} + +void +dns_kasp_setsigjitter(dns_kasp_t *kasp, uint32_t value) { + REQUIRE(DNS_KASP_VALID(kasp)); + REQUIRE(!kasp->frozen); + + kasp->signatures_jitter = value; +} + uint32_t dns_kasp_sigrefresh(dns_kasp_t *kasp) { REQUIRE(DNS_KASP_VALID(kasp)); diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index ba36b0d8ee..db0a382324 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -312,7 +312,7 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, const char *kaspname = NULL; dns_kasp_t *kasp = NULL; size_t i = 0; - uint32_t sigrefresh = 0, sigvalidity = 0; + uint32_t sigjitter = 0, sigrefresh = 0, sigvalidity = 0; uint32_t dnskeyttl = 0, dsttl = 0, maxttl = 0; uint32_t publishsafety = 0, retiresafety = 0; uint32_t zonepropdelay = 0, parentpropdelay = 0; @@ -360,6 +360,10 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, maps[i] = NULL; /* Configuration: Signatures */ + sigjitter = get_duration(maps, "signatures-jitter", + DNS_KASP_SIG_JITTER); + dns_kasp_setsigjitter(kasp, sigjitter); + sigrefresh = get_duration(maps, "signatures-refresh", DNS_KASP_SIG_REFRESH); dns_kasp_setsigrefresh(kasp, sigrefresh); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index d5b28baad2..7bfd8f9bde 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -2211,6 +2211,7 @@ static cfg_clausedef_t dnssecpolicy_clauses[] = { { "publish-safety", &cfg_type_duration, 0 }, { "purge-keys", &cfg_type_duration, 0 }, { "retire-safety", &cfg_type_duration, 0 }, + { "signatures-jitter", &cfg_type_duration, 0 }, { "signatures-refresh", &cfg_type_duration, 0 }, { "signatures-validity", &cfg_type_duration, 0 }, { "signatures-validity-dnskey", &cfg_type_duration, 0 }, From a1e61f179ece1d54829c8118e2c1be0667be4d87 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 31 Jan 2024 17:31:16 +0100 Subject: [PATCH 2/6] Refactor code that calculates signature validity There are three code blocks that are (almost) similar, refactor it to one function. (cherry picked from commit 0438d3655bca9d6aeea41746a01d82e5252eba64) --- lib/dns/zone.c | 135 ++++++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 85 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 4c5423815b..4b4949d434 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -7184,6 +7184,49 @@ failure: return (result); } +static void +calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, + isc_stdtime_t *inception, isc_stdtime_t *soaexpire, + isc_stdtime_t *expire, isc_stdtime_t *fullexpire) { + REQUIRE(inception != NULL); + REQUIRE(soaexpire != NULL); + /* expire and fullexpire are optional */ + + isc_stdtime_t sigvalidityinterval = + dns_zone_getsigvalidityinterval(zone); + isc_stdtime_t expiryinterval = dns_zone_getsigresigninginterval(zone); + isc_stdtime_t normaljitter = 0, fulljitter = 0; + + *inception = now - 3600; /* Allow for clock skew. */ + *soaexpire = now + sigvalidityinterval; + if (expiryinterval > sigvalidityinterval) { + expiryinterval = sigvalidityinterval; + } else { + expiryinterval = sigvalidityinterval - expiryinterval; + } + + /* + * Spread out signatures over time if they happen to be + * clumped. We don't do this for each add_sigs() call as + * we still want some clustering to occur. In normal operations + * the records should be re-signed as they fall due and they should + * already be spread out. However if the server is off for a + * period we need to ensure that the clusters don't become + * synchronised by using the full jitter range. + */ + if (sigvalidityinterval >= 3600U) { + if (sigvalidityinterval > 7200U) { + normaljitter = isc_random_uniform(3600); + fulljitter = isc_random_uniform(expiryinterval); + } else { + normaljitter = fulljitter = isc_random_uniform(1200); + } + } + + SET_IF_NOT_NULL(expire, *soaexpire - normaljitter - 1); + SET_IF_NOT_NULL(fullexpire, *soaexpire - fulljitter - 1); +} + static void zone_resigninc(dns_zone_t *zone) { const char *me = "zone_resigninc"; @@ -7199,7 +7242,6 @@ zone_resigninc(dns_zone_t *zone) { bool check_ksk, keyset_kskonly = false; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop; - uint32_t sigvalidityinterval, expiryinterval; unsigned int i; unsigned int nkeys = 0; unsigned int resign; @@ -7250,38 +7292,9 @@ zone_resigninc(dns_zone_t *zone) { goto failure; } - sigvalidityinterval = dns_zone_getsigvalidityinterval(zone); - inception = now - 3600; /* Allow for clock skew. */ - soaexpire = now + sigvalidityinterval; - expiryinterval = dns_zone_getsigresigninginterval(zone); - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } + calculate_rrsig_validity(zone, now, &inception, &soaexpire, &expire, + &fullexpire); - /* - * Spread out signatures over time if they happen to be - * clumped. We don't do this for each add_sigs() call as - * we still want some clustering to occur. In normal operations - * the records should be re-signed as they fall due and they should - * already be spread out. However if the server is off for a - * period we need to ensure that the clusters don't become - * synchronised by using the full jitter range. - */ - if (sigvalidityinterval >= 3600U) { - uint32_t normaljitter, fulljitter; - if (sigvalidityinterval > 7200U) { - normaljitter = isc_random_uniform(3600); - fulljitter = isc_random_uniform(expiryinterval); - } else { - normaljitter = fulljitter = isc_random_uniform(1200); - } - expire = soaexpire - normaljitter - 1; - fullexpire = soaexpire - fulljitter - 1; - } else { - expire = fullexpire = soaexpire - 1; - } stop = now + 5; check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); @@ -8376,7 +8389,6 @@ zone_nsec3chain(dns_zone_t *zone) { bool first; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire; - uint32_t jitter, sigvalidityinterval, expiryinterval; unsigned int i; unsigned int nkeys = 0; uint32_t nodes; @@ -8445,31 +8457,8 @@ zone_nsec3chain(dns_zone_t *zone) { goto failure; } - sigvalidityinterval = dns_zone_getsigvalidityinterval(zone); - inception = now - 3600; /* Allow for clock skew. */ - soaexpire = now + sigvalidityinterval; - expiryinterval = dns_zone_getsigresigninginterval(zone); - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } - - /* - * Spread out signatures over time if they happen to be - * clumped. We don't do this for each add_sigs() call as - * we still want some clustering to occur. - */ - if (sigvalidityinterval >= 3600U) { - if (sigvalidityinterval > 7200U) { - jitter = isc_random_uniform(expiryinterval); - } else { - jitter = isc_random_uniform(1200); - } - expire = soaexpire - jitter - 1; - } else { - expire = soaexpire - 1; - } + calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL, + &expire); check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY); @@ -9482,7 +9471,6 @@ zone_sign(dns_zone_t *zone) { bool first; isc_result_t result; isc_stdtime_t now, inception, soaexpire, expire; - uint32_t jitter, sigvalidityinterval, expiryinterval; unsigned int i, j; unsigned int nkeys = 0; uint32_t nodes; @@ -9534,32 +9522,8 @@ zone_sign(dns_zone_t *zone) { goto cleanup; } - kasp = dns_zone_getkasp(zone); - sigvalidityinterval = dns_zone_getsigvalidityinterval(zone); - inception = now - 3600; /* Allow for clock skew. */ - soaexpire = now + sigvalidityinterval; - expiryinterval = dns_zone_getsigresigninginterval(zone); - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } - - /* - * Spread out signatures over time if they happen to be - * clumped. We don't do this for each add_sigs() call as - * we still want some clustering to occur. - */ - if (sigvalidityinterval >= 3600U) { - if (sigvalidityinterval > 7200U) { - jitter = isc_random_uniform(expiryinterval); - } else { - jitter = isc_random_uniform(1200); - } - expire = soaexpire - jitter - 1; - } else { - expire = soaexpire - 1; - } + calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL, + &expire); /* * We keep pulling nodes off each iterator in turn until @@ -9575,6 +9539,7 @@ zone_sign(dns_zone_t *zone) { check_ksk = false; keyset_kskonly = true; use_kasp = true; + kasp = zone->kasp; } else { check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK); keyset_kskonly = DNS_ZONE_OPTION(zone, From 2d8ed9d5d2584e236910d59ba7c74672c5c5cd4f Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 1 Feb 2024 09:34:33 +0100 Subject: [PATCH 3/6] Implement signature jitter When calculating the RRSIG validity, jitter is now derived from the config option rather than from the refresh value. (cherry picked from commit 67f403a42371f943751a28411ded61949ca83fdf) --- lib/dns/include/dns/kasp.h | 1 + lib/dns/update.c | 33 +++++++++++++++++---------------- lib/dns/zone.c | 31 +++++++++++++++---------------- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/lib/dns/include/dns/kasp.h b/lib/dns/include/dns/kasp.h index 3dfd922720..76ba52ec9c 100644 --- a/lib/dns/include/dns/kasp.h +++ b/lib/dns/include/dns/kasp.h @@ -106,6 +106,7 @@ struct dns_kasp { #define DNS_KASP_VALID(kasp) ISC_MAGIC_VALID(kasp, DNS_KASP_MAGIC) /* Defaults */ +#define DEFAULT_JITTER (12 * 3600) #define DNS_KASP_SIG_JITTER "PT12H" #define DNS_KASP_SIG_REFRESH "P5D" #define DNS_KASP_SIG_VALIDITY "P14D" diff --git a/lib/dns/update.c b/lib/dns/update.c index a94d35276e..d3c449e83d 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1492,23 +1492,25 @@ struct dns_update_state { }; static uint32_t -dns__jitter_expire(dns_zone_t *zone, uint32_t sigvalidityinterval) { +dns__jitter_expire(dns_zone_t *zone) { /* Spread out signatures over time */ - if (sigvalidityinterval >= 3600U) { - uint32_t expiryinterval = - dns_zone_getsigresigninginterval(zone); + isc_stdtime_t jitter = DEFAULT_JITTER; + isc_stdtime_t sigvalidity = dns_zone_getsigvalidityinterval(zone); + dns_kasp_t *kasp = dns_zone_getkasp(zone); - if (sigvalidityinterval < 7200U) { - expiryinterval = 1200; - } else if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } - uint32_t jitter = isc_random_uniform(expiryinterval); - sigvalidityinterval -= jitter; + if (kasp != NULL) { + jitter = dns_kasp_sigjitter(kasp); + sigvalidity = dns_kasp_sigvalidity(kasp); } - return (sigvalidityinterval); + + if (sigvalidity >= 3600U) { + if (sigvalidity > 7200U) { + sigvalidity -= isc_random_uniform(jitter); + } else { + sigvalidity -= isc_random_uniform(1200); + } + } + return (sigvalidity); } isc_result_t @@ -1561,8 +1563,7 @@ dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db, isc_stdtime_get(&state->now); state->inception = state->now - 3600; /* Allow for some clock skew. */ - state->expire = state->now + - dns__jitter_expire(zone, sigvalidityinterval); + state->expire = state->now + dns__jitter_expire(zone); state->soaexpire = state->now + sigvalidityinterval; state->keyexpire = dns_zone_getkeyvalidityinterval(zone); if (state->keyexpire == 0) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 4b4949d434..1ad55e3c43 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -7192,18 +7192,17 @@ calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, REQUIRE(soaexpire != NULL); /* expire and fullexpire are optional */ - isc_stdtime_t sigvalidityinterval = - dns_zone_getsigvalidityinterval(zone); - isc_stdtime_t expiryinterval = dns_zone_getsigresigninginterval(zone); - isc_stdtime_t normaljitter = 0, fulljitter = 0; + isc_stdtime_t jitter = DEFAULT_JITTER; + isc_stdtime_t sigvalidity = dns_zone_getsigvalidityinterval(zone); + isc_stdtime_t shortjitter = 0, fulljitter = 0; + + if (zone->kasp != NULL) { + jitter = dns_kasp_sigjitter(zone->kasp); + sigvalidity = dns_kasp_sigvalidity(zone->kasp); + } *inception = now - 3600; /* Allow for clock skew. */ - *soaexpire = now + sigvalidityinterval; - if (expiryinterval > sigvalidityinterval) { - expiryinterval = sigvalidityinterval; - } else { - expiryinterval = sigvalidityinterval - expiryinterval; - } + *soaexpire = now + sigvalidity; /* * Spread out signatures over time if they happen to be @@ -7214,16 +7213,16 @@ calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, * period we need to ensure that the clusters don't become * synchronised by using the full jitter range. */ - if (sigvalidityinterval >= 3600U) { - if (sigvalidityinterval > 7200U) { - normaljitter = isc_random_uniform(3600); - fulljitter = isc_random_uniform(expiryinterval); + if (sigvalidity >= 3600U) { + if (sigvalidity > 7200U) { + shortjitter = isc_random_uniform(3600); + fulljitter = isc_random_uniform(jitter); } else { - normaljitter = fulljitter = isc_random_uniform(1200); + shortjitter = fulljitter = isc_random_uniform(1200); } } - SET_IF_NOT_NULL(expire, *soaexpire - normaljitter - 1); + SET_IF_NOT_NULL(expire, *soaexpire - shortjitter - 1); SET_IF_NOT_NULL(fullexpire, *soaexpire - fulljitter - 1); } From 74d5f8f689ce2109e3bea57d1608a4b268f7eaef Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 1 Feb 2024 09:50:40 +0100 Subject: [PATCH 4/6] Add release notes and CHANGES for #4554 Mention the new signature jitter option. (cherry picked from commit 8b7785bc237997342647c4ef47d996e9cab55b91) --- CHANGES | 2 ++ doc/notes/notes-current.rst | 3 +++ 2 files changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 73bd3de0c3..ba83424e8b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +6372. [func] Implement signature jitter for dnssec-policy. [GL #4554] + --- 9.18.26 released --- 6364. [protocol] Add RESOLVER.ARPA to the built in empty zones. diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 3c40996271..e59cc4eacb 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -22,6 +22,9 @@ New Features - None. +- A new option :any:`signatures-jitter` is added to :any:`dnssec-policy` to + spread out signature expiration times over a period of time. :gl:`#4554` + Removed Features ~~~~~~~~~~~~~~~~ From f211c05990ba50ba83c8a4ca0246a06cef08368d Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Tue, 16 Apr 2024 15:49:13 +0200 Subject: [PATCH 5/6] Add checkconf check for signatures-jitter Having a value higher than signatures-validity does not make sense and should be treated as a configuration error. (cherry picked from commit c3d8932f79907bf55580bc0ff86f38343a785914) --- .../system/checkconf/bad-kasp-jitter.conf | 27 +++++++++++++++++++ doc/arm/reference.rst | 4 ++- lib/dns/update.c | 5 ++++ lib/dns/zone.c | 5 ++++ lib/isccfg/kaspconf.c | 18 +++++++++++++ 5 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 bin/tests/system/checkconf/bad-kasp-jitter.conf diff --git a/bin/tests/system/checkconf/bad-kasp-jitter.conf b/bin/tests/system/checkconf/bad-kasp-jitter.conf new file mode 100644 index 0000000000..e358957437 --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-jitter.conf @@ -0,0 +1,27 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +/* + * The dnssec-policy jitter is more than signatures-validity, + * which is not allowed. + */ +dnssec-policy high-jitter { + signatures-jitter P8DT1S; + signatures-validity P8D; +}; + +zone "example.net" { + type primary; + file "example.db"; + dnssec-policy high-jitter; +}; diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst index 214f64edfe..cb2f5126af 100644 --- a/doc/arm/reference.rst +++ b/doc/arm/reference.rst @@ -6517,7 +6517,9 @@ The following options can be specified in a :any:`dnssec-policy` statement: vary the validity interval of individual signatures. The validity of a newly generated signatures is in range between :any:`signatures-validity` (maximum) and :any:`signatures-validity` minus :any:`signatures-jitter` - (minimum). The default jitter is 12 hours. + (minimum). The default jitter is 12 hours and the configured value must + be lower than :any:`signatures-validity` and + :any:`signatures-validity-dnskey`. .. namedconf:statement:: signatures-refresh :tags: dnssec diff --git a/lib/dns/update.c b/lib/dns/update.c index d3c449e83d..f062e8aff6 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1501,6 +1501,11 @@ dns__jitter_expire(dns_zone_t *zone) { if (kasp != NULL) { jitter = dns_kasp_sigjitter(kasp); sigvalidity = dns_kasp_sigvalidity(kasp); + INSIST(jitter <= sigvalidity); + } + + if (jitter > sigvalidity) { + jitter = sigvalidity; } if (sigvalidity >= 3600U) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 1ad55e3c43..4cbb3d316a 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -7199,6 +7199,11 @@ calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, if (zone->kasp != NULL) { jitter = dns_kasp_sigjitter(zone->kasp); sigvalidity = dns_kasp_sigvalidity(zone->kasp); + INSIST(jitter <= sigvalidity); + } + + if (jitter > sigvalidity) { + jitter = sigvalidity; } *inception = now - 3600; /* Allow for clock skew. */ diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index db0a382324..a482062a2b 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -380,6 +380,15 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, } dns_kasp_setsigvalidity_dnskey(kasp, sigvalidity); + if (sigjitter > sigvalidity) { + cfg_obj_log( + config, logctx, ISC_LOG_ERROR, + "dnssec-policy: policy '%s' signatures-jitter cannot " + "be larger than signatures-validity-dnskey", + kaspname); + result = ISC_R_FAILURE; + } + sigvalidity = get_duration(maps, "signatures-validity", DNS_KASP_SIG_VALIDITY); if (sigrefresh >= (sigvalidity * 0.9)) { @@ -392,6 +401,15 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp, } dns_kasp_setsigvalidity(kasp, sigvalidity); + if (sigjitter > sigvalidity) { + cfg_obj_log( + config, logctx, ISC_LOG_ERROR, + "dnssec-policy: policy '%s' signatures-jitter cannot " + "be larger than signatures-validity", + kaspname); + result = ISC_R_FAILURE; + } + if (result != ISC_R_SUCCESS) { goto cleanup; } From 0134b91febaa7abf5ee85fbeadd65020b35c4a04 Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 18 Apr 2024 16:02:48 +0200 Subject: [PATCH 6/6] If kasp is not used, use legacy signature jitter If the zone is signed with a different way than 'dnssec-policy', use the legacy way of jittering signatures, that is calculate jitter by taking the two values of 'sig-validity-interval' and subtracting the second value from the first value. --- lib/dns/update.c | 7 +++++++ lib/dns/zone.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/lib/dns/update.c b/lib/dns/update.c index f062e8aff6..b4d2a1258e 100644 --- a/lib/dns/update.c +++ b/lib/dns/update.c @@ -1502,6 +1502,13 @@ dns__jitter_expire(dns_zone_t *zone) { jitter = dns_kasp_sigjitter(kasp); sigvalidity = dns_kasp_sigvalidity(kasp); INSIST(jitter <= sigvalidity); + } else { + jitter = dns_zone_getsigresigninginterval(zone); + if (jitter > sigvalidity) { + jitter = sigvalidity; + } else { + jitter = sigvalidity - jitter; + } } if (jitter > sigvalidity) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 4cbb3d316a..2bf1a50bb8 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -7200,6 +7200,13 @@ calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now, jitter = dns_kasp_sigjitter(zone->kasp); sigvalidity = dns_kasp_sigvalidity(zone->kasp); INSIST(jitter <= sigvalidity); + } else { + jitter = dns_zone_getsigresigninginterval(zone); + if (jitter > sigvalidity) { + jitter = sigvalidity; + } else { + jitter = sigvalidity - jitter; + } } if (jitter > sigvalidity) {