From: Matthijs Mekking Date: Fri, 13 Nov 2020 11:26:05 +0000 (+0100) Subject: Add NSEC3PARAM unit test, refactor zone.c X-Git-Tag: v9.17.8~27^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=64db30942df50ef229624d48c8bfe08bc300a528;p=thirdparty%2Fbind9.git Add NSEC3PARAM unit test, refactor zone.c Add unit test to ensure the right NSEC3PARAM event is scheduled in 'dns_zone_setnsec3param()'. To avoid scheduling and managing actual tasks, split up the 'dns_zone_setnsec3param()' function in two parts: 1. 'dns__zone_lookup_nsec3param()' that will check if the requested NSEC3 parameters already exist, and if a new salt needs to be generated. 2. The actual scheduling of the new NSEC3PARAM event (if needed). --- diff --git a/lib/dns/include/dns/result.h b/lib/dns/include/dns/result.h index 7528e8bef03..58e7426b3fa 100644 --- a/lib/dns/include/dns/result.h +++ b/lib/dns/include/dns/result.h @@ -161,8 +161,9 @@ #define DNS_R_NSEC3ITERRANGE (ISC_RESULTCLASS_DNS + 123) #define DNS_R_NSEC3SALTRANGE (ISC_RESULTCLASS_DNS + 124) #define DNS_R_NSEC3BADALG (ISC_RESULTCLASS_DNS + 125) +#define DNS_R_NSEC3RESALT (ISC_RESULTCLASS_DNS + 126) -#define DNS_R_NRESULTS 126 /*%< Number of results */ +#define DNS_R_NRESULTS 127 /*%< Number of results */ /* * DNS wire format rcodes. diff --git a/lib/dns/result.c b/lib/dns/result.c index 118e2574f0b..1c8641227b9 100644 --- a/lib/dns/result.c +++ b/lib/dns/result.c @@ -169,10 +169,11 @@ static const char *text[DNS_R_NRESULTS] = { "no matching key found", /*%< 120 DNS_R_NOKEYMATCH */ "too many keys matching", /*%< 121 DNS_R_TOOMANYKEYS */ "key is not actively signing", /*%< 122 DNS_R_KEYNOTACTIVE */ + "NSEC3 iterations out of range", /*%< 123 DNS_R_NSEC3ITERRANGE */ + "NSEC3 salt length too high", /*%< 124 DNS_R_NSEC3SALTRANGE */ - "NSEC3 iterations out of range", /*%< 123 DNS_R_NSEC3ITERRANGE */ - "NSEC3 salt length too high", /*%< 124 DNS_R_NSEC3SALTRANGE */ "cannot use NSEC3 with key algorithm", /*%< 125 DNS_R_NSEC3BADALG */ + "NSEC3 resalt", /*%< 126 DNS_R_NSEC3RESALT */ }; static const char *ids[DNS_R_NRESULTS] = { @@ -306,6 +307,7 @@ static const char *ids[DNS_R_NRESULTS] = { "DNS_R_NSEC3ITERRANGE", "DNS_R_NSEC3SALTRANGE", "DNS_R_NSEC3BADALG", + "DNS_R_NSEC3RESALT", }; static const char *rcode_text[DNS_R_NRCODERESULTS] = { diff --git a/lib/dns/tests/Makefile.am b/lib/dns/tests/Makefile.am index 3322b892288..d28608bb5fb 100644 --- a/lib/dns/tests/Makefile.am +++ b/lib/dns/tests/Makefile.am @@ -30,6 +30,7 @@ check_PROGRAMS = \ keytable_test \ name_test \ nsec3_test \ + nsec3param_test \ peer_test \ private_test \ rbt_serialize_test \ diff --git a/lib/dns/tests/nsec3param_test.c b/lib/dns/tests/nsec3param_test.c new file mode 100644 index 00000000000..7cb46f2ab14 --- /dev/null +++ b/lib/dns/tests/nsec3param_test.c @@ -0,0 +1,302 @@ +/* + * 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 https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#if HAVE_CMOCKA + +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include +#include + +#define UNIT_TESTING +#include + +#include +#include +#include + +#include +#include +#include + +#include "../zone_p.h" +#include "dnstest.h" + +#define HASH 1 +#define FLAGS 0 +#define ITER 5 +#define SALTLEN 4 +#define SALT "FEDCBA98" + +static int +_setup(void **state) { + isc_result_t result; + + UNUSED(state); + + result = dns_test_begin(NULL, false); + assert_int_equal(result, ISC_R_SUCCESS); + + return (0); +} + +static int +_teardown(void **state) { + UNUSED(state); + + dns_test_end(); + + return (0); +} + +/*% + * Structures containing parameters for nsec3param_salttotext_test(). + */ +typedef struct { + dns_hash_t hash; + unsigned char flags; + dns_iterations_t iterations; + unsigned char salt_length; + const char *salt; +} nsec3param_rdata_test_params_t; + +typedef struct { + nsec3param_rdata_test_params_t lookup; + nsec3param_rdata_test_params_t expect; + bool resalt; + isc_result_t expected_result; +} nsec3param_change_test_params_t; + +static void +decode_salt(const char *string, unsigned char *salt, size_t saltlen) { + isc_buffer_t buf; + isc_result_t result; + + isc_buffer_init(&buf, salt, saltlen); + result = isc_hex_decodestring(string, &buf); + assert_int_equal(result, ISC_R_SUCCESS); +} + +static void +copy_params(nsec3param_rdata_test_params_t from, dns_rdata_nsec3param_t *to, + unsigned char *saltbuf, size_t saltlen) { + to->hash = from.hash; + to->flags = from.flags; + to->iterations = from.iterations; + to->salt_length = from.salt_length; + if (from.salt == NULL) { + to->salt = NULL; + } else if (strcmp(from.salt, "-") == 0) { + DE_CONST("-", to->salt); + } else { + decode_salt(from.salt, saltbuf, saltlen); + to->salt = saltbuf; + } +} + +static nsec3param_rdata_test_params_t +rdata_fromparams(uint8_t hash, uint8_t flags, uint16_t iter, uint8_t saltlen, + const char *salt) { + nsec3param_rdata_test_params_t nsec3param; + nsec3param.hash = hash; + nsec3param.flags = flags; + nsec3param.iterations = iter; + nsec3param.salt_length = saltlen; + nsec3param.salt = salt; + return (nsec3param); +} + +/*% + * Check whether zone_lookup_nsec3param() finds the correct NSEC3PARAM + * and sets the correct parameters to use in dns_zone_setnsec3param(). + */ +static void +nsec3param_change_test(const nsec3param_change_test_params_t *test) { + dns_zone_t *zone = NULL; + dns_rdata_nsec3param_t param, lookup, expect; + isc_result_t result; + unsigned char lookupsalt[255]; + unsigned char expectsalt[255]; + unsigned char saltbuf[255]; + + /* + * Prepare a zone along with its signing keys. + */ + result = dns_test_makezone("nsec3", &zone, NULL, false); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_zone_setfile(zone, "testdata/nsec3param/nsec3.db.signed", + dns_masterformat_text, + &dns_master_style_default); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_zone_load(zone, false); + assert_int_equal(result, ISC_R_SUCCESS); + + /* + * Copy parameters. + */ + copy_params(test->lookup, &lookup, lookupsalt, sizeof(lookupsalt)); + copy_params(test->expect, &expect, expectsalt, sizeof(expectsalt)); + + /* + * Test dns__zone_lookup_nsec3param(). + */ + result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m, saltbuf, + test->resalt); + + assert_int_equal(param.hash, expect.hash); + assert_int_equal(param.flags, expect.flags); + assert_int_equal(param.iterations, expect.iterations); + assert_int_equal(param.salt_length, expect.salt_length); + assert_non_null(param.salt); + if (expect.salt != NULL) { + int ret = memcmp(param.salt, expect.salt, expect.salt_length); + assert_true(ret == 0); + } else { + /* + * We don't know what the new salt is, but we can compare it + * to the previous salt and test that it has changed. + */ + unsigned char salt[SALTLEN]; + int ret; + decode_salt(SALT, salt, SALTLEN); + ret = memcmp(param.salt, salt, SALTLEN); + assert_false(ret == 0); + } + + /* + * Detach. + */ + dns_zone_detach(&zone); +} + +static void +nsec3param_change(void **state) { + size_t i; + + /* + * Define tests. + */ + const nsec3param_change_test_params_t tests[] = { + /* + * 1. Change nothing (don't care about salt). + * This should return ISC_R_SUCCESS because we are already + * using these NSEC3 parameters. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false, + ISC_R_SUCCESS }, + /* + * 2. Change nothing, but force a resalt. + * This should change the salt. Set 'expect.salt' to NULL to + * test a new salt has been generated. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true, + DNS_R_NSEC3RESALT }, + /* + * 3. Change iterations. + * The NSEC3 paarameters are not found, and there is no + * need to resalt because an explicit salt has been set, + * and resalt is not enforced. + */ + { rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT), + rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT), false, + ISC_R_NOTFOUND }, + /* + * 4. Change iterations, don't care about the salt. + * We don't care about the salt. Since we need to change the + * NSEC3 parameters, we will also resalt. + */ + { rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL), + rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL), false, + DNS_R_NSEC3RESALT }, + /* + * 5. Change salt length. + * Changing salt length means we need to resalt. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 16, NULL), + rdata_fromparams(HASH, FLAGS, ITER, 16, NULL), false, + DNS_R_NSEC3RESALT }, + /* + * 6. Set explicit salt. + * A different salt, so the NSEC3 parameters are not found. + * No need to resalt because an explicit salt is available. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"), + rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"), false, + ISC_R_NOTFOUND }, + /* + * 7. Same salt. + * Nothing changed, so expect ISC_R_SUCCESS as a result. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false, + ISC_R_SUCCESS }, + /* + * 8. Same salt, and force resalt. + * Nothing changed, but a resalt is enforced. + */ + { rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), + rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true, + DNS_R_NSEC3RESALT }, + /* + * 9. No salt. + * Change parameters to use no salt. These parameters are + * not found, and no new salt needs to be generated. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 0, NULL), + rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true, + ISC_R_NOTFOUND }, + /* + * 10. No salt, explicit. + * Same as above, but set no salt explicitly. + */ + { rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), + rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true, + ISC_R_NOTFOUND }, + }; + + UNUSED(state); + + /* + * Run tests. + */ + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + nsec3param_change_test(&tests[i]); + } +} + +int +main(void) { + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(nsec3param_change, _setup, + _teardown), + }; + + return (cmocka_run_group_tests(tests, NULL, NULL)); +} + +#else /* HAVE_CMOCKA */ + +#include + +int +main(void) { + printf("1..0 # Skipped: cmocka not available\n"); + return (0); +} + +#endif /* if HAVE_CMOCKA */ diff --git a/lib/dns/tests/testdata/nsec3param/nsec3.db.signed b/lib/dns/tests/testdata/nsec3param/nsec3.db.signed new file mode 100644 index 00000000000..aeced0e892c --- /dev/null +++ b/lib/dns/tests/testdata/nsec3param/nsec3.db.signed @@ -0,0 +1,73 @@ +; File written on Mon Nov 16 16:04:21 2020 +; dnssec_signzone version 9.16.8 +nsec3. 1000 IN SOA nsec3. postmaster.nsec3. ( + 1993050801 ; serial + 3600 ; refresh (1 hour) + 1800 ; retry (30 minutes) + 604800 ; expire (1 week) + 3600 ; minimum (1 hour) + ) + 1000 RRSIG SOA 13 1 1000 ( + 20201216140421 20201116140421 40382 nsec3. + qh61ZPgQaNLAoIQvAoTLbR3sLBY7XATaMGSS + fYOssQWvgAzpAzhalmF/cSXmQ/RZQOyIdpVg + v3rgyTxA2vGNnA== ) + 1000 NS ns1.nsec3. + 1000 NS ns2.nsec3. + 1000 RRSIG NS 13 1 1000 ( + 20201216140421 20201116140421 40382 nsec3. + 4Le+e5Lu/taEvrvrmBn/z+QP4zhzUqwO6v70 + WYrzCggUls8+fUd2unBHDPWag1oSKfNpGGWA + crihrs4RhMPfZA== ) + 1000 DNSKEY 257 3 13 ( + VKkttSi/v3lAyzUYnykwdwowXfDOQ7wdN9BT + +eb8fVfgRApvuun9hjUBlv7ogriU/GAb60B8 + juj9bXZADT+OGg== + ) ; KSK; alg = ECDSAP256SHA256 ; key id = 40382 + 1000 RRSIG DNSKEY 13 1 1000 ( + 20201216140421 20201116140421 40382 nsec3. + ZnBqGgWvHwjjQBSIRPXe2fx6+MsQp1QQdzJ0 + QaEyaOmud5JPatUXaV9eFRcPNCsi+2HZSZVp + vsAGUCge7w6u9A== ) + 0 NSEC3PARAM 1 0 5 FEDCBA98 + 0 RRSIG NSEC3PARAM 13 1 0 ( + 20201216140421 20201116140421 40382 nsec3. + WPTD+5vr54YtvGqCUJHPvGdF7Wd4piZYltcs + cztBRfdM7FRJ/zvrDS72rt6zm0TYSXzawqt/ + MiwOkYKv2vxfUg== ) +ns2.nsec3. 1000 IN A 1.2.3.5 + 1000 RRSIG A 13 2 1000 ( + 20201216140421 20201116140421 40382 nsec3. + l9Mc2Y5JFmllSxJj3GUdH6RtEsYfhjJU39sa + vAVa4zxv6S9vU+vLvTA05aQ+DPLvKTX+WNH7 + dDa+Yy5ffBs68g== ) +QVCH33BSJ0Q2C74FEDFDBCFQHO255NEB.nsec3. 3600 IN NSEC3 1 0 5 FEDCBA98 ( + STH5N5QDVC5DGEN5VGUC7JGALSM3R8AP + A RRSIG ) + 3600 RRSIG NSEC3 13 2 3600 ( + 20201216140421 20201116140421 40382 nsec3. + F/wKQtv+RlBHG1WCz0CkHlTSoUiRx0z+qBI1 + GTHoXSjgG1NSHqTI4C32AasZSMp+uuF2R8KW + 9z4gOLucl0Xmfg== ) +STH5N5QDVC5DGEN5VGUC7JGALSM3R8AP.nsec3. 3600 IN NSEC3 1 0 5 FEDCBA98 ( + A084TNR6VJ2ND5K1U0AI4HO4EPVKBG4U + NS SOA RRSIG DNSKEY NSEC3PARAM ) + 3600 RRSIG NSEC3 13 2 3600 ( + 20201216140421 20201116140421 40382 nsec3. + 9TgGFGY3vwkxMFlXy3oKMgHPqvcPozKDHZzc + Ny6eJn3TXNX5bLhiT5rw5+CCtyOEQmn3pf0X + njK7jZBAcBV+5Q== ) +A084TNR6VJ2ND5K1U0AI4HO4EPVKBG4U.nsec3. 3600 IN NSEC3 1 0 5 FEDCBA98 ( + QVCH33BSJ0Q2C74FEDFDBCFQHO255NEB + A RRSIG ) + 3600 RRSIG NSEC3 13 2 3600 ( + 20201216140421 20201116140421 40382 nsec3. + auf+5lrkMESIfdFK8bf4yg1a+NLGWzgUmohS + ydcKaJz0XcnULegatWdfE75jmZoDeqKNpwdL + 5lQ77GF4cEh1OQ== ) +ns1.nsec3. 1000 IN A 1.2.3.4 + 1000 RRSIG A 13 2 1000 ( + 20201216140421 20201116140421 40382 nsec3. + yAmr1EE8qe+Jl+wQXOdj/uSjMFUmns0D1lx6 + zAVe9BaQwvF3wR7ZUk/u9G0RrUBchmEj0+yq + KEsw32Tru4Romg== ) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 629992cc380..112e8a43944 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -21052,6 +21052,25 @@ failure: INSIST(newver == NULL); } +static void +salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text, + unsigned int textlen) { + isc_region_t r; + isc_buffer_t buf; + isc_result_t result; + + r.base = salt; + r.length = (unsigned int)saltlen; + + isc_buffer_init(&buf, text, textlen); + result = isc_hex_totext(&r, 2, "", &buf); + if (result == ISC_R_SUCCESS) { + text[saltlen * 2] = 0; + } else { + text[0] = 0; + } +} + /* * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters. * @@ -21061,9 +21080,10 @@ failure: * Returns ISC_R_SUCCESS, if a match is found, or an error if no match is * found, or if the db lookup failed. */ -static isc_result_t -zone_has_nsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, - uint16_t iter, uint8_t saltlen, unsigned char *salt) { +isc_result_t +dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup, + dns_rdata_nsec3param_t *param, + unsigned char saltbuf[255], bool resalt) { isc_result_t result = ISC_R_UNEXPECTED; dns_dbnode_t *node = NULL; dns_db_t *db = NULL; @@ -21073,7 +21093,6 @@ zone_has_nsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, dns_rdata_t rdata = DNS_RDATA_INIT; REQUIRE(DNS_ZONE_VALID(zone)); - UNUSED(flags); dns_rdataset_init(&rdataset); @@ -21083,7 +21102,7 @@ zone_has_nsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, } ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); if (db == NULL) { - goto cleanup; + goto setparam; } result = dns_db_findnode(db, &zone->origin, false, &node); @@ -21091,7 +21110,7 @@ zone_has_nsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, dns_zone_log(zone, ISC_LOG_ERROR, "nsec3param lookup failure: %s", dns_result_totext(result)); - goto cleanup; + goto setparam; } dns_db_currentversion(db, &version); @@ -21105,7 +21124,7 @@ zone_has_nsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, "nsec3param lookup failure: %s", dns_result_totext(result)); } - goto cleanup; + goto setparam; } for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; @@ -21115,27 +21134,76 @@ zone_has_nsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, result = dns_rdata_tostruct(&rdata, &nsec3param, NULL); INSIST(result == ISC_R_SUCCESS); dns_rdata_reset(&rdata); - if (nsec3param.hash != hash) { + + /* Check parameters. */ + if (nsec3param.hash != lookup->hash) { continue; } - if (nsec3param.iterations != iter) { + if (nsec3param.iterations != lookup->iterations) { continue; } - if (nsec3param.salt_length != saltlen) { + if (nsec3param.salt_length != lookup->salt_length) { continue; } - if (salt != NULL) { - if (memcmp(nsec3param.salt, salt, saltlen) != 0) { + if (lookup->salt != NULL) { + if (memcmp(nsec3param.salt, lookup->salt, + lookup->salt_length) != 0) { continue; } } /* Found a match. */ result = ISC_R_SUCCESS; - goto cleanup; + param->hash = nsec3param.hash; + param->flags = nsec3param.flags; + param->iterations = nsec3param.iterations; + param->salt_length = nsec3param.salt_length; + param->salt = nsec3param.salt; + break; + } + +setparam: + if (result != ISC_R_SUCCESS) { + /* Found no match. */ + result = ISC_R_NOTFOUND; + param->hash = lookup->hash; + param->flags = lookup->flags; + param->iterations = lookup->iterations; + param->salt_length = lookup->salt_length; + param->salt = lookup->salt; + } + + if (param->salt_length == 0) { + DE_CONST("-", param->salt); + } else if (resalt || param->salt == NULL) { + unsigned char *newsalt; + unsigned char salttext[255 * 2 + 1]; + do { + /* Generate a new salt. */ + result = dns_nsec3_generate_salt(saltbuf, + param->salt_length); + if (result != ISC_R_SUCCESS) { + break; + } + newsalt = saltbuf; + salt2text(newsalt, param->salt_length, salttext, + sizeof(salttext)); + dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s", + salttext); + /* Check for salt conflict. */ + if (param->salt != NULL && + memcmp(newsalt, param->salt, param->salt_length) == + 0) + { + result = ISC_R_SUCCESS; + } else { + param->salt = newsalt; + result = DNS_R_NSEC3RESALT; + } + } while (result == ISC_R_SUCCESS); + + INSIST(result != ISC_R_SUCCESS); } - INSIST(result != ISC_R_SUCCESS); -cleanup: if (dns_rdataset_isassociated(&rdataset)) { dns_rdataset_disassociate(&rdataset); } @@ -21152,25 +21220,6 @@ cleanup: return (result); } -static void -salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text, - unsigned int textlen) { - isc_region_t r; - isc_buffer_t buf; - isc_result_t result; - - r.base = salt; - r.length = (unsigned int)saltlen; - - isc_buffer_init(&buf, text, textlen); - result = isc_hex_totext(&r, 2, "", &buf); - if (result == ISC_R_SUCCESS) { - text[saltlen * 2] = 0; - } else { - text[0] = 0; - } -} - /* * Called when an "rndc signing -nsec3param ..." command is received, or the * 'dnssec-policy' has changed. @@ -21196,59 +21245,41 @@ dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, uint16_t iter, uint8_t saltlen, unsigned char *salt, bool replace, bool resalt) { isc_result_t result = ISC_R_SUCCESS; - dns_rdata_nsec3param_t param; + dns_rdata_nsec3param_t param, lookup; dns_rdata_t nrdata = DNS_RDATA_INIT; dns_rdata_t prdata = DNS_RDATA_INIT; unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE]; + unsigned char saltbuf[255]; struct np3event *npe; nsec3param_t *np; dns_zone_t *dummy = NULL; isc_buffer_t b; isc_event_t *e = NULL; - unsigned char saltbuf[255]; - unsigned char salttext[255 * 2 + 1]; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); - result = zone_has_nsec3param(zone, hash, flags, iter, saltlen, salt); - if (result == ISC_R_SUCCESS) { - /* - * The right NSEC3 parameters are already set, no need to - * set again, unless resalting is enforced. - */ - if (!resalt) { - result = ISC_R_EXISTS; - goto failure; + /* + * First check if the requested NSEC3 parameters are already set, + * if so, no need to set again. + */ + if (hash != 0) { + lookup.hash = hash; + lookup.flags = flags; + lookup.iterations = iter; + lookup.salt_length = saltlen; + lookup.salt = salt; + param.salt = NULL; + result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m, + saltbuf, resalt); + if (result == ISC_R_SUCCESS) { + UNLOCK_ZONE(zone); + return (ISC_R_SUCCESS); } + INSIST(param.salt != NULL); } - if (saltlen == 0) { - DE_CONST("-", salt); - salttext[0] = '-'; - salttext[1] = 0; - } else if (resalt || salt == NULL) { - do { - /* Generate a new salt. */ - CHECK(dns_nsec3_generate_salt(saltbuf, saltlen)); - if (result != ISC_R_SUCCESS) { - goto failure; - } - salt = saltbuf; - salt2text(salt, saltlen, salttext, sizeof(salttext)); - dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s", - salttext); - /* - * Check for NSEC3 param conflicts, this is done to - * avoid salt collision. - */ - result = zone_has_nsec3param(zone, hash, flags, iter, - saltlen, salt); - } while (result == ISC_R_SUCCESS); - } - INSIST(salt != NULL); - e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM, setnsec3param, zone, sizeof(struct np3event)); @@ -21265,11 +21296,7 @@ dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, param.common.rdtype = dns_rdatatype_nsec3param; ISC_LINK_INIT(¶m.common, link); param.mctx = NULL; - param.hash = hash; - param.flags = flags; - param.iterations = iter; - param.salt_length = saltlen; - param.salt = salt; + /* nsec3 specific param set in dns__zone_lookup_nsec3param() */ isc_buffer_init(&b, nbuf, sizeof(nbuf)); CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass, dns_rdatatype_nsec3param, ¶m, @@ -21280,10 +21307,13 @@ dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags, np->nsec = false; if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) { - salt2text(salt, saltlen, salttext, sizeof(salttext)); + unsigned char salttext[255 * 2 + 1]; + salt2text(param.salt, param.salt_length, salttext, + sizeof(salttext)); dnssec_log(zone, ISC_LOG_DEBUG(3), - "setnsec3param:nsec3 %u %u %u %s", hash, - flags, iter, salttext); + "setnsec3param:nsec3 %u %u %u %s", + param.hash, param.flags, param.iterations, + salttext); } } diff --git a/lib/dns/zone_p.h b/lib/dns/zone_p.h index 90f0b8476cd..0c1c40d109f 100644 --- a/lib/dns/zone_p.h +++ b/lib/dns/zone_p.h @@ -41,6 +41,11 @@ dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version, isc_stdtime_t now, bool check_ksk, bool keyset_kskonly, dns__zonediff_t *zonediff); +isc_result_t +dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup, + dns_rdata_nsec3param_t *param, + unsigned char saltbuf[255], bool resalt); + ISC_LANG_ENDDECLS #endif /* DNS_ZONE_P_H */ diff --git a/util/copyrights b/util/copyrights index ef18d6f35b6..065652da307 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1656,6 +1656,7 @@ ./lib/dns/tests/mkraw.pl PERL 2011,2012,2016,2018,2019,2020 ./lib/dns/tests/name_test.c C 2014,2015,2016,2017,2018,2019,2020 ./lib/dns/tests/nsec3_test.c C 2012,2014,2015,2016,2017,2018,2019,2020 +./lib/dns/tests/nsec3param_test.c C 2020 ./lib/dns/tests/peer_test.c C 2014,2016,2018,2019,2020 ./lib/dns/tests/private_test.c C 2011,2012,2016,2018,2019,2020 ./lib/dns/tests/rbt_serialize_test.c C 2014,2015,2016,2018,2019,2020