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).
This commit is contained in:
Matthijs Mekking 2020-11-13 12:26:05 +01:00
parent 6b5d7357df
commit 64db30942d
8 changed files with 563 additions and 148 deletions

View file

@ -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.

View file

@ -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] = {

View file

@ -30,6 +30,7 @@ check_PROGRAMS = \
keytable_test \
name_test \
nsec3_test \
nsec3param_test \
peer_test \
private_test \
rbt_serialize_test \

View file

@ -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 <sched.h> /* IWYU pragma: keep */
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/hex.h>
#include <isc/string.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/nsec3.h>
#include <dns/result.h>
#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, &param, 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 <stdio.h>
int
main(void) {
printf("1..0 # Skipped: cmocka not available\n");
return (0);
}
#endif /* if HAVE_CMOCKA */

View file

@ -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== )

View file

@ -21052,106 +21052,6 @@ failure:
INSIST(newver == NULL);
}
/*
* Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
*
* If 'salt' is NULL, a match is found if the salt has the requested length,
* otherwise the NSEC3 salt must match the requested salt value too.
*
* 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 result = ISC_R_UNEXPECTED;
dns_dbnode_t *node = NULL;
dns_db_t *db = NULL;
dns_dbversion_t *version = NULL;
dns_rdataset_t rdataset;
dns_rdata_nsec3param_t nsec3param;
dns_rdata_t rdata = DNS_RDATA_INIT;
REQUIRE(DNS_ZONE_VALID(zone));
UNUSED(flags);
dns_rdataset_init(&rdataset);
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (zone->db != NULL) {
dns_db_attach(zone->db, &db);
}
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
if (db == NULL) {
goto cleanup;
}
result = dns_db_findnode(db, &zone->origin, false, &node);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"nsec3param lookup failure: %s",
dns_result_totext(result));
goto cleanup;
}
dns_db_currentversion(db, &version);
result = dns_db_findrdataset(db, node, version,
dns_rdatatype_nsec3param,
dns_rdatatype_none, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS) {
INSIST(!dns_rdataset_isassociated(&rdataset));
if (result != ISC_R_NOTFOUND) {
dns_zone_log(zone, ISC_LOG_ERROR,
"nsec3param lookup failure: %s",
dns_result_totext(result));
}
goto cleanup;
}
for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset))
{
dns_rdataset_current(&rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
INSIST(result == ISC_R_SUCCESS);
dns_rdata_reset(&rdata);
if (nsec3param.hash != hash) {
continue;
}
if (nsec3param.iterations != iter) {
continue;
}
if (nsec3param.salt_length != saltlen) {
continue;
}
if (salt != NULL) {
if (memcmp(nsec3param.salt, salt, saltlen) != 0) {
continue;
}
}
/* Found a match. */
result = ISC_R_SUCCESS;
goto cleanup;
}
INSIST(result != ISC_R_SUCCESS);
cleanup:
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_disassociate(&rdataset);
}
if (node != NULL) {
dns_db_detachnode(db, &node);
}
if (version != NULL) {
dns_db_closeversion(db, &version, false);
}
if (db != NULL) {
dns_db_detach(&db);
}
return (result);
}
static void
salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
unsigned int textlen) {
@ -21171,6 +21071,155 @@ salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
}
}
/*
* Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
*
* If 'salt' is NULL, a match is found if the salt has the requested length,
* otherwise the NSEC3 salt must match the requested salt value too.
*
* Returns ISC_R_SUCCESS, if a match is found, or an error if no match is
* found, or if the db lookup failed.
*/
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;
dns_dbversion_t *version = NULL;
dns_rdataset_t rdataset;
dns_rdata_nsec3param_t nsec3param;
dns_rdata_t rdata = DNS_RDATA_INIT;
REQUIRE(DNS_ZONE_VALID(zone));
dns_rdataset_init(&rdataset);
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
if (zone->db != NULL) {
dns_db_attach(zone->db, &db);
}
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
if (db == NULL) {
goto setparam;
}
result = dns_db_findnode(db, &zone->origin, false, &node);
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_ERROR,
"nsec3param lookup failure: %s",
dns_result_totext(result));
goto setparam;
}
dns_db_currentversion(db, &version);
result = dns_db_findrdataset(db, node, version,
dns_rdatatype_nsec3param,
dns_rdatatype_none, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS) {
INSIST(!dns_rdataset_isassociated(&rdataset));
if (result != ISC_R_NOTFOUND) {
dns_zone_log(zone, ISC_LOG_ERROR,
"nsec3param lookup failure: %s",
dns_result_totext(result));
}
goto setparam;
}
for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
result = dns_rdataset_next(&rdataset))
{
dns_rdataset_current(&rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
INSIST(result == ISC_R_SUCCESS);
dns_rdata_reset(&rdata);
/* Check parameters. */
if (nsec3param.hash != lookup->hash) {
continue;
}
if (nsec3param.iterations != lookup->iterations) {
continue;
}
if (nsec3param.salt_length != lookup->salt_length) {
continue;
}
if (lookup->salt != NULL) {
if (memcmp(nsec3param.salt, lookup->salt,
lookup->salt_length) != 0) {
continue;
}
}
/* Found a match. */
result = ISC_R_SUCCESS;
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);
}
if (dns_rdataset_isassociated(&rdataset)) {
dns_rdataset_disassociate(&rdataset);
}
if (node != NULL) {
dns_db_detachnode(db, &node);
}
if (version != NULL) {
dns_db_closeversion(db, &version, false);
}
if (db != NULL) {
dns_db_detach(&db);
}
return (result);
}
/*
* 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, &param,
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(&param.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, &param,
@ -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);
}
}

View file

@ -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 */

View file

@ -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