From 29126500d2f4e5564b3ee3d2b3112fd876dbbb79 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Mon, 19 Apr 2021 16:32:54 +1000 Subject: [PATCH 1/9] Reduce nsec3 max iterations to 150 --- bin/dnssec/dnssec-signzone.c | 7 +--- bin/named/server.c | 3 +- lib/dns/include/dns/nsec3.h | 14 ++----- lib/dns/nsec3.c | 75 ++---------------------------------- lib/dns/tests/nsec3_test.c | 9 ++--- lib/ns/update.c | 9 ++--- 6 files changed, 17 insertions(+), 100 deletions(-) diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 3a88e861e3..0881ef3bda 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -3857,7 +3857,6 @@ main(int argc, char *argv[]) { warnifallksk(gdb); if (IS_NSEC3) { - unsigned int max; bool answer; hash_length = dns_nsec3_hashlength(dns_hash_sha1); @@ -3876,12 +3875,10 @@ main(int argc, char *argv[]) { "NSEC-only DNSKEY"); } - result = dns_nsec3_maxiterations(gdb, NULL, mctx, &max); - check_result(result, "dns_nsec3_maxiterations()"); - if (nsec3iter > max) { + if (nsec3iter > dns_nsec3_maxiterations()) { fatal("NSEC3 iterations too big for weakest DNSKEY " "strength. Maximum iterations allowed %u.", - max); + dns_nsec3_maxiterations()); } } else { hashlist_init(&hashlist, 0, 0); /* silence clang */ diff --git a/bin/named/server.c b/bin/named/server.c index f26f867f90..136c922384 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -14786,7 +14786,8 @@ named_server_signing(named_server_t *server, isc_lex_t *lex, return (ISC_R_BADNUMBER); } - if (hash > 0xffU || flags > 0xffU) { + if (hash > 0xffU || flags > 0xffU || + iter > dns_nsec3_maxiterations()) { return (ISC_R_RANGE); } diff --git a/lib/dns/include/dns/nsec3.h b/lib/dns/include/dns/nsec3.h index 1c12a464e9..2f178b680b 100644 --- a/lib/dns/include/dns/nsec3.h +++ b/lib/dns/include/dns/nsec3.h @@ -208,18 +208,10 @@ dns_nsec3_activex(dns_db_t *db, dns_dbversion_t *version, bool complete, * 'answer' to be non NULL. */ -isc_result_t -dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version, isc_mem_t *mctx, - unsigned int *iterationsp); +unsigned int +dns_nsec3_maxiterations(void); /*%< - * Find the maximum permissible number of iterations allowed based on - * the key strength. - * - * Requires: - * 'db' to be valid. - * 'version' to be valid or NULL. - * 'mctx' to be valid. - * 'iterationsp' to be non NULL. + * Return the maximum permissible number of NSEC3 iterations. */ bool diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index a6401e92f5..b5df23eefe 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -1878,78 +1878,9 @@ try_private: return (result); } -isc_result_t -dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version, isc_mem_t *mctx, - unsigned int *iterationsp) { - dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; - dst_key_t *key = NULL; - isc_buffer_t buffer; - isc_result_t result; - unsigned int bits, minbits = 4096; - - result = dns_db_getoriginnode(db, &node); - if (result != ISC_R_SUCCESS) { - return (result); - } - - dns_rdataset_init(&rdataset); - result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey, 0, - 0, &rdataset, NULL); - dns_db_detachnode(db, &node); - if (result == ISC_R_NOTFOUND) { - *iterationsp = 0; - return (ISC_R_SUCCESS); - } - if (result != ISC_R_SUCCESS) { - goto failure; - } - - for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&rdataset)) - { - dns_rdata_t rdata = DNS_RDATA_INIT; - dns_rdataset_current(&rdataset, &rdata); - - REQUIRE(rdata.type == dns_rdatatype_key || - rdata.type == dns_rdatatype_dnskey); - REQUIRE(rdata.length > 3); - - /* Skip unsupported algorithms when - * calculating the maximum iterations. - */ - if (!dst_algorithm_supported(rdata.data[3])) { - continue; - } - - isc_buffer_init(&buffer, rdata.data, rdata.length); - isc_buffer_add(&buffer, rdata.length); - CHECK(dst_key_fromdns(dns_db_origin(db), rdataset.rdclass, - &buffer, mctx, &key)); - bits = dst_key_size(key); - dst_key_free(&key); - if (minbits > bits) { - minbits = bits; - } - } - if (result != ISC_R_NOMORE) { - goto failure; - } - - if (minbits <= 1024) { - *iterationsp = 150; - } else if (minbits <= 2048) { - *iterationsp = 500; - } else { - *iterationsp = 2500; - } - result = ISC_R_SUCCESS; - -failure: - if (dns_rdataset_isassociated(&rdataset)) { - dns_rdataset_disassociate(&rdataset); - } - return (result); +unsigned int +dns_nsec3_maxiterations(void) { + return (150); } isc_result_t diff --git a/lib/dns/tests/nsec3_test.c b/lib/dns/tests/nsec3_test.c index a71b3c908b..a9868dd843 100644 --- a/lib/dns/tests/nsec3_test.c +++ b/lib/dns/tests/nsec3_test.c @@ -60,8 +60,7 @@ iteration_test(const char *file, unsigned int expected) { result = dns_test_loaddb(&db, dns_dbtype_zone, "test", file); assert_int_equal(result, ISC_R_SUCCESS); - result = dns_nsec3_maxiterations(db, NULL, dt_mctx, &iterations); - assert_int_equal(result, ISC_R_SUCCESS); + iterations = dns_nsec3_maxiterations(); assert_int_equal(iterations, expected); @@ -138,10 +137,10 @@ max_iterations(void **state) { UNUSED(state); iteration_test("testdata/nsec3/1024.db", 150); - iteration_test("testdata/nsec3/2048.db", 500); - iteration_test("testdata/nsec3/4096.db", 2500); + iteration_test("testdata/nsec3/2048.db", 150); + iteration_test("testdata/nsec3/4096.db", 150); iteration_test("testdata/nsec3/min-1024.db", 150); - iteration_test("testdata/nsec3/min-2048.db", 500); + iteration_test("testdata/nsec3/min-2048.db", 150); } /* check dns_nsec3param_salttotext() */ diff --git a/lib/ns/update.c b/lib/ns/update.c index 6b72b534bc..3cb9356998 100644 --- a/lib/ns/update.c +++ b/lib/ns/update.c @@ -2007,7 +2007,7 @@ check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, dns_difftuple_t *tuple; bool nseconly = false, nsec3 = false; isc_result_t result; - unsigned int iterations = 0, max; + unsigned int iterations = 0; dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */ @@ -2062,12 +2062,9 @@ check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, /* Verify NSEC3 params */ CHECK(get_iterations(db, ver, privatetype, &iterations)); - CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); - if (max != 0 && iterations > max) { + if (iterations > dns_nsec3_maxiterations()) { update_log(client, zone, ISC_LOG_ERROR, - "too many NSEC3 iterations (%u) for " - "weakest DNSKEY (%u)", - iterations, max); + "too many NSEC3 iterations (%u)", iterations); result = DNS_R_REFUSED; goto failure; } From aa26cde2aea459d682f6f609a7c902ef9a7a35eb Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 21 Apr 2021 11:57:46 +1000 Subject: [PATCH 2/9] Check dnssec-policy nsec3param iterations limit --- .../system/checkconf/bad-kasp-iterations.conf | 14 ++++++++++++++ .../system/checkconf/good-kasp-iterations.conf | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 bin/tests/system/checkconf/bad-kasp-iterations.conf create mode 100644 bin/tests/system/checkconf/good-kasp-iterations.conf diff --git a/bin/tests/system/checkconf/bad-kasp-iterations.conf b/bin/tests/system/checkconf/bad-kasp-iterations.conf new file mode 100644 index 0000000000..041ca7678e --- /dev/null +++ b/bin/tests/system/checkconf/bad-kasp-iterations.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy too-many-iterations { + nsec3param iterations 151; +}; diff --git a/bin/tests/system/checkconf/good-kasp-iterations.conf b/bin/tests/system/checkconf/good-kasp-iterations.conf new file mode 100644 index 0000000000..e197957cf5 --- /dev/null +++ b/bin/tests/system/checkconf/good-kasp-iterations.conf @@ -0,0 +1,14 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * 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 http://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +dnssec-policy max-iterations { + nsec3param iterations 150; +}; From c9f5f8a05909a47ef0f4a95ffee71a608f76a468 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 23 Apr 2021 14:23:00 +1000 Subject: [PATCH 3/9] Warn if there is excessive NSEC3 iterations --- lib/dns/zone.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 031fa4827c..24d5849f61 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -3869,13 +3869,12 @@ cleanup: static isc_result_t check_nsec3param(dns_zone_t *zone, dns_db_t *db) { + bool ok = false; dns_dbnode_t *node = NULL; - dns_rdataset_t rdataset; dns_dbversion_t *version = NULL; dns_rdata_nsec3param_t nsec3param; - bool ok = false; + dns_rdataset_t rdataset; isc_result_t result; - dns_rdata_t rdata = DNS_RDATA_INIT; bool dynamic = (zone->type == dns_zone_master) ? dns_zone_isdynamic(zone, false) : false; @@ -3906,18 +3905,21 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { goto cleanup; } - /* - * For dynamic zones we must support every algorithm so we can - * regenerate all the NSEC3 chains. - * For non-dynamic zones we only need to find a supported algorithm. - */ for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdataset_current(&rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); - dns_rdata_reset(&rdata); - INSIST(result == ISC_R_SUCCESS); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + + /* + * For dynamic zones we must support every algorithm so we + * can regenerate all the NSEC3 chains. + * For non-dynamic zones we only need to find a supported + * algorithm. + */ if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) && nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic) { @@ -3945,6 +3947,16 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { } else { ok = true; } + + /* + * Warn if the zone has excessive NSEC3 iterations. + */ + if (nsec3param.iterations > dns_nsec3_maxiterations()) { + dnssec_log(zone, ISC_LOG_WARNING, + "excessive NSEC3PARAM iterations %u > %u", + nsec3param.iterations, + dns_nsec3_maxiterations()); + } } if (result == ISC_R_NOMORE) { result = ISC_R_SUCCESS; From 3fe75d9809902be38e49a409be3e688d78a2db2b Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 23 Apr 2021 10:03:53 +1000 Subject: [PATCH 4/9] nsupdate: reject attempts to add NSEC3PARAM with excessive iterations --- bin/nsupdate/nsupdate.c | 14 ++++++++++++++ bin/tests/system/nsupdate/tests.sh | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/bin/nsupdate/nsupdate.c b/bin/nsupdate/nsupdate.c index 3b505b9694..4965a274f5 100644 --- a/bin/nsupdate/nsupdate.c +++ b/bin/nsupdate/nsupdate.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -1968,6 +1969,19 @@ parseclass: } } + if (!isdelete && rdata->type == dns_rdatatype_nsec3param) { + dns_rdata_nsec3param_t nsec3param; + + result = dns_rdata_tostruct(rdata, &nsec3param, NULL); + check_result(result, "dns_rdata_tostruct"); + if (nsec3param.iterations > dns_nsec3_maxiterations()) { + fprintf(stderr, + "NSEC3PARAM has excessive iterations (> %u)\n", + dns_nsec3_maxiterations()); + goto failure; + } + } + doneparsing: result = dns_message_gettemprdatalist(updatemsg, &rdatalist); diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 1bbb804584..7a421f1c8b 100755 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -1190,6 +1190,8 @@ then echo_i "failed"; status=1 fi +n=`expr $n + 1` +ret=0 echo_i "check that DS to the zone apex is ignored ($n)" $DIG $DIGOPTS +tcp +norec example DS @10.53.0.3 > dig.out.pre.test$n || ret=1 grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1 @@ -1209,7 +1211,20 @@ grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1 grep "ANSWER: 0," dig.out.post.test$n > /dev/null || ret=1 [ $ret = 0 ] || { echo_i "failed"; status=1; } -if $FEATURETEST --gssapi ; then +n=`expr $n + 1` +ret=0 +echo_i "check that excessive NSEC3PARAM iterations are rejected by nsupdate ($n)" +$NSUPDATE -d < nsupdate.out-$n 2>&1 && ret=1 +server 10.53.0.3 ${PORT} +zone example +update add example 0 in NSEC3PARAM 1 0 151 - +END +grep "NSEC3PARAM has excessive iterations (> 150)" nsupdate.out-$n || ret=1 +[ $ret = 0 ] || { echo_i "failed"; status=1; } + +if ! $FEATURETEST --gssapi ; then + echo_i "SKIPPED: GSSAPI tests" +else n=`expr $n + 1` ret=0 echo_i "check krb5-self match ($n)" From 4ce8437a6ef788fd6337f2c36de973eb4f7358fd Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 23 Apr 2021 10:28:06 +1000 Subject: [PATCH 5/9] Check that named rejects excessive iterations via UPDATE --- bin/tests/system/nsupdate/tests.sh | 3 ++- bin/tests/system/nsupdate/update_test.pl | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh index 7a421f1c8b..f7a1a4ee4e 100755 --- a/bin/tests/system/nsupdate/tests.sh +++ b/bin/tests/system/nsupdate/tests.sh @@ -310,6 +310,7 @@ then { $PERL update_test.pl -s 10.53.0.1 -p ${PORT} update.nil. || ret=1 } | cat_i + grep "updating zone 'update.nil/IN': too many NSEC3 iterations (151)" ns1/named.run > /dev/null || ret=1 [ $ret -eq 1 ] && { echo_i "failed"; status=1; } else echo_i "The second part of this test requires the Net::DNS library." >&2 @@ -1219,7 +1220,7 @@ server 10.53.0.3 ${PORT} zone example update add example 0 in NSEC3PARAM 1 0 151 - END -grep "NSEC3PARAM has excessive iterations (> 150)" nsupdate.out-$n || ret=1 +grep "NSEC3PARAM has excessive iterations (> 150)" nsupdate.out-$n >/dev/null || ret=1 [ $ret = 0 ] || { echo_i "failed"; status=1; } if ! $FEATURETEST --gssapi ; then diff --git a/bin/tests/system/nsupdate/update_test.pl b/bin/tests/system/nsupdate/update_test.pl index 894a572196..fd6a5425aa 100644 --- a/bin/tests/system/nsupdate/update_test.pl +++ b/bin/tests/system/nsupdate/update_test.pl @@ -410,6 +410,10 @@ test("NOERROR", ["update", rr_add("u.$zone 300 NS ns.u.$zone")]); test("NOERROR", ["update", rr_del("u.$zone NS ns.u.$zone")]); +section("Excessive NSEC3PARAM iterations"); +test("REFUSED", ["update", rr_add("$zone 300 NSEC3PARAM 1 0 151 -")]); +test("NOERROR", ["update", rr_add("$zone 300 NSEC3PARAM 1 0 150 -")]); + if ($failures) { print "$failures tests failed.\n"; } else { From 8ec16c378dbe4698de10174bb29e23c6814a406e Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 23 Apr 2021 11:46:31 +1000 Subject: [PATCH 6/9] Check NSEC3 iterations with dnssec-signzone --- .../general/Kexample.com.+008+15002.key | 5 +++ .../general/Kexample.com.+008+15002.private | 13 ++++++++ .../general/Kexample.com.+008+63613.key | 5 +++ .../general/Kexample.com.+008+63613.private | 13 ++++++++ .../system/dnssec/signer/general/test9.zone | 17 ++++++++++ bin/tests/system/dnssec/tests.sh | 32 ++++++++++++++++--- util/copyrights | 4 +++ 7 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key create mode 100644 bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private create mode 100644 bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key create mode 100644 bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private create mode 100644 bin/tests/system/dnssec/signer/general/test9.zone diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key new file mode 100644 index 0000000000..d4b8efbe61 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 15002, for example.com. +; Created: 20210423012926 (Fri Apr 23 11:29:26 2021) +; Publish: 20210423012926 (Fri Apr 23 11:29:26 2021) +; Activate: 20210423012926 (Fri Apr 23 11:29:26 2021) +example.com. IN DNSKEY 257 3 8 AwEAAdp+oCXl7vpKA3Mmyndx6/iA+wLrtxeMUiWL7uWJ9ZF24EdS8Dye 63p0lGlyvjvM9T5dTiyEpTAdutEBr79H0MlDqIBqpadrCdJRI2S4kC+0 nq5+Aj2CEyiAamPGujwWeXwtfLAvVPfBqs42PBr6wPQIJOByFYDaZBU3 enUEWgHYy/7OnJDrt0QlswKphR6SvYtyuixiUR8J/WouWXglUY5qlC7Z vVDxs9E4q7B1mfKCyoqcFMKPh9lzEBH+IfUZ543xXEYf2BEztKB1SZ2R QnpYedjATGDcgPis46uA2gHMfvDYJTQ5UqTBtveGb3Wsqc0oRXVPMEoY 3WnWhaKDzkk= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private new file mode 100644 index 0000000000..72b8e2e0c1 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: 2n6gJeXu+koDcybKd3Hr+ID7Auu3F4xSJYvu5Yn1kXbgR1LwPJ7renSUaXK+O8z1Pl1OLISlMB260QGvv0fQyUOogGqlp2sJ0lEjZLiQL7Sern4CPYITKIBqY8a6PBZ5fC18sC9U98GqzjY8GvrA9Agk4HIVgNpkFTd6dQRaAdjL/s6ckOu3RCWzAqmFHpK9i3K6LGJRHwn9ai5ZeCVRjmqULtm9UPGz0TirsHWZ8oLKipwUwo+H2XMQEf4h9RnnjfFcRh/YETO0oHVJnZFCelh52MBMYNyA+Kzjq4DaAcx+8NglNDlSpMG294ZvdaypzShFdU8wShjdadaFooPOSQ== +PublicExponent: AQAB +PrivateExponent: SD4X64/0DTONonRP+2Biej8DP7r6RcHyo1F6QtDzrg4VJ+AHaLPO/iUvsRHsTk99QwqMv3F4QMmDrHmXR3KSWQmS3Crm7M0aaTzErBfOLMfWs7EcQoQQm5KiGq1phFaWAnXzxTlRKb4SIK6T/wOr6sQKlV+DNqB++Pjn92rh67vLM8kZBUzWI14Vl9N0ib+xOOFH1oYFo7ynDgMfJhpnQSkuRfyQls3aD1eKQsNazRtZ7lFi2S0HR/V0AKYH2AQi7SdL5wH6hYba5cHfpKSw7PebI0lYkUJ4PAg3Xw7DPMkg8O0hkpLICpU8x7MPqQQ74eKDaEY+fjbL0KLL0Dy9UQ== +Prime1: /IDRb7WzMY6wp14LqDORULoUnmiQOqkRjOQnCoEXT2KVpYwPmGMG+GR40hrMFgqqAZFVmi56VBoasWpYbSBEqM4aJv1JVimMPREk23v5i+TY93kxICO/ee9/v0hXgLmrKUkS1Kwu4a1PxLX5U/LAzXPR6zF+EHP9OKFjDRWHqN0= +Prime2: 3YU9QdtsXofjNmlDETRwemKv45pa0oVNPmNvS1vtzIpQ3m/QSuhJxzyTgSP9x1XMiIsg63er3LOCtkRifXVE1IBrfIUgchp8YD5LsyesRl2ielE8Hw8PwSA1YjUVu90yRHcVfbZJ8lm2KyRKHgDWXz94t2Xnm/9M5XjUGuNW7l0= +Exponent1: 7KIkpJYZyvW4ZAFk10sMgiUBMbs4f2D2i509YUC9ga4YJD7wVpVncN1nxS9L19RCopl7KbUo+yxDm8TX/dzhu3j7VVLFqbPiM1Cfw/mZUhszoii3ezFFPpbOl4rKRl66I0TSGvEKNoDfYrBPavby7Rf/wHRveifZRXspgpeMvRk= +Exponent2: yvvtjuxW2CRiopg/+YL40lyd2cy2DpRRnKqW8BHzzGquAbWpwwopmOS8MSjewgqv2irK5pmJJTpku0nciiOsB6EJXVfLzGLSt4o96ZOf+/aPDNBla/xsLkaqRCxqlvPwvOX2DnS8O9PS5qNhOy7/QNYzcrJxUfPV7awTh/Pr040= +Coefficient: PHxU1tqPKTpI/8nABvso0SRerc1m+RPWGRk7s/SVcADSBvEW7fUDcwiZeRfK9MdlwPvLiVozbYnRbgRQl8GuKSqAD1+Cnvn2yOQk81AgNKbuKPwF7UvKIdq/c/xnhj2bvZUVSavJ91ux/RlZNP50378Ks8bj5HJl1xzAMVHXB5o= +Created: 20210423012926 +Publish: 20210423012926 +Activate: 20210423012926 diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key new file mode 100644 index 0000000000..990b837003 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 63613, for example.com. +; Created: 20210423012810 (Fri Apr 23 11:28:10 2021) +; Publish: 20210423012810 (Fri Apr 23 11:28:10 2021) +; Activate: 20210423012810 (Fri Apr 23 11:28:10 2021) +example.com. IN DNSKEY 256 3 8 AwEAAZzun7bYfjmGDwUEn4pyJG34vsiawRMW6pEdoNMH87ozxriOzgG6 /4zTjEv8JyYjGQz2k2vcoWWcD+86xD5IUqfa1pdXXUU8bdhG9DBtW/K1 mc4P6g8heU+0f++mq/L4TPlWVZUG8lVH4H8mD6r8PsVK7v/QR7wMeg9b JpCYyxon2A9rZ4zS0J9kX9bfciQVh6ODGVENctwEK5FNp5u0VonPEIx3 5Kj+IVn/mHpfbz4LaC02s7C6Kgvn3ToFFSJczwbOaexl/d+/ai8FLJi7 8UgiAq5/178bcVLItMeY6aD5eQGkRtr2c3JZ/JR4Nf+TQAWFBnl9NSDa RH4Qa55ZNqs= diff --git a/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private new file mode 100644 index 0000000000..1765d3f0f6 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: nO6ftth+OYYPBQSfinIkbfi+yJrBExbqkR2g0wfzujPGuI7OAbr/jNOMS/wnJiMZDPaTa9yhZZwP7zrEPkhSp9rWl1ddRTxt2Eb0MG1b8rWZzg/qDyF5T7R/76ar8vhM+VZVlQbyVUfgfyYPqvw+xUru/9BHvAx6D1smkJjLGifYD2tnjNLQn2Rf1t9yJBWHo4MZUQ1y3AQrkU2nm7RWic8QjHfkqP4hWf+Yel9vPgtoLTazsLoqC+fdOgUVIlzPBs5p7GX9379qLwUsmLvxSCICrn/XvxtxUsi0x5jpoPl5AaRG2vZzcln8lHg1/5NABYUGeX01INpEfhBrnlk2qw== +PublicExponent: AQAB +PrivateExponent: N4egcDzO/V/YdLgcFAsrpNY9/BH2e+DCA7NuMv4/WgX0LV4quyYGQzigDksdNzt4I8Qkiig53BCK+uXahwdkaAzhng/F6zfkzoDc6z3nKUzlLasn8U6w9Gk0VAKwGXuPETNheShKG68hWxyGssQrGfjX9SEoIPxxPHnOfZ/zTj95KAnVV5qPz90xVAb0+FUrLXAt72KuRwepOTlsETsMFDKe17uUCqCCdX98Ko0u14wrO6zGRQtNhUsfvNB/pY8fvbHD1GcCTbFSx4FxsUsZMrNtMsvMe3HN9ggC0Y9htbH9HV0hS0w9SKCUyoeOVwf/JZL4hlfoe8+jglsyJpAgoQ== +Prime1: zeXvO3PT4iXv9GlGeebl39pF1sXs8tXY4B9VHUJGGSYlyOlyCEy4URQJIPfuL6VjFKCErSxUJSrGz0HyQuKr8l9qP/0MGxGRH7wxvUR7YTmai84yyQ4fFENRmn8bzxGwj0MVHIW7cKC59j7nWT24gseT21/NP5m8EnPsjz/K40M= +Prime2: wx5vVFSydUfr8HtOHNS1kRrTjhnQOfjmj8SxGi72Hk+mgi9fBCTC5fRLifd80wGbgyFk1vZOXeStOC8L3IlnBGLX0O9MNip+vVX3hRzIRhLwHhL1ygN3xEd04qwVH0XJ8+4A0XCzh/FJgW59F62geN6gwedo7GmZAOSZUBAyRHk= +Exponent1: IlkqeLuQ7Fgx2I87b5iiXp62Keco6TXdkT4I3/GvagCgKw0utc2+rd/uye4ycQZhKg7BM3aCrxScx/STaq8PykY6nmQjgdyDXkzx60YiYwzOCGakuD+/1YyJb4Gm7PthffTN780rgNV/UGIcDBoszrxmoSExR1vpMRbfruIQgas= +Exponent2: or0Os/KUibc79W6Snv9WlLkgPAQRpViQzNaLtD/47R0Xzrs975HNsMgJ/P+bb86Ga1994MC8ahmh1BuBNCax8nmScWQ1V3QoEzjRYoe4DqIa/aposF4mFWJX/fry/wtRPo+CxSzPwJGh8j86PHaHQmjFAhVFcPE+OP1xVdK8alk= +Coefficient: r5wPmPXUF5pVC0Y7La3jVkL4w/3wvq9LBz91tH9gA8OUNLpDDBuFZISiJdhOZ4JVw+qSSoHcEa+3Phd+BqxmXzwZDU1Fqta9mLDDGCqCWjVQOopeeJgrvkv9P0TIzEuoGmW50cQhyqHYCtuUxjOnHfiQSc53p7rfD4Vom1VQ3Ok= +Created: 20210423012810 +Publish: 20210423012810 +Activate: 20210423012810 diff --git a/bin/tests/system/dnssec/signer/general/test9.zone b/bin/tests/system/dnssec/signer/general/test9.zone new file mode 100644 index 0000000000..5cfac09189 --- /dev/null +++ b/bin/tests/system/dnssec/signer/general/test9.zone @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; 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 http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +; This is a zone which has two DNSKEY records, both of which have +; existing private key files available. They should be loaded automatically +; and the zone correctly signed. +; +$TTL 3600 +example.com. IN SOA ns hostmaster 00090000 1200 3600 604800 300 +$include Kexample.com.+008+63613.key +$include Kexample.com.+008+15002.key diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 0620562e25..6b4c267cd0 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -1312,7 +1312,7 @@ status=$((status+ret)) echo_ic "one non-KSK DNSKEY ($n)" ret=0 ( -cd signer/general || exit 1 +cd signer/general || exit 0 rm -f signed.zone $SIGNER -f signed.zone -o example.com. test2.zone > signer.out.$n test -f signed.zone @@ -1324,7 +1324,7 @@ status=$((status+ret)) echo_ic "one KSK DNSKEY ($n)" ret=0 ( -cd signer/general || exit 1 +cd signer/general || exit 0 rm -f signed.zone $SIGNER -f signed.zone -o example.com. test3.zone > signer.out.$n test -f signed.zone @@ -1372,7 +1372,7 @@ status=$((status+ret)) echo_ic "two DNSKEY, both private keys missing ($n)" ret=0 ( -cd signer/general || exit 1 +cd signer/general || exit 0 rm -f signed.zone $SIGNER -f signed.zone -o example.com. test7.zone > signer.out.$n test -f signed.zone @@ -1384,7 +1384,7 @@ status=$((status+ret)) echo_ic "two DNSKEY, one private key missing ($n)" ret=0 ( -cd signer/general || exit 1 +cd signer/general || exit 0 rm -f signed.zone $SIGNER -f signed.zone -o example.com. test8.zone > signer.out.$n test -f signed.zone @@ -1393,6 +1393,30 @@ n=$((n+1)) test "$ret" -eq 0 || echo_i "failed" status=$((status+ret)) +echo_ic "check that dnssec-signzone rejects excessive NSEC3 iterations ($n)" +ret=0 +( +cd signer/general || exit 0 +rm -f signed.zone +$SIGNER -f signed.zone -3 - -H 151 -o example.com. test9.zone > signer.out.$n +test -f signed.zone +) && ret=1 +n=$((n+1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + +echo_ic "check that dnssec-signzone accepts maximum NSEC3 iterations ($n)" +ret=0 +( +cd signer/general || exit 1 +rm -f signed.zone +$SIGNER -f signed.zone -3 - -H 150 -o example.com. test9.zone > signer.out.$n +test -f signed.zone +) || ret=1 +n=$((n+1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + echo_i "checking that a key using an unsupported algorithm cannot be generated ($n)" ret=0 zone=example diff --git a/util/copyrights b/util/copyrights index e716e78985..1e37f6a4c7 100644 --- a/util/copyrights +++ b/util/copyrights @@ -362,6 +362,10 @@ ./bin/tests/system/dnssec/signer/general/Kexample.com.+005+07065.private X 2018,2019,2020,2021 ./bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.key X 2018,2019,2020,2021 ./bin/tests/system/dnssec/signer/general/Kexample.com.+005+23362.private X 2018,2019,2020,2021 +./bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.key X 2021 +./bin/tests/system/dnssec/signer/general/Kexample.com.+008+15002.private X 2021 +./bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.key X 2021 +./bin/tests/system/dnssec/signer/general/Kexample.com.+008+63613.private X 2021 ./bin/tests/system/dnssec/signer/general/bogus-ksk.key X 2018,2019,2020,2021 ./bin/tests/system/dnssec/signer/general/bogus-zsk.key X 2018,2019,2020,2021 ./bin/tests/system/dnssec/tests.sh SH 2000,2001,2002,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021 From 46eb21c546eb36362bafcefa65ee8650fe2de795 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 17 Feb 2021 16:33:49 +1100 Subject: [PATCH 7/9] Check that excessive iterations in logged by named when loading an existing zone or transfering from the primary. --- bin/dnssec/dnssec-signzone.c | 20 ++++++++++++--- bin/tests/system/dnssec/clean.sh | 1 + bin/tests/system/dnssec/ns1/root.db.in | 2 ++ bin/tests/system/dnssec/ns1/sign.sh | 1 + bin/tests/system/dnssec/ns2/named.conf.in | 5 ++++ bin/tests/system/dnssec/ns2/sign.sh | 11 ++++++++ .../dnssec/ns2/too-many-iterations.db.in | 25 +++++++++++++++++++ bin/tests/system/dnssec/ns3/named.conf.in | 6 +++++ bin/tests/system/dnssec/ns4/named4.conf.in | 1 + bin/tests/system/dnssec/tests.sh | 8 ++++++ 10 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 bin/tests/system/dnssec/ns2/too-many-iterations.db.in diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 0881ef3bda..902dfce8b4 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -178,8 +178,9 @@ static bool remove_orphansigs = false; static bool remove_inactkeysigs = false; static bool output_dnssec_only = false; static bool output_stdout = false; -bool set_maxttl = false; +static bool set_maxttl = false; static dns_ttl_t maxttl = 0; +static bool no_max_check = false; #define INCSTAT(counter) \ if (printstats) { \ @@ -3439,6 +3440,12 @@ main(int argc, char *argv[]) { case 'H': set_iter = true; + /* too-many is NOT DOCUMENTED */ + if (strcmp(isc_commandline_argument, "too-many") == 0) { + nsec3iter = 151; + no_max_check = true; + break; + } nsec3iter = strtoul(isc_commandline_argument, &endp, 0); if (*endp != '\0') { fatal("iterations must be numeric"); @@ -3876,9 +3883,14 @@ main(int argc, char *argv[]) { } if (nsec3iter > dns_nsec3_maxiterations()) { - fatal("NSEC3 iterations too big for weakest DNSKEY " - "strength. Maximum iterations allowed %u.", - dns_nsec3_maxiterations()); + if (no_max_check) { + fprintf(stderr, + "Ignoring max iterations check.\n"); + } else { + fatal("NSEC3 iterations too big. Maximum " + "iterations allowed %u.", + dns_nsec3_maxiterations()); + } } } else { hashlist_init(&hashlist, 0, 0); /* silence clang */ diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh index e660c3349d..adcb52f7d2 100644 --- a/bin/tests/system/dnssec/clean.sh +++ b/bin/tests/system/dnssec/clean.sh @@ -25,6 +25,7 @@ rm -f ./canonical?.* rm -f ./delv.out* rm -f ./delve.out* rm -f ./dig.out.* +rm -f ./ns2/too-many-iterations.db rm -f ./dnssectools.out* rm -f ./dsfromkey.out.* rm -f ./keygen.err diff --git a/bin/tests/system/dnssec/ns1/root.db.in b/bin/tests/system/dnssec/ns1/root.db.in index 09855f7d20..9c1296e899 100644 --- a/bin/tests/system/dnssec/ns1/root.db.in +++ b/bin/tests/system/dnssec/ns1/root.db.in @@ -31,3 +31,5 @@ ns6.optout-tld. A 10.53.0.6 in-addr.arpa. NS ns2.example. inprogress. NS ns10.inprogress. ns10.inprogress. A 10.53.0.10 +too-many-iterations. NS ns2.too-many-iterations. +ns2.too-many-iterations. A 10.53.0.2 diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh index 2a54928719..e59e534c51 100644 --- a/bin/tests/system/dnssec/ns1/sign.sh +++ b/bin/tests/system/dnssec/ns1/sign.sh @@ -26,6 +26,7 @@ echo_i "ns1/sign.sh" cp "../ns2/dsset-example$TP" . cp "../ns2/dsset-in-addr.arpa$TP" . +cp "../ns2/dsset-too-many-iterations$TP" . grep "$DEFAULT_ALGORITHM_NUMBER [12] " "../ns2/dsset-algroll$TP" > "dsset-algroll$TP" cp "../ns6/dsset-optout-tld$TP" . diff --git a/bin/tests/system/dnssec/ns2/named.conf.in b/bin/tests/system/dnssec/ns2/named.conf.in index 4b75918a56..3928ec03ad 100644 --- a/bin/tests/system/dnssec/ns2/named.conf.in +++ b/bin/tests/system/dnssec/ns2/named.conf.in @@ -191,4 +191,9 @@ zone "hours-vs-days" { allow-update { any; }; }; +zone "too-many-iterations" { + type master; + file "too-many-iterations.db.signed"; +}; + include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns2/sign.sh b/bin/tests/system/dnssec/ns2/sign.sh index 1bfaa37a04..af2717825f 100644 --- a/bin/tests/system/dnssec/ns2/sign.sh +++ b/bin/tests/system/dnssec/ns2/sign.sh @@ -318,3 +318,14 @@ key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$ key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") $SETTIME -P sync now "$key1" > /dev/null cat "$infile" > "$zonefile.signed" + +# +# Negative result from this zone should come back as insecure. +# +zone=too-many-iterations +infile=too-many-iterations.db.in +zonefile=too-many-iterations.db +key1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone -f KSK "$zone") +key2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone") +cat "$infile" "$key1.key" "$key2.key" > "$zonefile" +"$SIGNER" -P -3 - -H too-many -g -o "$zone" "$zonefile" > /dev/null 2>&1 diff --git a/bin/tests/system/dnssec/ns2/too-many-iterations.db.in b/bin/tests/system/dnssec/ns2/too-many-iterations.db.in new file mode 100644 index 0000000000..e6f502fe69 --- /dev/null +++ b/bin/tests/system/dnssec/ns2/too-many-iterations.db.in @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; 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 http://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 30 ; 5 minutes +@ IN SOA mname1. . ( + 2000042407 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 30 ; minimum (1 hour) + ) + NS ns2 +ns2 A 10.53.0.2 +ns3 A 10.53.0.3 + +a A 10.0.0.1 +*.a A 10.0.0.3 +b A 10.0.0.2 +d A 10.0.0.4 diff --git a/bin/tests/system/dnssec/ns3/named.conf.in b/bin/tests/system/dnssec/ns3/named.conf.in index 196a13dd4e..233db0cc91 100644 --- a/bin/tests/system/dnssec/ns3/named.conf.in +++ b/bin/tests/system/dnssec/ns3/named.conf.in @@ -363,6 +363,12 @@ zone "revoked.trusted" { file "revoked.trusted.db.signed"; }; +zone "too-many-iterations" { + type secondary; + primaries { 10.53.0.2; }; + file "too-many-iterations.bk"; +}; + include "siginterval.conf"; include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns4/named4.conf.in b/bin/tests/system/dnssec/ns4/named4.conf.in index 77590b30f3..6e5b40a830 100644 --- a/bin/tests/system/dnssec/ns4/named4.conf.in +++ b/bin/tests/system/dnssec/ns4/named4.conf.in @@ -42,6 +42,7 @@ view rec { recursion yes; dnssec-validation yes; dnssec-accept-expired yes; + minimal-responses no; zone "." { type hint; diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index 6b4c267cd0..728325c794 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -4323,5 +4323,13 @@ n=$((n+1)) test "$ret" -eq 0 || echo_i "failed" status=$((status+ret)) +echo_i "checking excessive NSEC3 iteration warnings in named.run ($n)" +ret=0 +grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 150" ns2/named.run >/dev/null 2>&1 || ret=1 +grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 150" ns3/named.run >/dev/null 2>&1 || ret=1 +n=$((n+1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status+ret)) + echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 From e04f06873f7d1e9ffd061f6f8f91df05818f0ba2 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 21 Apr 2021 11:43:47 +1000 Subject: [PATCH 8/9] Add CHANGES for [GL #2642] 5625. [func] Reduce the supported maximum number of iterations that can be configured in an NSEC3 zones to 150. [GL #2642] --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 24b36eb72a..ad7b586591 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +5629. [func] Reduce the supported maximum number of iterations + that can be configured in an NSEC3 zone to 150. + [GL #2642] + 5628. [bug] Host and nslookup could die on SERVFAIL response. [GL #2564] From ca07b8e414ff51d19af51dad1433dd2f8042020a Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Wed, 21 Apr 2021 11:45:56 +1000 Subject: [PATCH 9/9] Add Release Note for [GL #2642] --- doc/notes/notes-current.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/notes/notes-current.rst b/doc/notes/notes-current.rst index 5a47a5f528..23f122f192 100644 --- a/doc/notes/notes-current.rst +++ b/doc/notes/notes-current.rst @@ -48,6 +48,9 @@ Feature Changes - Implement ``draft-vandijk-dnsop-nsec-ttl``, NSEC(3) TTL values are now set to the minimum of the SOA MINIMUM value and the SOA TTL. [GL #2347]. +- Reduce the supported maximum number of iterations that can be + configured in an NSEC3 zones to 150. [GL #2642] + Bug Fixes ~~~~~~~~~