mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 12:10:00 -04:00
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:
parent
6b5d7357df
commit
64db30942d
8 changed files with 563 additions and 148 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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] = {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ check_PROGRAMS = \
|
|||
keytable_test \
|
||||
name_test \
|
||||
nsec3_test \
|
||||
nsec3param_test \
|
||||
peer_test \
|
||||
private_test \
|
||||
rbt_serialize_test \
|
||||
|
|
|
|||
302
lib/dns/tests/nsec3param_test.c
Normal file
302
lib/dns/tests/nsec3param_test.c
Normal 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, ¶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 <stdio.h>
|
||||
|
||||
int
|
||||
main(void) {
|
||||
printf("1..0 # Skipped: cmocka not available\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* if HAVE_CMOCKA */
|
||||
73
lib/dns/tests/testdata/nsec3param/nsec3.db.signed
vendored
Normal file
73
lib/dns/tests/testdata/nsec3param/nsec3.db.signed
vendored
Normal 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== )
|
||||
320
lib/dns/zone.c
320
lib/dns/zone.c
|
|
@ -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, ¶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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue