From b8cb65db93a3daeb01f55d157580f492ded066fa Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Tue, 9 Dec 2025 16:52:44 -0800 Subject: [PATCH 1/2] use the zone file's basename as origin in dnssec tools In dnssec-signzone and dnssec-verify, if the zone origin is not specified using the `-o` parameter, the default behavior is to try to use the zone's file name as the origin. So, for example, `dnssec-signzone -S example.com` or 'dnssec-verify example.com' will work, so long as the file name matches the zone name. This now also works if the zone is in a different directory. For example, `dnssec-signzone -S zones/example.com` or 'dnssec-verify zones/example.com' will set the origin value to `example.com`. --- bin/dnssec/dnssec-signzone.c | 10 ++++++---- bin/dnssec/dnssec-verify.c | 22 +++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index bd54700c0e..f16fcbf636 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -2451,7 +2451,8 @@ nsec3ify(unsigned int hashalg, dns_iterations_t iterations, * Load the zone file from disk */ static void -loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { +loadzone(char *file, const char *origin, dns_rdataclass_t rdclass, + dns_db_t **db) { isc_buffer_t b; int len; dns_fixedname_t fname; @@ -2459,7 +2460,7 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { isc_result_t result; len = strlen(origin); - isc_buffer_init(&b, origin, len); + isc_buffer_constinit(&b, origin, len); isc_buffer_add(&b, len); name = dns_fixedname_initname(&fname); @@ -3212,7 +3213,8 @@ main(int argc, char *argv[]) { int ch; char *startstr = NULL, *endstr = NULL, *classname = NULL; char *dnskey_endstr = NULL; - char *origin = NULL, *file = NULL, *output = NULL; + const char *origin = NULL; + char *file = NULL, *output = NULL; char *inputformatstr = NULL, *outputformatstr = NULL; char *serialformatstr = NULL; char *dskeyfile[MAXDSKEYS]; @@ -3612,7 +3614,7 @@ main(int argc, char *argv[]) { argv += 1; if (origin == NULL) { - origin = file; + origin = isc_file_basename(file); } if (output == NULL) { diff --git a/bin/dnssec/dnssec-verify.c b/bin/dnssec/dnssec-verify.c index c4950da389..0aea7802b2 100644 --- a/bin/dnssec/dnssec-verify.c +++ b/bin/dnssec/dnssec-verify.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -89,7 +90,8 @@ report(const char *format, ...) { * Load the zone file from disk */ static void -loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { +loadzone(char *file, const char *origin, bool origin_is_file, + dns_rdataclass_t rdclass, dns_db_t **db) { isc_buffer_t b; int len; dns_fixedname_t fname; @@ -97,7 +99,7 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { isc_result_t result; len = strlen(origin); - isc_buffer_init(&b, origin, len); + isc_buffer_constinit(&b, origin, len); isc_buffer_add(&b, len); name = dns_fixedname_initname(&fname); @@ -117,12 +119,7 @@ loadzone(char *file, char *origin, dns_rdataclass_t rdclass, dns_db_t **db) { case ISC_R_SUCCESS: break; case DNS_R_NOTZONETOP: - /* - * Comparing pointers (vs. using strcmp()) is intentional: we - * want to check whether -o was supplied on the command line, - * not whether origin and file contain the same string. - */ - if (origin == file) { + if (origin_is_file) { fatal("failed loading zone '%s' from file '%s': " "use -o to specify a different zone origin", origin, file); @@ -164,13 +161,15 @@ usage(int ret) { int main(int argc, char *argv[]) { - char *origin = NULL, *file = NULL; + const char *origin = NULL; + char *file = NULL; char *inputformatstr = NULL; isc_result_t result; char *classname = NULL; dns_rdataclass_t rdclass; char *endp; int ch; + bool origin_is_file = false; isc_commandline_init(argc, argv); @@ -295,7 +294,8 @@ main(int argc, char *argv[]) { POST(argv); if (origin == NULL) { - origin = file; + origin = isc_file_basename(file); + origin_is_file = true; } if (inputformatstr != NULL) { @@ -310,7 +310,7 @@ main(int argc, char *argv[]) { gdb = NULL; report("Loading zone '%s' from file '%s'\n", origin, file); - loadzone(file, origin, rdclass, &gdb); + loadzone(file, origin, origin_is_file, rdclass, &gdb); if (journal != NULL) { loadjournal(isc_g_mctx, gdb, journal); } From 1251ae896c06c1a2e8c7953042f859847dacfa6b Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Wed, 1 Apr 2026 11:11:55 +0200 Subject: [PATCH 2/2] Test dnssec tools using zone file basename as origin Add test cases where dnssec-signzone and dnssec-verify use the zone file's basename as the origin when '-o' is omitted. --- .../dnssectools/signer/general/test13.zone | 17 +++++++++ bin/tests/system/dnssectools/tests.sh | 36 +++++++++++++++++++ .../dnssectools/tests_sh_dnssectools.py | 7 ++++ 3 files changed, 60 insertions(+) create mode 100644 bin/tests/system/dnssectools/signer/general/test13.zone diff --git a/bin/tests/system/dnssectools/signer/general/test13.zone b/bin/tests/system/dnssectools/signer/general/test13.zone new file mode 100644 index 0000000000..3f2c7207f3 --- /dev/null +++ b/bin/tests/system/dnssectools/signer/general/test13.zone @@ -0,0 +1,17 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; 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. + +; 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 diff --git a/bin/tests/system/dnssectools/tests.sh b/bin/tests/system/dnssectools/tests.sh index 85cd1ac2a6..f8e836c8ec 100644 --- a/bin/tests/system/dnssectools/tests.sh +++ b/bin/tests/system/dnssectools/tests.sh @@ -789,6 +789,42 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) +echo_i "checking dnssec-signzone without -o and zone is in directory (incorrect basename) ($n)" +ret=0 +cp signer/general/test13.zone signer/bad.db +$SIGNER -O full -S signer/bad.db 2>signer.err.$n && ret=1 +grep "example.com: not at top of zone" signer.err.$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-signzone without -o and zone is in directory ($n)" +ret=0 +cp signer/general/test13.zone signer/example.com +$SIGNER -S -K signer/general -O full signer/example.com >signer.out.$n || ret=1 +test -f signer/example.com.signed +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-verify without -o and zone is in directory (incorrect basename) ($n)" +ret=0 +$VERIFY signer/example.com.signed 2>verify.err.$n && ret=1 +grep "example.com: not at top of zone" verify.err.$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + +echo_i "checking dnssec-verify without -o and zone is in directory ($n)" +ret=0 +cp signer/example.com.signed signer/example.com +$VERIFY signer/example.com >verify.out.$n || ret=1 +grep "Loading zone 'example.com' from file 'signer/example.com'" verify.out.$n >/dev/null || ret=1 +grep "Zone fully signed" verify.out.$n >/dev/null || ret=1 +n=$((n + 1)) +test "$ret" -eq 0 || echo_i "failed" +status=$((status + ret)) + echo_i "check that RRSIGs are correctly removed from apex when RRset is removed NSEC ($n)" ret=0 # generate signed zone with MX and AAAA records at apex. diff --git a/bin/tests/system/dnssectools/tests_sh_dnssectools.py b/bin/tests/system/dnssectools/tests_sh_dnssectools.py index 6ab8993543..fe70cf52c4 100644 --- a/bin/tests/system/dnssectools/tests_sh_dnssectools.py +++ b/bin/tests/system/dnssectools/tests_sh_dnssectools.py @@ -22,6 +22,13 @@ pytestmark = pytest.mark.extra_artifacts( "*/K*", "*/dsset-*", "*/*.signed", + "dsset-*", + "signer.err.*", + "signer.out.*", + "verify.err.*", + "verify.out.*", + "signer/bad.db", + "signer/example.com", "signer/example.db", "signer/example.db.after", "signer/example.db.before",