From cdafea5f1229496341a3d22ab33c8a205840fd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicki=20K=C5=99=C3=AD=C5=BEek?= Date: Mon, 8 Jun 2026 15:19:22 +0000 Subject: [PATCH] Add mixed DS test to dnssec_py Rewrite dnssec_unsupported_ds/tests_mixed_ds.py as dnssec_py/tests_mixed_ds.py using the isctest.zone helpers for zone setup. The test verifies that a zone whose DS RRset contains only an unsupported algorithm DS and a bogus DS record is treated as insecure by a validating resolver, resulting in SERVFAIL for queries to that zone. The DS set for child.mixed-ds. is deliberately corrupted after signing to contain a DS record with an unsupported algorithm (12) and a DS record with an invalid digest, exercising the mixed-DS insecurity proof path. Assisted-by: Claude:claude-opus-4-8 --- bin/tests/system/dnssec_py/tests_mixed_ds.py | 72 +++++++++++++++++++ .../dnssec_unsupported_ds/ns1/named.conf.j2 | 25 ------- .../system/dnssec_unsupported_ds/ns1/sign.sh | 37 ---------- .../ns1/zones/root.db.in | 5 -- .../dnssec_unsupported_ds/ns2/named.conf.j2 | 34 --------- .../system/dnssec_unsupported_ds/ns2/sign.sh | 35 --------- .../ns2/zones/example.db.in | 5 -- .../dnssec_unsupported_ds/ns3/named.conf.j2 | 34 --------- .../system/dnssec_unsupported_ds/ns3/sign.sh | 32 --------- .../ns3/zones/child.example.db.in | 7 -- .../dnssec_unsupported_ds/ns4/named.conf.j2 | 29 -------- .../system/dnssec_unsupported_ds/setup.sh | 32 --------- .../dnssec_unsupported_ds/tests_mixed_ds.py | 36 ---------- 13 files changed, 72 insertions(+), 311 deletions(-) create mode 100644 bin/tests/system/dnssec_py/tests_mixed_ds.py delete mode 100644 bin/tests/system/dnssec_unsupported_ds/ns1/named.conf.j2 delete mode 100755 bin/tests/system/dnssec_unsupported_ds/ns1/sign.sh delete mode 100644 bin/tests/system/dnssec_unsupported_ds/ns1/zones/root.db.in delete mode 100644 bin/tests/system/dnssec_unsupported_ds/ns2/named.conf.j2 delete mode 100755 bin/tests/system/dnssec_unsupported_ds/ns2/sign.sh delete mode 100644 bin/tests/system/dnssec_unsupported_ds/ns2/zones/example.db.in delete mode 100644 bin/tests/system/dnssec_unsupported_ds/ns3/named.conf.j2 delete mode 100755 bin/tests/system/dnssec_unsupported_ds/ns3/sign.sh delete mode 100644 bin/tests/system/dnssec_unsupported_ds/ns3/zones/child.example.db.in delete mode 100644 bin/tests/system/dnssec_unsupported_ds/ns4/named.conf.j2 delete mode 100755 bin/tests/system/dnssec_unsupported_ds/setup.sh delete mode 100644 bin/tests/system/dnssec_unsupported_ds/tests_mixed_ds.py diff --git a/bin/tests/system/dnssec_py/tests_mixed_ds.py b/bin/tests/system/dnssec_py/tests_mixed_ds.py new file mode 100644 index 0000000000..a3c9d43845 --- /dev/null +++ b/bin/tests/system/dnssec_py/tests_mixed_ds.py @@ -0,0 +1,72 @@ +# 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. + +from re import compile as Re + +from dnssec_py.common import DNSSEC_PY_MARK +from isctest.template import NS2, NS3, zones +from isctest.vars.algorithms import Algorithm +from isctest.zone import Zone, configure_root + +import isctest + +pytestmark = DNSSEC_PY_MARK + + +def modify_dsset(): + with open("ns3/dsset-child.mixed-ds.", encoding="utf-8") as dsset_file: + ds_orig = dsset_file.readline() + + alg = Algorithm.default().number + alg_re = Re(rf"\s+{alg}\s+") + ds_unsupported = alg_re.sub(" 12 ", ds_orig) + + digest_re = Re(rf"\s+{alg}\s+2\s+.*") + ds_bogus = digest_re.sub( + f" {alg} 2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + ds_orig, + ) + + with open("ns3/dsset-child.mixed-ds.", "w", encoding="utf-8") as dsset_file: + dsset_file.writelines([ds_unsupported, ds_bogus]) + + +def bootstrap(): + child = Zone("child.mixed-ds", NS3, signed=True) + child.configure() + + isctest.log.info( + "child.mixed-ds: modify DS set to have unsupported and bogus DS records" + ) + modify_dsset() + + mixed_ds = Zone("mixed-ds", NS2, signed=True) + mixed_ds.delegations = [child] + mixed_ds.configure() + + root = configure_root([mixed_ds]) + + return { + "trust_anchors": root.trust_anchors(), + "zones": zones([root, mixed_ds, child]), + } + + +def test_mixed_ds(ns9): + msg = isctest.query.create("child.mixed-ds.", "DNSKEY") + with ns9.watch_log_from_here() as watcher: + res = isctest.query.tcp(msg, ns9.ip) + watcher.wait_for_line("child.mixed-ds/DNSKEY: insecurity proof failed") + isctest.check.servfail(res) + + msg = isctest.query.create("a.child.mixed-ds.", "A") + res = isctest.query.tcp(msg, ns9.ip) + isctest.check.servfail(res) diff --git a/bin/tests/system/dnssec_unsupported_ds/ns1/named.conf.j2 b/bin/tests/system/dnssec_unsupported_ds/ns1/named.conf.j2 deleted file mode 100644 index 95bc334d94..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns1/named.conf.j2 +++ /dev/null @@ -1,25 +0,0 @@ -// NS1 - -options { - query-source address 10.53.0.1; - notify-source 10.53.0.1; - transfer-source 10.53.0.1; - port @PORT@; - pid-file "named.pid"; - listen-on { 10.53.0.1; }; - listen-on-v6 { none; }; - minimal-any no; - minimal-responses no; - recursion no; - notify yes; - dnssec-validation yes; - /* test that we can turn off trust-anchor-telemetry */ - trust-anchor-telemetry no; -}; - -zone "." { - type primary; - file "zones/root.db.signed"; -}; - -include "trusted.conf"; diff --git a/bin/tests/system/dnssec_unsupported_ds/ns1/sign.sh b/bin/tests/system/dnssec_unsupported_ds/ns1/sign.sh deleted file mode 100755 index ac42bb859d..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns1/sign.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -e - -# 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. - -# shellcheck source=conf.sh -. ../../conf.sh - -set -e - -echo_i "ns1/sign.sh" - -zone=. - -mkdir -p keys -ksk=$("$KEYGEN" -K keys -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "${zone}") -zsk=$("$KEYGEN" -K keys -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "${zone}") - -cat "zones/root.db.in" "keys/$ksk.key" "keys/$zsk.key" ../ns2/dsset-example. >"zones/root.db" - -"$SIGNER" -S -K "keys" \ - -o . \ - -f "zones/root.db.signed" \ - "zones/root.db" >/dev/null 2>&1 - -keyfile_to_static_ds "keys/$ksk" >trusted.conf -cp trusted.conf ../ns2/trusted.conf -cp trusted.conf ../ns3/trusted.conf -cp trusted.conf ../ns4/trusted.conf diff --git a/bin/tests/system/dnssec_unsupported_ds/ns1/zones/root.db.in b/bin/tests/system/dnssec_unsupported_ds/ns1/zones/root.db.in deleted file mode 100644 index fc01c377e7..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns1/zones/root.db.in +++ /dev/null @@ -1,5 +0,0 @@ -. 300 IN SOA gson.nominum.com. a.root.servers.nil. 2000042100 600 600 1200 600 -ns2.example. 300 IN A 10.53.0.2 -example. 300 IN NS ns2.example. -a.root-servers.nil. 300 IN A 10.53.0.1 -. 300 IN NS a.root-servers.nil. diff --git a/bin/tests/system/dnssec_unsupported_ds/ns2/named.conf.j2 b/bin/tests/system/dnssec_unsupported_ds/ns2/named.conf.j2 deleted file mode 100644 index 714d5319b5..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns2/named.conf.j2 +++ /dev/null @@ -1,34 +0,0 @@ -// NS2 - -options { - query-source address 10.53.0.2; - notify-source 10.53.0.2; - transfer-source 10.53.0.2; - port @PORT@; - pid-file "named.pid"; - listen-on { 10.53.0.2; }; - listen-on-v6 { none; }; - recursion no; - dnssec-validation yes; -}; - -key rndc_key { - secret "1234abcd8765"; - algorithm @DEFAULT_HMAC@; -}; - -controls { - inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; -}; - -zone "." { - type hint; - file "../../_common/root.hint"; -}; - -zone "example." { - type primary; - file "zones/example.db.signed"; -}; - -include "trusted.conf"; diff --git a/bin/tests/system/dnssec_unsupported_ds/ns2/sign.sh b/bin/tests/system/dnssec_unsupported_ds/ns2/sign.sh deleted file mode 100755 index 8bfd0dd939..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns2/sign.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh -e - -# 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. - -# shellcheck source=conf.sh -. ../../conf.sh - -set -e - -echo_i "ns2/sign.sh" - -zone=example. - -mkdir -p keys -ksk=$("$KEYGEN" -K keys -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "${zone}") -zsk=$("$KEYGEN" -K keys -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "${zone}") - -cat "zones/${zone}db.in" "keys/$ksk.key" "keys/$zsk.key" >"zones/${zone}db" - -<"../ns3/dsset-child.${zone}" sed -E "s/[[:space:]]+$DEFAULT_ALGORITHM_NUMBER[[:space:]]+/ 12 /" >>"zones/${zone}db" -<"../ns3/dsset-child.${zone}" sed -E "s/[[:space:]]+$DEFAULT_ALGORITHM_NUMBER[[:space:]]+2[[:space:]]+.*/ $DEFAULT_ALGORITHM_NUMBER 2 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/" >>"zones/${zone}db" - -"$SIGNER" -S -K "keys" \ - -o "${zone}" \ - -f "zones/${zone}db.signed" \ - "zones/${zone}db" >/dev/null 2>&1 diff --git a/bin/tests/system/dnssec_unsupported_ds/ns2/zones/example.db.in b/bin/tests/system/dnssec_unsupported_ds/ns2/zones/example.db.in deleted file mode 100644 index eaf7ee143b..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns2/zones/example.db.in +++ /dev/null @@ -1,5 +0,0 @@ -example. 300 IN SOA ns1.example. admin.example. 2026021901 3600 900 86400 300 -ns1.example. 300 IN A 10.53.0.2 -ns1.child.example. 300 IN A 10.53.0.3 -child.example. 300 IN NS ns1.child.example. -example. 300 IN NS ns1.example. diff --git a/bin/tests/system/dnssec_unsupported_ds/ns3/named.conf.j2 b/bin/tests/system/dnssec_unsupported_ds/ns3/named.conf.j2 deleted file mode 100644 index 9da5b55970..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns3/named.conf.j2 +++ /dev/null @@ -1,34 +0,0 @@ -// NS3 - -options { - query-source address 10.53.0.3; - notify-source 10.53.0.3; - transfer-source 10.53.0.3; - port @PORT@; - pid-file "named.pid"; - listen-on { 10.53.0.3; }; - listen-on-v6 { none; }; - recursion no; - dnssec-validation yes; -}; - -key rndc_key { - secret "1234abcd8765"; - algorithm @DEFAULT_HMAC@; -}; - -controls { - inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; -}; - -zone "." { - type hint; - file "../../_common/root.hint"; -}; - -zone "child.example." { - type primary; - file "zones/child.example.db.signed"; -}; - -include "trusted.conf"; diff --git a/bin/tests/system/dnssec_unsupported_ds/ns3/sign.sh b/bin/tests/system/dnssec_unsupported_ds/ns3/sign.sh deleted file mode 100755 index 08a5c797e6..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns3/sign.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -e - -# 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. - -# shellcheck source=conf.sh -. ../../conf.sh - -set -e - -echo_i "ns3/sign.sh" - -zone=child.example. - -mkdir -p keys -ksk=$("$KEYGEN" -K keys -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -f KSK "${zone}") -zsk=$("$KEYGEN" -K keys -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "${zone}") - -cat "zones/${zone}db.in" "keys/$ksk.key" "keys/$zsk.key" >"zones/${zone}db" - -"$SIGNER" -S -K "keys" \ - -o "${zone}" \ - -f "zones/${zone}db.signed" \ - "zones/${zone}db" >/dev/null 2>&1 diff --git a/bin/tests/system/dnssec_unsupported_ds/ns3/zones/child.example.db.in b/bin/tests/system/dnssec_unsupported_ds/ns3/zones/child.example.db.in deleted file mode 100644 index 51515ded18..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns3/zones/child.example.db.in +++ /dev/null @@ -1,7 +0,0 @@ -child.example. 300 IN SOA ns1.child.example. admin.child.example. 2026021901 3600 900 86400 300 -api.child.example. 300 IN A 192.0.2.102 -child.example. 300 IN MX 10 mail.child.example. -mail.child.example. 300 IN A 192.0.2.101 -www.child.example. 300 IN A 192.0.2.100 -ns1.child.example. 300 IN A 10.53.0.3 -child.example. 300 IN NS ns1.child.example. diff --git a/bin/tests/system/dnssec_unsupported_ds/ns4/named.conf.j2 b/bin/tests/system/dnssec_unsupported_ds/ns4/named.conf.j2 deleted file mode 100644 index 8afe4936e6..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/ns4/named.conf.j2 +++ /dev/null @@ -1,29 +0,0 @@ -// NS4 - -options { - query-source address 10.53.0.4; - notify-source 10.53.0.4; - transfer-source 10.53.0.4; - port @PORT@; - pid-file "named.pid"; - listen-on { 10.53.0.4; }; - listen-on-v6 { none; }; - recursion yes; - dnssec-validation yes; -}; - -key rndc_key { - secret "1234abcd8765"; - algorithm @DEFAULT_HMAC@; -}; - -controls { - inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; -}; - -zone "." { - type hint; - file "../../_common/root.hint"; -}; - -include "trusted.conf"; diff --git a/bin/tests/system/dnssec_unsupported_ds/setup.sh b/bin/tests/system/dnssec_unsupported_ds/setup.sh deleted file mode 100755 index 3b40ffc5bd..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/setup.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -e - -# 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. - -# shellcheck source=conf.sh -. ../conf.sh - -set -e - -( - cd ns3 - $SHELL sign.sh -) - -( - cd ns2 - $SHELL sign.sh -) - -( - cd ns1 - $SHELL sign.sh -) diff --git a/bin/tests/system/dnssec_unsupported_ds/tests_mixed_ds.py b/bin/tests/system/dnssec_unsupported_ds/tests_mixed_ds.py deleted file mode 100644 index e1cf82c132..0000000000 --- a/bin/tests/system/dnssec_unsupported_ds/tests_mixed_ds.py +++ /dev/null @@ -1,36 +0,0 @@ -# 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. - -import pytest - -import isctest - -pytestmark = pytest.mark.extra_artifacts( - [ - "ns*/dsset-*", - "ns*/keys", - "ns*/keys/*.key", - "ns*/keys/*.private", - "ns*/trusted.conf", - "ns*/zones/*.db", - "ns*/zones/*.db.signed", - ] -) - - -def test_mixed_ds(): - msg = isctest.query.create("child.example.", "DNSKEY") - res = isctest.query.tcp(msg, "10.53.0.4") - isctest.check.servfail(res) - - msg = isctest.query.create("child.example.", "A") - res = isctest.query.tcp(msg, "10.53.0.4") - isctest.check.servfail(res)