From e43e4bd20a99860e79294afbcc9b75f01ff28c26 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 26 Mar 2026 13:10:45 +1100 Subject: [PATCH 1/2] Use the correct maximal compressed bit map buffer size There are up to 256 windows in a NSEC/NSEC3 compressed bit map of 32 + 2 octets each. --- lib/dns/include/dns/nsec.h | 7 ++++++- lib/dns/zoneverify.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/dns/include/dns/nsec.h b/lib/dns/include/dns/nsec.h index eda6214bb1..ebb1c65a43 100644 --- a/lib/dns/include/dns/nsec.h +++ b/lib/dns/include/dns/nsec.h @@ -21,7 +21,12 @@ #include #include -#define DNS_NSEC_BUFFERSIZE (DNS_NAME_MAXWIRE + 8192 + 512) +/* + * max compressed bitmap size: + * 256 windows * (window number + window length + bitmap (max 256 bits)) + */ +#define DNS_NSEC_MAXCBMSIZE (256 * ((256 / 8) + 2)) +#define DNS_NSEC_BUFFERSIZE (DNS_NAME_MAXWIRE + DNS_NSEC_MAXCBMSIZE) isc_result_t dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node, diff --git a/lib/dns/zoneverify.c b/lib/dns/zoneverify.c index 70209432a2..70e21b4270 100644 --- a/lib/dns/zoneverify.c +++ b/lib/dns/zoneverify.c @@ -447,7 +447,7 @@ match_nsec3(const vctx_t *vctx, const dns_name_t *name, const unsigned char types[8192], unsigned int maxtype, const unsigned char *rawhash, size_t rhsize, isc_result_t *vresult) { - unsigned char cbm[8244]; + unsigned char cbm[DNS_NSEC_MAXCBMSIZE]; char namebuf[DNS_NAME_FORMATSIZE]; dns_rdata_nsec3_t nsec3; isc_result_t result; From e9a58de251e87227d573937d7838544a89c3091e Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 26 Mar 2026 13:05:18 +1100 Subject: [PATCH 2/2] Checking maximal sized compresses bit map works Add records that will be at end of each compressed bitmap less 1 of the NSEC3 record. Zone verification should still work. --- bin/tests/system/dnssectools/tests.sh | 29 +++++++++++++++++++ .../dnssectools/tests_sh_dnssectools.py | 1 + 2 files changed, 30 insertions(+) diff --git a/bin/tests/system/dnssectools/tests.sh b/bin/tests/system/dnssectools/tests.sh index f8e836c8ec..666c6ebe85 100644 --- a/bin/tests/system/dnssectools/tests.sh +++ b/bin/tests/system/dnssectools/tests.sh @@ -906,6 +906,35 @@ n=$((n + 1)) if [ "$ret" -ne 0 ]; then echo_i "failed"; fi status=$((status + ret)) +echo_i "checking maximal sized compresses bit map works ($n)" +ret=0 +( + cd signer || exit 0 + key1=$(${KEYGEN} -a "${DEFAULT_ALGORITHM}" -f KSK maxcbm.example) + key2=$(${KEYGEN} -a "${DEFAULT_ALGORITHM}" maxcbm.example) + cat >>maxcbm.example.db <>maxcbm.example.db + type=$((type + 256)) + done + "${SIGNER}" -3 - -o maxcbm.example maxcbm.example.db >signer.out.$n + "${CHECKZONE}" -q -D maxcbm.example maxcbm.example.db.signed \ + | grep '^M7L6E3AJUD7LRVUMMQS595OGHBMT4DFT.*NSEC3.*TYPE65534$' >/dev/null || ret=1 +) || ret=1 +n=$((n + 1)) +if [ "$ret" -ne 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + echo_i "check that 'dnssec-keygen -S' works for all supported algorithms ($n)" ret=0 alg=1 diff --git a/bin/tests/system/dnssectools/tests_sh_dnssectools.py b/bin/tests/system/dnssectools/tests_sh_dnssectools.py index fe70cf52c4..3837da290d 100644 --- a/bin/tests/system/dnssectools/tests_sh_dnssectools.py +++ b/bin/tests/system/dnssectools/tests_sh_dnssectools.py @@ -41,6 +41,7 @@ pytestmark = pytest.mark.extra_artifacts( "signer/general/signed.expect", "signer/general/signed.zone", "signer/general/signer.out.*", + "signer/maxcbm.example.db", "signer/nsec3param.out", "signer/prepub.db", "signer/revoke.example.db",