2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-29 05:28:00 +00:00

dnssec-signzone -Z none removes ZONEMD records

"dnssec-signzone -Z none" removes pre-existing ZONEMD records from a
signed zone. If followed by another -Z option, a new ZONEMD record
will be added to replace the existing ones. This can be used, for
instance, to switch from one scheme/digest to the other.
This commit is contained in:
Evan Hunt 2025-08-27 11:45:11 -07:00
parent fcbd4bea02
commit 8db40614c4
3 changed files with 92 additions and 22 deletions

View File

@ -173,7 +173,9 @@ static bool set_maxttl = false;
static dns_ttl_t maxttl = 0; static dns_ttl_t maxttl = 0;
static bool no_max_check = false; static bool no_max_check = false;
static const char *sync_records = "cdnskey,cds:sha-256"; static const char *sync_records = "cdnskey,cds:sha-256";
uint8_t zonemd_scheme[2] = { 0 }, zonemd_digest[2] = { 0 };
static bool add_zonemd = false; static bool add_zonemd = false;
static bool del_zonemd = false;
#define INCSTAT(counter) \ #define INCSTAT(counter) \
if (printstats) { \ if (printstats) { \
@ -1963,7 +1965,7 @@ addnsec3param(const unsigned char *salt, size_t salt_len,
if (result == DNS_R_UNCHANGED) { if (result == DNS_R_UNCHANGED) {
result = ISC_R_SUCCESS; result = ISC_R_SUCCESS;
} }
check_result(result, "dddnsec3param: dns_db_deleterdataset()"); check_result(result, "addnsec3param: dns_db_deleterdataset()");
result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset, result = dns_db_addrdataset(gdb, node, gversion, 0, &rdataset,
DNS_DBADD_MERGE, NULL); DNS_DBADD_MERGE, NULL);
@ -2217,6 +2219,35 @@ addzonemd(uint8_t scheme, uint8_t digest_type) {
dns_db_detachnode(&node); dns_db_detachnode(&node);
} }
static void
setup_zonemd(void) {
if (del_zonemd) {
/* Delete any current ZONEMD records.*/
isc_result_t result;
dns_dbnode_t *node = NULL;
result = dns_db_getoriginnode(gdb, &node);
check_result(result, "dns_db_getoriginnode()");
result = dns_db_deleterdataset(gdb, node, gversion,
dns_rdatatype_zonemd, 0);
dns_db_detachnode(&node);
if (result == DNS_R_UNCHANGED) {
result = ISC_R_SUCCESS;
}
check_result(result, "dns_db_deleterdataset()");
}
if (add_zonemd) {
for (size_t i = 0; i < ARRAY_SIZE(zonemd_scheme); i++) {
if (zonemd_scheme[i] != 0) {
addzonemd(zonemd_scheme[i], zonemd_digest[i]);
}
}
}
}
static void static void
rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset, dns_diff_t *add, rrset_cleanup(dns_name_t *name, dns_rdataset_t *rdataset, dns_diff_t *add,
dns_diff_t *del) { dns_diff_t *del) {
@ -3389,7 +3420,6 @@ main(int argc, char *argv[]) {
bool set_optout = false; bool set_optout = false;
bool set_iter = false; bool set_iter = false;
bool nonsecify = false; bool nonsecify = false;
uint8_t zonemd_scheme[2] = { 0 }, zonemd_digest[2] = { 0 };
atomic_init(&shuttingdown, false); atomic_init(&shuttingdown, false);
atomic_init(&finished, false); atomic_init(&finished, false);
@ -3685,13 +3715,17 @@ main(int argc, char *argv[]) {
break; break;
case 'Z': case 'Z':
add_zonemd = true; if (strcasecmp(isc_commandline_argument, "none") == 0) {
if (strcasecmp(isc_commandline_argument, del_zonemd = true;
"simple-sha384") == 0 || memset(zonemd_scheme, 0, sizeof(zonemd_scheme));
strcasecmp(isc_commandline_argument, "sha384") == memset(zonemd_digest, 0, sizeof(zonemd_digest));
0 || } else if (strcasecmp(isc_commandline_argument,
strcmp(isc_commandline_argument, "-") == 0) "simple-sha384") == 0 ||
strcasecmp(isc_commandline_argument,
"sha384") == 0 ||
strcmp(isc_commandline_argument, "-") == 0)
{ {
add_zonemd = true;
for (size_t i = 0; for (size_t i = 0;
i < ARRAY_SIZE(zonemd_scheme); i++) i < ARRAY_SIZE(zonemd_scheme); i++)
{ {
@ -3713,6 +3747,7 @@ main(int argc, char *argv[]) {
strcasecmp(isc_commandline_argument, strcasecmp(isc_commandline_argument,
"sha512") == 0) "sha512") == 0)
{ {
add_zonemd = true;
for (size_t i = 0; for (size_t i = 0;
i < ARRAY_SIZE(zonemd_scheme); i++) i < ARRAY_SIZE(zonemd_scheme); i++)
{ {
@ -4043,13 +4078,8 @@ main(int argc, char *argv[]) {
/* Remove duplicates and cap TTLs at maxttl */ /* Remove duplicates and cap TTLs at maxttl */
cleanup_zone(); cleanup_zone();
if (add_zonemd) { /* Set up ZONEMD records */
for (size_t i = 0; i < ARRAY_SIZE(zonemd_scheme); i++) { setup_zonemd();
if (zonemd_scheme[i] != 0) {
addzonemd(zonemd_scheme[i], zonemd_digest[i]);
}
}
}
if (!nonsecify) { if (!nonsecify) {
if (IS_NSEC3) { if (IS_NSEC3) {

View File

@ -403,13 +403,17 @@ Options
.. option:: -Z method .. option:: -Z method
This option causes a ZONEMD record to be added to the signed zone, This option causes a ZONEMD record to be added to, or removed from,
if there wasn't a ZONEMD already present. The ``method`` parameter the signed zone. The ``method`` parameter indicates the scheme and
indicates the scheme and digest type to use: valid options are digest type to use: valid options are ``simple-sha384`` (or
``simple-sha384`` (or ``sha384``, or ``-``) for scheme SIMPLE ``sha384``, or ``-``) for scheme SIMPLE and digest type SHA384,
and digest type SHA384, and ``simple-sha512`` (or ``sha512``) and ``simple-sha512`` (or ``sha512``) for scheme SIMPLE and digest
for scheme SIMPLE and digest type SHA512. Multiple ``-Z`` options type SHA512. ``-Z none`` removes all ZONEMD records.
can be used simultaneously to add multiple ZONEMD records.
Multiple ``-Z`` options can be used simultaneously, and are processed
in order. This allows multiple ZONEMD records to be added with a single
command, or (by specifying ``none`` first) existing ZONEMD records to
be removed and replaced.
.. option:: zonefile .. option:: zonefile

View File

@ -279,6 +279,42 @@ n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed" test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret)) status=$((status + ret))
echo_ic "check that dnssec-signzone -Z none removes ZONEMD records ($n)"
ret=0
(
cd signer/general || exit 1
rm -f signed.zone
$SIGNER -Z none -f signed.zone -o example.com. test14.zone >signer.out.$n
count=$(grep -c "ZONEMD.90000 1 1 " signed.zone)
test $count -eq 1 && exit 1
count=$(grep -c "ZONEMD.90000 1 2 " signed.zone)
test $count -eq 1 && exit 1
count=$(grep -c "RRSIG.ZONEMD" signed.zone)
test $count -eq 1 && exit 1
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 -Z none -Z - keeps one ZONEMD record ($n)"
ret=0
(
cd signer/general || exit 1
rm -f signed.zone
$SIGNER -Z none -Z - -f signed.zone -o example.com. test14.zone >signer.out.$n
count=$(grep -c "ZONEMD.90000 1 1 " signed.zone)
test $count -eq 1 || exit 1
count=$(grep -c "ZONEMD.90000 1 2 " signed.zone)
test $count -eq 1 && exit 1
count=$(grep -c "RRSIG.ZONEMD" signed.zone)
test $count -eq 1 || exit 1
test -f signed.zone
) || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
get_default_algorithm_key_ids_from_sigs() { get_default_algorithm_key_ids_from_sigs() {
zone=$1 zone=$1