From: Evan Hunt Date: Fri, 27 Jun 2025 03:29:24 +0000 (-0700) Subject: convert dnssec validation tests to python X-Git-Tag: v9.21.11~13^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=950df056b354bd45cd29c3a709b1b0e1417a84d9;p=thirdparty%2Fbind9.git convert dnssec validation tests to python begin converting DNSSEC validation tests from shell to python, and simplify the name servers used in the test. ns4, the name server used for validation tests, is now configured using jinja2 templates. ns8, which was previously used for testing unsupported, disabled and revoked keys and trust anchors, has been removed. we now use a jinja2 configuration in ns5 for this purpose. the configurations in ns7 and ns6 didn't conflict with one another, so the two servers have been merged into one. --- diff --git a/bin/tests/system/dnssec/README b/bin/tests/system/dnssec/README index fcaa3b6c808..c72442c61be 100644 --- a/bin/tests/system/dnssec/README +++ b/bin/tests/system/dnssec/README @@ -19,14 +19,11 @@ ns4 is a caching-only server, configured with the correct trusted key for the root. ns5 is a caching-only server, configured with the an incorrect trusted -key for the root. It is used for testing failure cases. +key for the root, or with unsupported and disabled algorithms. It is used +for testing failure cases. -ns6 is an caching and authoritative server used for testing unusual -server behaviors such as disabled DNSSEC algorithms. - -ns7 is used for checking non-cacheable answers. - -ns8 is a caching-only server, configured with unsupported and disabled -algorithms. It is used for testing failure cases. +ns6 is a caching and authoritative server used for testing unusual +server behaviors such as disabled DNSSEC algorithms and non-cacheable +responses. It runs with -T nonearest, -T nosoa, and -T tat=3. ns9 is a forwarding-only server. diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh index bd434aeb809..02c9e18320c 100644 --- a/bin/tests/system/dnssec/ns1/sign.sh +++ b/bin/tests/system/dnssec/ns1/sign.sh @@ -22,7 +22,6 @@ zonefile=root.db (cd ../ns2 && $SHELL sign.sh) (cd ../ns6 && $SHELL sign.sh) -(cd ../ns7 && $SHELL sign.sh) echo_i "ns1/sign.sh" @@ -51,7 +50,6 @@ cp trusted.conf ../ns2/trusted.conf cp trusted.conf ../ns3/trusted.conf cp trusted.conf ../ns4/trusted.conf cp trusted.conf ../ns6/trusted.conf -cp trusted.conf ../ns7/trusted.conf cp trusted.conf ../ns9/trusted.conf keyfile_to_static_keys "$ksk" >trusted.keys diff --git a/bin/tests/system/dnssec/ns2/example.db.in b/bin/tests/system/dnssec/ns2/example.db.in index 1efb1755b40..c7251329881 100644 --- a/bin/tests/system/dnssec/ns2/example.db.in +++ b/bin/tests/system/dnssec/ns2/example.db.in @@ -9,7 +9,7 @@ ; See the COPYRIGHT file distributed with this work for additional ; information regarding copyright ownership. -$TTL 300 ; 5 minutes +$TTL 3600 ; 1 hour @ IN SOA mname1. . ( 2000042407 ; serial 20 ; refresh (20 seconds) @@ -106,6 +106,9 @@ ns.dnskey-unknown A 10.53.0.3 dnskey-unsupported NS ns.dnskey-unsupported ns.dnskey-unsupported A 10.53.0.3 +dnskey-unsupported-2 NS ns.dnskey-unsupported +ns.dnskey-unsupported-2 A 10.53.0.3 + ds-unsupported NS ns.ds-unsupported ns.ds-unsupported A 10.53.0.3 diff --git a/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in index a7792fd3b87..34006877b35 100644 --- a/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in +++ b/bin/tests/system/dnssec/ns3/auto-nsec.example.db.in @@ -34,7 +34,7 @@ insecure NS ns.insecure ns.insecure A 10.53.0.2 nosoa NS ns.nosoa -ns.nosoa A 10.53.0.7 +ns.nosoa A 10.53.0.6 normalthenrrsig A 10.0.0.28 rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in index a7792fd3b87..34006877b35 100644 --- a/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in +++ b/bin/tests/system/dnssec/ns3/auto-nsec3.example.db.in @@ -34,7 +34,7 @@ insecure NS ns.insecure ns.insecure A 10.53.0.2 nosoa NS ns.nosoa -ns.nosoa A 10.53.0.7 +ns.nosoa A 10.53.0.6 normalthenrrsig A 10.0.0.28 rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns3/expired.example.db.in b/bin/tests/system/dnssec/ns3/expired.example.db.in index b7706d3c9f1..eaee74b765c 100644 --- a/bin/tests/system/dnssec/ns3/expired.example.db.in +++ b/bin/tests/system/dnssec/ns3/expired.example.db.in @@ -9,7 +9,7 @@ ; See the COPYRIGHT file distributed with this work for additional ; information regarding copyright ownership. -$TTL 300 ; 5 minutes +$TTL 3600 ; 1 hour @ IN SOA mname1. . ( 2000042407 ; serial 20 ; refresh (20 seconds) @@ -36,7 +36,7 @@ insecure NS ns.insecure ns.insecure A 10.53.0.2 nosoa NS ns.nosoa -ns.nosoa A 10.53.0.7 +ns.nosoa A 10.53.0.6 normalthenrrsig A 10.0.0.28 rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns3/expiring.example.db.in b/bin/tests/system/dnssec/ns3/expiring.example.db.in index 8acf7b121ec..be3e6803544 100644 --- a/bin/tests/system/dnssec/ns3/expiring.example.db.in +++ b/bin/tests/system/dnssec/ns3/expiring.example.db.in @@ -9,7 +9,7 @@ ; See the COPYRIGHT file distributed with this work for additional ; information regarding copyright ownership. -$TTL 300 ; 5 minutes +$TTL 3600 ; 1 hour @ IN SOA mname1. . ( 2000042407 ; serial 20 ; refresh (20 seconds) diff --git a/bin/tests/system/dnssec/ns3/secure.example.db.in b/bin/tests/system/dnssec/ns3/secure.example.db.in index 9aebd980078..5859ebcdc5e 100644 --- a/bin/tests/system/dnssec/ns3/secure.example.db.in +++ b/bin/tests/system/dnssec/ns3/secure.example.db.in @@ -39,7 +39,7 @@ insecure NS ns2.insecure ns2.insecure A 10.53.0.2 nosoa NS ns.nosoa -ns.nosoa A 10.53.0.7 +ns.nosoa A 10.53.0.6 normalthenrrsig A 10.0.0.28 rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns3/sign.sh b/bin/tests/system/dnssec/ns3/sign.sh index 8cf46a2f06f..58da7378f03 100644 --- a/bin/tests/system/dnssec/ns3/sign.sh +++ b/bin/tests/system/dnssec/ns3/sign.sh @@ -53,7 +53,7 @@ for tld in managed trusted; do "$SIGNER" -z -3 - -o "$zone" -O full -f ${zonefile}.tmp "$zonefile" >/dev/null awk '$4 == "DNSKEY" { $7 = 255 } $4 == "RRSIG" { $6 = 255 } { print }' ${zonefile}.tmp >${zonefile}.signed - # Make trusted-keys and managed keys conf sections for ns8. + # Make trusted-keys and managed keys conf sections for ns5/many_anchors. mv ${keyname4}.key ${keyname4}.tmp awk '$1 == "unsupported.'"${tld}"'." { $6 = 255 } { print }' ${keyname4}.tmp >${keyname4}.key @@ -67,10 +67,10 @@ for tld in managed trusted; do case $tld in "managed") - keyfile_to_initial_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 >../ns8/managed.conf + keyfile_to_initial_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 >../ns5/many-managed.conf ;; "trusted") - keyfile_to_static_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 >../ns8/trusted.conf + keyfile_to_static_keys $keyname1 $keyname2 $keyname3 $keyname4 $keyname5 >../ns5/many-trusted.conf ;; esac done @@ -324,7 +324,7 @@ $DSFROMKEY -2 -A -f ${zonefile}.signed "$zone" | tail -1 >>"$DSFILE" # # A zone which is fine by itself (supported algorithm) but that is used -# to mimic unsupported DS digest (see ns8). +# to mimic unsupported DS digest (see ns5/many_anchors). # zone=ds-unsupported.example. infile=ds-unsupported.example.db.in diff --git a/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in index a7792fd3b87..34006877b35 100644 --- a/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in +++ b/bin/tests/system/dnssec/ns3/update-nsec3.example.db.in @@ -34,7 +34,7 @@ insecure NS ns.insecure ns.insecure A 10.53.0.2 nosoa NS ns.nosoa -ns.nosoa A 10.53.0.7 +ns.nosoa A 10.53.0.6 normalthenrrsig A 10.0.0.28 rrsigonly A 10.0.0.29 diff --git a/bin/tests/system/dnssec/ns4/named.conf.j2 b/bin/tests/system/dnssec/ns4/named.conf.j2 new file mode 100644 index 00000000000..9a67908bde0 --- /dev/null +++ b/bin/tests/system/dnssec/ns4/named.conf.j2 @@ -0,0 +1,119 @@ +/* + * 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. + */ + +// NS11 + + +{% set managed_key = managed_key | default(False) %} +{% set accept_expired = accept_expired | default(False) %} +{% set multi_view = multi_view | default(False) %} + +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; + minimal-responses no; + + {% if accept_expired %} + dnssec-accept-expired yes; + {% endif %} + + {% if managed_key %} + dnssec-validation auto; + bindkeys-file "managed.conf"; + {% else %} + # Note: We only reference the bind.keys file here to + # confirm that it is *not* being used. It contains the + # real root key, and we're using a local toy root zone for + # the tests, so it wouldn't work. But dnssec-validation + # is set to "yes" not "auto", so that won't matter. + dnssec-validation yes; + bindkeys-file "../../../../../bind.keys"; + {% endif %} + + disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; }; + disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384"; }; + disable-ds-digests "ds-unsupported.example." { "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; }; + disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; }; +}; + +{% if not managed_key %} +include "trusted.conf"; +{% endif %} + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +{% if multi_view %} + view rec { + match-recursive-only yes; + recursion yes; + dnssec-accept-expired yes; + minimal-responses no; + dnssec-validation yes; + + include "trusted.conf"; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone secure.example { + type static-stub; + server-addresses { 10.53.0.4; }; + }; + + zone insecure.secure.example { + type static-stub; + server-addresses { 10.53.0.4; }; + }; + }; + + view auth { + recursion no; + allow-recursion { none; }; + dnssec-validation no; + + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + zone secure.example { + type secondary; + primaries { 10.53.0.3; }; + }; + + zone insecure.secure.example { + type secondary; + primaries { 10.53.0.2; }; + }; + }; +{% else %} + zone "." { + type hint; + file "../../_common/root.hint"; + }; +{% endif %} diff --git a/bin/tests/system/dnssec/ns4/named1.conf.in b/bin/tests/system/dnssec/ns4/named1.conf.in deleted file mode 100644 index 66975a352af..00000000000 --- a/bin/tests/system/dnssec/ns4/named1.conf.in +++ /dev/null @@ -1,50 +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. - */ - -// 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; - minimal-responses no; - - # Note: We only reference the bind.keys file here to confirm that it - # is *not* being used. It contains the real root key, and we're - # using a local toy root zone for the tests, so it wouldn't work. - # But since dnssec-validation is set to "yes" not "auto", that - # won't matter. - dnssec-validation yes; - bindkeys-file "../../../../../bind.keys"; -}; - -include "trusted.conf"; - -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"; -}; diff --git a/bin/tests/system/dnssec/ns4/named2.conf.in b/bin/tests/system/dnssec/ns4/named2.conf.in deleted file mode 100644 index c8699834f33..00000000000 --- a/bin/tests/system/dnssec/ns4/named2.conf.in +++ /dev/null @@ -1,43 +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. - */ - -// 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; - minimal-responses no; - - dnssec-validation auto; - bindkeys-file "managed.conf"; -}; - -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"; -}; diff --git a/bin/tests/system/dnssec/ns4/named3.conf.in b/bin/tests/system/dnssec/ns4/named3.conf.in deleted file mode 100644 index 24012b38e72..00000000000 --- a/bin/tests/system/dnssec/ns4/named3.conf.in +++ /dev/null @@ -1,46 +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. - */ - -// 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; - minimal-responses no; - - dnssec-accept-expired yes; - servfail-ttl 0; - - dnssec-validation auto; - bindkeys-file "managed.conf"; -}; - -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"; -}; diff --git a/bin/tests/system/dnssec/ns4/named4.conf.in b/bin/tests/system/dnssec/ns4/named4.conf.in deleted file mode 100644 index f5b387d0bdc..00000000000 --- a/bin/tests/system/dnssec/ns4/named4.conf.in +++ /dev/null @@ -1,90 +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. - */ - -// 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; }; - minimal-responses no; - - disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; }; - disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384"; }; - disable-ds-digests "ds-unsupported.example." { "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; }; - disable-algorithms "badalg.secure.example." { ECDSAP256SHA256; }; -}; - -key rndc_key { - secret "1234abcd8765"; - algorithm @DEFAULT_HMAC@; -}; - -controls { - inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; -}; - -key auth { - secret "1234abcd8765"; - algorithm @DEFAULT_HMAC@; -}; - -view rec { - match-recursive-only yes; - recursion yes; - dnssec-accept-expired yes; - minimal-responses no; - dnssec-validation yes; - - include "trusted.conf"; - - zone "." { - type hint; - file "../../_common/root.hint"; - }; - - zone secure.example { - type static-stub; - server-addresses { 10.53.0.4; }; - }; - - zone insecure.secure.example { - type static-stub; - server-addresses { 10.53.0.4; }; - }; -}; - -view auth { - recursion no; - allow-recursion { none; }; - dnssec-validation no; - - zone "." { - type hint; - file "../../_common/root.hint"; - }; - - zone secure.example { - type secondary; - primaries { 10.53.0.3; }; - }; - - zone insecure.secure.example { - type secondary; - primaries { 10.53.0.2; }; - }; -}; diff --git a/bin/tests/system/dnssec/ns5/named.conf.j2 b/bin/tests/system/dnssec/ns5/named.conf.j2 index bdbd1f3b30f..a0332d9d6ff 100644 --- a/bin/tests/system/dnssec/ns5/named.conf.j2 +++ b/bin/tests/system/dnssec/ns5/named.conf.j2 @@ -13,6 +13,9 @@ // NS5 +{% set revoked_key = revoked_key | default(False) %} +{% set broken_key = broken_key | default(False) %} +{% set many_anchors = many_anchors | default(False) %} options { query-source address 10.53.0.5; notify-source 10.53.0.5; @@ -22,6 +25,14 @@ options { listen-on { 10.53.0.5; 127.0.0.1; }; listen-on-v6 { none; }; recursion yes; + minimal-responses no; + servfail-ttl 0; + +{% if many_anchors %} + dnssec-validation yes; + disable-algorithms "disabled.managed." { @DISABLED_ALGORITHM@; }; + disable-algorithms "disabled.trusted." { @DISABLED_ALGORITHM@; }; +{% endif %} }; key rndc_key { @@ -33,8 +44,6 @@ controls { inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; }; -{% set revoked_key = revoked_key | default(False) %} -{% set broken_key = broken_key | default(False) %} {% if revoked_key %} view root { match-destinations { 127.0.0.1; }; @@ -62,6 +71,14 @@ controls { }; include "broken.conf"; +{% elif many_anchors %} + zone "." { + type hint; + file "../../_common/root.hint"; + }; + + include "many-managed.conf"; + include "many-trusted.conf"; {% else %} zone "." { type hint; diff --git a/bin/tests/system/dnssec/ns6/named.args b/bin/tests/system/dnssec/ns6/named.args deleted file mode 100644 index 04d5d1b50ef..00000000000 --- a/bin/tests/system/dnssec/ns6/named.args +++ /dev/null @@ -1 +0,0 @@ --m record -c named.conf -d 99 -D dnssec-ns6 -g -T maxcachesize=2097152 -T nonearest -T tat=1 diff --git a/bin/tests/system/dnssec/ns6/named.conf.j2 b/bin/tests/system/dnssec/ns6/named.conf.j2 index 2818b7958cb..c3c0da6e44e 100644 --- a/bin/tests/system/dnssec/ns6/named.conf.j2 +++ b/bin/tests/system/dnssec/ns6/named.conf.j2 @@ -37,4 +37,15 @@ zone "optout-tld" { file "optout-tld.db.signed"; }; +zone "nosoa.secure.example" { + type primary; + file "nosoa.secure.example.db"; +}; + +zone "split-rrsig" { + type primary; + file "split-rrsig.db.signed"; + allow-update { any; }; +}; + include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns6/named.nonearest b/bin/tests/system/dnssec/ns6/named.nonearest new file mode 100644 index 00000000000..ba4c4eb3abc --- /dev/null +++ b/bin/tests/system/dnssec/ns6/named.nonearest @@ -0,0 +1,12 @@ +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. + +Add -T nonearest. diff --git a/bin/tests/system/dnssec/ns7/named.nosoa b/bin/tests/system/dnssec/ns6/named.nosoa similarity index 100% rename from bin/tests/system/dnssec/ns7/named.nosoa rename to bin/tests/system/dnssec/ns6/named.nosoa diff --git a/bin/tests/system/dnssec/ns6/named.tat=1 b/bin/tests/system/dnssec/ns6/named.tat=1 new file mode 100644 index 00000000000..c5c93e99916 --- /dev/null +++ b/bin/tests/system/dnssec/ns6/named.tat=1 @@ -0,0 +1,12 @@ +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. + +Add -T tat=1. diff --git a/bin/tests/system/dnssec/ns7/nosoa.secure.example.db b/bin/tests/system/dnssec/ns6/nosoa.secure.example.db similarity index 97% rename from bin/tests/system/dnssec/ns7/nosoa.secure.example.db rename to bin/tests/system/dnssec/ns6/nosoa.secure.example.db index d3c98783ead..6b7af125534 100644 --- a/bin/tests/system/dnssec/ns7/nosoa.secure.example.db +++ b/bin/tests/system/dnssec/ns6/nosoa.secure.example.db @@ -18,5 +18,5 @@ $TTL 300 ; 5 minutes 3600 ; minimum (1 hour) ) @ IN NS ns -ns IN A 10.53.0.7 +ns IN A 10.53.0.6 a IN A 1.2.3.4 diff --git a/bin/tests/system/dnssec/ns6/sign.sh b/bin/tests/system/dnssec/ns6/sign.sh index 103baf257eb..74ae836f718 100644 --- a/bin/tests/system/dnssec/ns6/sign.sh +++ b/bin/tests/system/dnssec/ns6/sign.sh @@ -27,3 +27,28 @@ keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") cat "$infile" "$keyname.key" >"$zonefile" "$SIGNER" -z -3 - -A -o "$zone" "$zonefile" >/dev/null 2>&1 + +zone=split-rrsig +infile=split-rrsig.db.in +zonefile=split-rrsig.db + +k1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") +k2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") + +cat "$infile" "$k1.key" "$k2.key" >"$zonefile" + +# The awk script below achieves two goals: +# +# - it puts one of the two RRSIG(SOA) records at the end of the zone file, so +# that these two records (forming a single RRset) are not placed immediately +# next to each other; the test then checks if RRSIG RRsets split this way are +# correctly added to resigning heaps, +# +# - it places a copy of one of the RRSIG(SOA) records somewhere else than at the +# zone apex; the test then checks whether such signatures are automatically +# removed from the zone after it is loaded. +"$SIGNER" -P -3 - -A -o "$zone" -O full -f "$zonefile.unsplit" -e now-3600 -s now-7200 "$zonefile" >/dev/null 2>&1 +awk 'BEGIN { r = ""; } + $4 == "RRSIG" && $5 == "SOA" && r == "" { r = $0; next; } + { print } + END { print r; print "not-at-zone-apex." r; }' "$zonefile.unsplit" >"$zonefile.signed" diff --git a/bin/tests/system/dnssec/ns7/split-rrsig.db.in b/bin/tests/system/dnssec/ns6/split-rrsig.db.in similarity index 100% rename from bin/tests/system/dnssec/ns7/split-rrsig.db.in rename to bin/tests/system/dnssec/ns6/split-rrsig.db.in diff --git a/bin/tests/system/dnssec/ns7/named.conf.j2 b/bin/tests/system/dnssec/ns7/named.conf.j2 deleted file mode 100644 index b35284664b3..00000000000 --- a/bin/tests/system/dnssec/ns7/named.conf.j2 +++ /dev/null @@ -1,76 +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. - */ - -// NS3 - -options { - query-source address 10.53.0.7; - notify-source 10.53.0.7; - transfer-source 10.53.0.7; - port @PORT@; - pid-file "named.pid"; - listen-on { 10.53.0.7; }; - listen-on-v6 { none; }; - recursion no; - notify yes; - dnssec-validation yes; - minimal-responses yes; -}; - -zone "." { - type hint; - file "../../_common/root.hint"; -}; - -zone "nsec3.example" { - type secondary; - primaries { 10.53.0.3; }; - file "nsec3.example.bk"; -}; - -zone "optout.example" { - type secondary; - primaries { 10.53.0.3; }; - file "optout.example.bk"; -}; - -zone "nsec3-unknown.example" { - type secondary; - primaries { 10.53.0.3; }; - file "nsec3-unknown.example.bk"; -}; - -zone "optout-unknown.example" { - type secondary; - primaries { 10.53.0.3; }; - file "optout-unknown.example.bk"; -}; - -zone "multiple.example" { - type secondary; - primaries { 10.53.0.3; }; - file "multiple.example.bk"; -}; - -zone "nosoa.secure.example" { - type primary; - file "nosoa.secure.example.db"; -}; - -zone "split-rrsig" { - type primary; - file "split-rrsig.db.signed"; - allow-update { any; }; -}; - -include "trusted.conf"; diff --git a/bin/tests/system/dnssec/ns7/sign.sh b/bin/tests/system/dnssec/ns7/sign.sh deleted file mode 100644 index 7aaceadbb9b..00000000000 --- a/bin/tests/system/dnssec/ns7/sign.sh +++ /dev/null @@ -1,44 +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 "ns7/sign.sh" - -zone=split-rrsig -infile=split-rrsig.db.in -zonefile=split-rrsig.db - -k1=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") -k2=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone") - -cat "$infile" "$k1.key" "$k2.key" >"$zonefile" - -# The awk script below achieves two goals: -# -# - it puts one of the two RRSIG(SOA) records at the end of the zone file, so -# that these two records (forming a single RRset) are not placed immediately -# next to each other; the test then checks if RRSIG RRsets split this way are -# correctly added to resigning heaps, -# -# - it places a copy of one of the RRSIG(SOA) records somewhere else than at the -# zone apex; the test then checks whether such signatures are automatically -# removed from the zone after it is loaded. -"$SIGNER" -P -3 - -A -o "$zone" -O full -f "$zonefile.unsplit" -e now-3600 -s now-7200 "$zonefile" >/dev/null 2>&1 -awk 'BEGIN { r = ""; } - $4 == "RRSIG" && $5 == "SOA" && r == "" { r = $0; next; } - { print } - END { print r; print "not-at-zone-apex." r; }' "$zonefile.unsplit" >"$zonefile.signed" diff --git a/bin/tests/system/dnssec/ns8/named.conf.j2 b/bin/tests/system/dnssec/ns8/named.conf.j2 deleted file mode 100644 index 2590de18908..00000000000 --- a/bin/tests/system/dnssec/ns8/named.conf.j2 +++ /dev/null @@ -1,47 +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. - */ - -// NS8 - -options { - query-source address 10.53.0.8; - notify-source 10.53.0.8; - transfer-source 10.53.0.8; - port @PORT@; - pid-file "named.pid"; - listen-on { 10.53.0.8; }; - listen-on-v6 { none; }; - recursion yes; - dnssec-validation yes; - minimal-responses no; - disable-algorithms "disabled.managed." { @DISABLED_ALGORITHM@; }; - disable-algorithms "disabled.trusted." { @DISABLED_ALGORITHM@; }; -}; - -key rndc_key { - secret "1234abcd8765"; - algorithm @DEFAULT_HMAC@; -}; - -controls { - inet 10.53.0.8 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; -}; - -zone "." { - type hint; - file "../../_common/root.hint"; -}; - -include "managed.conf"; -include "trusted.conf"; - diff --git a/bin/tests/system/dnssec/setup.sh b/bin/tests/system/dnssec/setup.sh index 14970719b94..7c895667fc4 100644 --- a/bin/tests/system/dnssec/setup.sh +++ b/bin/tests/system/dnssec/setup.sh @@ -16,8 +16,6 @@ set -e -copy_setports ns4/named1.conf.in ns4/named.conf - ( cd ns1 $SHELL sign.sh diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index b0033f61277..2b4f9c864a8 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -75,165 +75,12 @@ checkprivate() { return 1 } -# -# Ensure there is not multiple consecutive blank lines. -# Ensure there is a blank line before "Start view" and -# "Negative trust anchors:". -# Ensure there is not a blank line before "Secure roots:". -# -check_secroots_layout() { - awk '$0 == "" { if (empty) exit(1); empty=1; next } - /Start view/ { if (!empty) exit(1) } - /Secure roots:/ { if (empty) exit(1) } - /Negative trust anchors:/ { if (!empty) exit(1) } - { empty=0 }' $1 || return $? -} - -# Check that for a query against a validating resolver where the -# authoritative zone is unsigned (insecure delegation), glue is returned -# in the additional section -echo_i "checking that additional glue is returned for unsigned delegation ($n)" -ret=0 -$DIG +tcp +dnssec -p "$PORT" a.insecure.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -grep "ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ns\\.insecure\\.example\\..*A.10\\.53\\.0\\.3" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -# Check the example. domain - -echo_i "checking that zone transfer worked ($n)" -for i in 1 2 3 4 5 6 7 8 9; do - ret=0 - dig_with_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 - dig_with_opts a.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 - $PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns3.test$n >/dev/null || ret=1 - [ "$ret" -eq 0 ] && break - sleep 1 -done -digcomp dig.out.ns2.test$n dig.out.ns3.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# test AD bit: -# - dig +adflag asks for authentication (ad in response) -echo_i "checking AD bit asking for validation ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# test AD bit: -# - dig +noadflag -echo_i "checking that AD is not set without +adflag or +dnssec ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking for AD in authoritative answer ($n)" -ret=0 -dig_with_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation NSEC ($n)" -ret=0 -dig_with_opts +noauth a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking recovery from spoofed server addresses ($n)" -ret=0 -# prime cache with spoofed address records -dig_with_opts +cd target.peer-ns-spoof @10.53.0.4 a >dig.out.prime.ns4.test$n || ret=1 -grep "status: SERVFAIL" dig.out.prime.ns4.test$n >/dev/null || ret=1 -rndccmd 10.53.0.4 dumpdb | sed 's/^/ns4 /' | cat_i -mv ns4/named_dump.db ns4/named_dump.db.test$n >/dev/null || ret=1 -grep "10.53.0.100" ns4/named_dump.db.test$n || ret=1 -# reload server with properly signed zone -cp ns2/peer.peer-ns-spoof.db.next ns2/peer.peer-ns-spoof.db.signed -nextpart ns2/named.run >/dev/null -rndccmd 10.53.0.2 reload peer.peer-ns-spoof | sed 's/^/ns2 /' | cat_i -wait_for_log 5 "zone peer.peer-ns-spoof/IN: loaded serial 2000042408" ns2/named.run || ret=1 -dig_with_opts +noauth test.target.peer-ns-spoof @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags: qr rd ra ad;" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking recovery from stripped DNSKEY RRSIG ($n)" -ret=0 -# prime cache with DNSKEY without RRSIGs -dig_with_opts +noauth +cd dnskey-rrsigs-stripped. @10.53.0.4 dnskey >dig.out.prime.ns4.test$n || ret=1 -grep ";; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1" dig.out.prime.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1 -grep "RRSIG.DNSKEY" dig.out.prime.ns4.test$n >/dev/null && ret=1 -# reload server with properly signed zone -cp ns2/dnskey-rrsigs-stripped.db.next ns2/dnskey-rrsigs-stripped.db.signed -nextpart ns2/named.run >/dev/null -rndccmd 10.53.0.2 reload dnskey-rrsigs-stripped | sed 's/^/ns2 /' | cat_i -wait_for_log 5 "zone dnskey-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1 -dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking recovery from stripped DS RRSIG ($n)" -ret=0 -# prime cache with DS without RRSIGs -dig_with_opts +noauth +cd child.ds-rrsigs-stripped. @10.53.0.4 ds >dig.out.prime.ns4.test$n || ret=1 -grep ";; flags: qr rd ra cd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.prime.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1 -grep "RRSIG.DS" dig.out.prime.ns4.test$n >/dev/null && ret=1 -# reload server with properly signed zone -cp ns2/ds-rrsigs-stripped.db.next ns2/ds-rrsigs-stripped.db.signed -nextpart ns2/named.run >/dev/null -rndccmd 10.53.0.2 reload ds-rrsigs-stripped | sed 's/^/ns2 /' | cat_i -wait_for_log 5 "zone ds-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1 -dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that 'example/DS' from the referral was used in previous validation ($n)" -ret=0 -grep "query 'example/DS/IN' approved" ns1/named.run >/dev/null && ret=1 -grep "fetch: example/DS" ns4/named.run >/dev/null && ret=1 -grep "validating example/DS: starting" ns4/named.run >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - if [ -x "${DELV}" ]; then ret=0 echo_i "checking positive validation NSEC using dns_client ($n)" delv_with_opts @10.53.0.4 a a.example >delv.out$n || ret=1 grep "a.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 - grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n >/dev/null || ret=1 + grep "a.example..*.RRSIG.A [0-9][0-9]* 2 3600 .*" delv.out$n >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) @@ -242,50 +89,22 @@ if [ -x "${DELV}" ]; then echo_i "checking positive validation NSEC using dns_client (trusted-keys) ($n)" "$DELV" -a ns1/trusted.keys -p "$PORT" @10.53.0.4 a a.example >delv.out$n || ret=1 grep "a.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 - grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n >/dev/null || ret=1 + grep "a.example..*.RRSIG.A [0-9][0-9]* 2 3600 .*" delv.out$n >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking positive validation NSEC3 ($n)" -ret=0 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking positive validation NSEC3 using dns_client ($n)" delv_with_opts @10.53.0.4 a a.nsec3.example >delv.out$n || ret=1 grep "a.nsec3.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 - grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1 + grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300 .*" delv.out$n >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking positive validation OPTOUT ($n)" -ret=0 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -SP="[[:space:]]+" + SP="[[:space:]]+" -if [ -x "${DELV}" ]; then ret=0 echo_i "checking positive validation OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 a a.optout.example >delv.out$n || ret=1 @@ -294,66 +113,16 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi -echo_i "checking positive wildcard validation NSEC ($n)" -ret=0 -dig_with_opts a.wild.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts a.wild.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n -stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n -digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1 -grep "\\*\\.wild\\.example\\..*RRSIG NSEC" dig.out.ns4.test$n >/dev/null || ret=1 -grep "\\*\\.wild\\.example\\..*NSEC z\\.example" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then ret=0 echo_i "checking positive wildcard validation NSEC using dns_client ($n)" delv_with_opts @10.53.0.4 a a.wild.example >delv.out$n || ret=1 grep "a.wild.example..*10.0.0.27" delv.out$n >/dev/null || ret=1 - grep -E "a.wild.example..*RRSIG.A [0-9]+ 2 300.*" delv.out$n >/dev/null || ret=1 + grep -E "a.wild.example..*RRSIG.A [0-9]+ 2 3600 .*" delv.out$n >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking positive wildcard answer NSEC3 ($n)" -ret=0 -dig_with_opts a.wild.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -grep "AUTHORITY: 4," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive wildcard answer NSEC3 ($n)" -ret=0 -dig_with_opts a.wild.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -grep "AUTHORITY: 4," dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive wildcard validation NSEC3 ($n)" -ret=0 -dig_with_opts a.wild.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts a.wild.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n -stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n -digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking positive wildcard validation NSEC3 using dns_client ($n)" delv_with_opts @10.53.0.4 a a.wild.nsec3.example >delv.out$n || ret=1 @@ -362,24 +131,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi -echo_i "checking positive wildcard validation OPTOUT ($n)" -ret=0 -dig_with_opts a.wild.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts a.wild.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n -stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n -digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then ret=0 echo_i "checking positive wildcard validation OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 a a.wild.optout.example >delv.out$n || ret=1 @@ -388,20 +140,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking negative validation NXDOMAIN NSEC ($n)" -ret=0 -dig_with_opts +noauth q.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth q.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative validation NXDOMAIN NSEC using dns_client ($n)" delv_with_opts @10.53.0.4 a q.example >delv.out$n 2>&1 || ret=1 @@ -409,30 +148,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking RRSIG covered type in negative cache entry ($n)" -ret=0 -rndc_dumpdb ns4 -grep -F '; example. RRSIG NSEC ...' ns4/named_dump.db.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking negative validation NXDOMAIN NSEC3 ($n)" -ret=0 -dig_with_opts +noauth q.nsec3.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth q.nsec3.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative validation NXDOMAIN NSEC3 using dns_client ($n)" delv_with_opts @10.53.0.4 a q.nsec3.example >delv.out$n 2>&1 || ret=1 @@ -440,23 +156,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking negative validation NXDOMAIN OPTOUT ($n)" -ret=0 -dig_with_opts +noauth q.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth q.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative validation NXDOMAIN OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 a q.optout.example >delv.out$n 2>&1 || ret=1 @@ -464,21 +164,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking negative validation NODATA NSEC ($n)" -ret=0 -dig_with_opts +noauth a.example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth a.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 txt a.example >delv.out$n 2>&1 || ret=1 @@ -486,23 +172,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi -echo_i "checking negative validation NODATA NSEC3 ($n)" -ret=0 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative validation NODATA NSEC3 using dns_client ($n)" delv_with_opts @10.53.0.4 txt a.nsec3.example >delv.out$n 2>&1 || ret=1 @@ -510,23 +180,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking negative validation NODATA OPTOUT ($n)" -ret=0 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 txt a.optout.example >delv.out$n 2>&1 || ret=1 @@ -534,20 +188,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking negative wildcard validation NSEC ($n)" -ret=0 -dig_with_opts b.wild.example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1 -dig_with_opts b.wild.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative wildcard validation NSEC using dns_client ($n)" delv_with_opts @10.53.0.4 txt b.wild.example >delv.out$n 2>&1 || ret=1 @@ -555,19 +196,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking negative wildcard validation NSEC3 ($n)" -ret=0 -dig_with_opts b.wild.nsec3.example. @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 -dig_with_opts b.wild.nsec3.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative wildcard validation NSEC3 using dns_client ($n)" delv_with_opts @10.53.0.4 txt b.wild.nsec3.example >delv.out$n 2>&1 || ret=1 @@ -575,23 +204,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking negative wildcard validation OPTOUT ($n)" -ret=0 -dig_with_opts b.wild.optout.example. \ - @10.53.0.3 txt >dig.out.ns3.test$n || ret=1 -dig_with_opts b.wild.optout.example. \ - @10.53.0.4 txt >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking negative wildcard validation OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 txt b.optout.nsec3.example >delv.out$n 2>&1 || ret=1 @@ -599,23 +212,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -# Check the insecure.example domain - -echo_i "checking 1-server insecurity proof NSEC ($n)" -ret=0 -dig_with_opts +noauth a.insecure.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.insecure.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking 1-server insecurity proof NSEC using dns_client ($n)" delv_with_opts @10.53.0.4 a a.insecure.example >delv.out$n || ret=1 @@ -623,21 +220,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking 1-server insecurity proof NSEC3 ($n)" -ret=0 -dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking 1-server insecurity proof NSEC3 using dns_client ($n)" delv_with_opts @10.53.0.4 a a.insecure.nsec3.example >delv.out$n || ret=1 @@ -645,21 +228,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking 1-server insecurity proof OPTOUT ($n)" -ret=0 -dig_with_opts +noauth a.insecure.optout.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.insecure.optout.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking 1-server insecurity proof OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 a a.insecure.optout.example >delv.out$n || ret=1 @@ -667,23 +236,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking 1-server negative insecurity proof NSEC ($n)" -ret=0 -dig_with_opts q.insecure.example. a @10.53.0.3 \ - >dig.out.ns3.test$n || ret=1 -dig_with_opts q.insecure.example. a @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking 1-server negative insecurity proof NSEC using dns_client ($n)" delv_with_opts @10.53.0.4 a q.insecure.example >delv.out$n 2>&1 || ret=1 @@ -691,23 +244,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi -echo_i "checking 1-server negative insecurity proof NSEC3 ($n)" -ret=0 -dig_with_opts q.insecure.nsec3.example. a @10.53.0.3 \ - >dig.out.ns3.test$n || ret=1 -dig_with_opts q.insecure.nsec3.example. a @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then ret=0 echo_i "checking 1-server negative insecurity proof NSEC3 using dns_client ($n)" delv_with_opts @10.53.0.4 a q.insecure.nsec3.example >delv.out$n 2>&1 || ret=1 @@ -715,23 +252,7 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking 1-server negative insecurity proof OPTOUT ($n)" -ret=0 -dig_with_opts q.insecure.optout.example. a @10.53.0.3 \ - >dig.out.ns3.test$n || ret=1 -dig_with_opts q.insecure.optout.example. a @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -if [ -x "${DELV}" ]; then ret=0 echo_i "checking 1-server negative insecurity proof OPTOUT using dns_client ($n)" delv_with_opts @10.53.0.4 a q.insecure.optout.example >delv.out$n 2>&1 || ret=1 @@ -739,718 +260,34 @@ if [ -x "${DELV}" ]; then n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -fi - -echo_i "checking 1-server negative insecurity proof with SOA hack NSEC ($n)" -ret=0 -dig_with_opts r.insecure.example. soa @10.53.0.3 \ - >dig.out.ns3.test$n || ret=1 -dig_with_opts r.insecure.example. soa @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) -echo_i "checking 1-server negative insecurity proof with SOA hack NSEC3 ($n)" -ret=0 -dig_with_opts r.insecure.nsec3.example. soa @10.53.0.3 \ - >dig.out.ns3.test$n || ret=1 -dig_with_opts r.insecure.nsec3.example. soa @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) + ret=0 + echo_i "checking failed validation using dns_client ($n)" + delv_with_opts +cd @10.53.0.4 a a.bogus.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: RRSIG failed to verify" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) -echo_i "checking 1-server negative insecurity proof with SOA hack OPTOUT ($n)" -ret=0 -dig_with_opts r.insecure.optout.example. soa @10.53.0.3 \ - >dig.out.ns3.test$n || ret=1 -dig_with_opts r.insecure.optout.example. soa @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) + ret=0 + echo_i "checking that validation fails when key record is missing using dns_client ($n)" + delv_with_opts +cd @10.53.0.4 a a.b.keyless.example >delv.out$n 2>&1 || ret=1 + grep "resolution failed: insecurity proof failed" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) -# Check the secure.example domain + ret=0 + echo_i "checking that validation succeeds when a revoked key is encountered using dns_client ($n)" + delv_with_opts +cd @10.53.0.4 soa revkey.example >delv.out$n 2>&1 || ret=1 + grep "fully validated" delv.out$n >/dev/null || ret=1 + n=$((n + 1)) + test "$ret" -eq 0 || echo_i "failed" + status=$((status + ret)) +fi -echo_i "checking multi-stage positive validation NSEC/NSEC ($n)" -ret=0 -dig_with_opts +noauth a.secure.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.secure.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking mixed-case positive validation ($n)" -ret=0 -for type in a txt aaaa loc; do - dig_with_opts +noauth mixedcase.secure.example. \ - @10.53.0.3 $type >dig.out.$type.ns3.test$n || ret=1 - dig_with_opts +noauth mixedcase.secure.example. \ - @10.53.0.4 $type >dig.out.$type.ns4.test$n || ret=1 - digcomp --lc dig.out.$type.ns3.test$n dig.out.$type.ns4.test$n || ret=1 - grep "status: NOERROR" dig.out.$type.ns4.test$n >/dev/null || ret=1 - grep "flags:.*ad.*QUERY" dig.out.$type.ns4.test$n >/dev/null || ret=1 -done -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)" -ret=0 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation NSEC/OPTOUT ($n)" -ret=0 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation NSEC3/NSEC ($n)" -ret=0 -dig_with_opts +noauth a.secure.nsec3.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.secure.nsec3.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation NSEC3/NSEC3 ($n)" -ret=0 -dig_with_opts +noauth a.nsec3.nsec3.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.nsec3.nsec3.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation NSEC3/OPTOUT ($n)" -ret=0 -dig_with_opts +noauth a.optout.nsec3.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.optout.nsec3.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation OPTOUT/NSEC ($n)" -ret=0 -dig_with_opts +noauth a.secure.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.secure.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation OPTOUT/NSEC3 ($n)" -ret=0 -dig_with_opts +noauth a.nsec3.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.nsec3.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking multi-stage positive validation OPTOUT/OPTOUT ($n)" -ret=0 -dig_with_opts +noauth a.optout.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.optout.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking empty NODATA OPTOUT ($n)" -ret=0 -dig_with_opts +noauth empty.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth empty.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation with private algorithm works ($n)" -ret=0 -dig_with_opts +noauth a.rsasha256oid.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.rsasha256oid.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then - ret=0 - echo_i "checking positive validation NSEC3 using dns_client ($n)" - delv_with_opts @10.53.0.4 a a.nsec3.example >delv.out$n || ret=1 - grep "a.nsec3.example..*10.0.0.1" delv.out$n >/dev/null || ret=1 - grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1 - n=$((n + 1)) - test "$ret" -eq 0 || echo_i "failed" - status=$((status + ret)) -fi - -echo_i "checking positive validation with unknown private algorithm works ($n)" -ret=0 -dig_with_opts +noauth a.unknownoid.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.unknownoid.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation with extra ds for private algorithm ($n)" -ret=0 -dig_with_opts +noauth a.extradsoid.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.extradsoid.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation with extra ds for unknown private algorithm fails ($n)" -ret=0 -dig_with_opts +noauth a.extradsunknownoid.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.extradsunknownoid.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -grep 'No DNSKEY for extradsunknownoid.example/DS with PRIVATEOID algorithm, tag [1-9][0-9]*$' ns4/named.run >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if $FEATURETEST --extended-ds-digest; then - echo_i "checking positive validation with extra ds using extended digest type for unknown private algorithm succeeds ($n)" - ret=0 - dig_with_opts +noauth a.extended-ds-unknown-oid.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 - dig_with_opts +noauth a.extended-ds-unknown-oid.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 - digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 - grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 - n=$((n + 1)) - test "$ret" -eq 0 || echo_i "failed" - status=$((status + ret)) -fi - -# Check the bogus domain - -echo_i "checking failed validation ($n)" -ret=0 -dig_with_opts a.bogus.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then - ret=0 - echo_i "checking failed validation using dns_client ($n)" - delv_with_opts +cd @10.53.0.4 a a.bogus.example >delv.out$n 2>&1 || ret=1 - grep "resolution failed: RRSIG failed to verify" delv.out$n >/dev/null || ret=1 - n=$((n + 1)) - test "$ret" -eq 0 || echo_i "failed" - status=$((status + ret)) -fi - -echo_i "checking that validation fails when key record is missing ($n)" -ret=0 -dig_with_opts a.b.keyless.example. a @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then - ret=0 - echo_i "checking that validation fails when key record is missing using dns_client ($n)" - delv_with_opts +cd @10.53.0.4 a a.b.keyless.example >delv.out$n 2>&1 || ret=1 - grep "resolution failed: insecurity proof failed" delv.out$n >/dev/null || ret=1 - n=$((n + 1)) - test "$ret" -eq 0 || echo_i "failed" - status=$((status + ret)) -fi - -echo_i "checking that validation succeeds when a revoked key is encountered ($n)" -ret=0 -dig_with_opts revkey.example soa @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags: .* ad" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -if [ -x "${DELV}" ]; then - ret=0 - echo_i "checking that validation succeeds when a revoked key is encountered using dns_client ($n)" - delv_with_opts +cd @10.53.0.4 soa revkey.example >delv.out$n 2>&1 || ret=1 - grep "fully validated" delv.out$n >/dev/null || ret=1 - n=$((n + 1)) - test "$ret" -eq 0 || echo_i "failed" - status=$((status + ret)) -fi - -echo_i "Checking that a bad CNAME signature is caught after a +CD query ($n)" -ret=0 -#prime -dig_with_opts +cd bad-cname.example. @10.53.0.4 >dig.out.ns4.prime$n || ret=1 -#check: requery with +CD. pending data should be returned even if it's bogus -expect="a.example. -10.0.0.1" -ans=$(dig_with_opts +cd +nodnssec +short bad-cname.example. @10.53.0.4) || ret=1 -test "$ans" = "$expect" || ret=1 -test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'" -#check: requery without +CD. bogus cached data should be rejected. -dig_with_opts +nodnssec bad-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "Checking that a bad DNAME signature is caught after a +CD query ($n)" -ret=0 -#prime -dig_with_opts +cd a.bad-dname.example. @10.53.0.4 >dig.out.ns4.prime$n || ret=1 -#check: requery with +CD. pending data should be returned even if it's bogus -expect="example. -a.example. -10.0.0.1" -ans=$(dig_with_opts +cd +nodnssec +short a.bad-dname.example. @10.53.0.4) || ret=1 -test "$ans" = "$expect" || ret=1 -test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'" -#check: requery without +CD. bogus cached data should be rejected. -dig_with_opts +nodnssec a.bad-dname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Check the insecure.secure.example domain (insecurity proof) - -echo_i "checking 2-server insecurity proof ($n)" -ret=0 -dig_with_opts +noauth a.insecure.secure.example. @10.53.0.2 a \ - >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth a.insecure.secure.example. @10.53.0.4 a \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Check a negative response in insecure.secure.example - -echo_i "checking 2-server insecurity proof with a negative answer ($n)" -ret=0 -dig_with_opts q.insecure.secure.example. @10.53.0.2 a >dig.out.ns2.test$n \ - || ret=1 -dig_with_opts q.insecure.secure.example. @10.53.0.4 a >dig.out.ns4.test$n \ - || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking 2-server insecurity proof with a negative answer and SOA hack ($n)" -ret=0 -dig_with_opts r.insecure.secure.example. @10.53.0.2 soa >dig.out.ns2.test$n \ - || ret=1 -dig_with_opts r.insecure.secure.example. @10.53.0.4 soa >dig.out.ns4.test$n \ - || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Check that the query for a security root is successful and has ad set - -echo_i "checking security root query ($n)" -ret=0 -dig_with_opts . @10.53.0.4 key >dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking insecurity proof works using negative cache ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -dig_with_opts +cd @10.53.0.4 insecure.example. ds >dig.out.ns4.test$n.1 || ret=1 -for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18; do - dig_with_opts @10.53.0.4 nonexistent.insecure.example. >dig.out.ns4.test$n.2 || ret=1 - if grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null; then - break - fi - sleep 1 -done -grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Should work with FIPS mode as we are only validating -echo_i "checking positive validation RSASHA1 NSEC ($n)" -ret=0 -if $FEATURETEST --rsasha1; then - dig_with_opts +noauth a.rsasha1.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 - dig_with_opts +noauth a.rsasha1.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 - digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 - grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -else - echo_i "skip: RSASHA1 not supported by OS" -fi -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Should work with FIPS mode as we are only validating -echo_i "checking positive validation RSASHA1 (1024 bits) NSEC ($n)" -ret=0 -if $FEATURETEST --rsasha1; then - dig_with_opts +noauth a.rsasha1-1024.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 - dig_with_opts +noauth a.rsasha1-1024.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 - digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 - grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -else - echo_i "skip: RSASHA1 not supported by OS" -fi -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation RSASHA256 NSEC ($n)" -ret=0 -dig_with_opts +noauth a.rsasha256.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.rsasha256.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation RSASHA512 NSEC ($n)" -ret=0 -dig_with_opts +noauth a.rsasha512.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.rsasha512.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation with KSK-only DNSKEY signature ($n)" -ret=0 -dig_with_opts +noauth a.kskonly.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.kskonly.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that validation of an ANY query works ($n)" -ret=0 -dig_with_opts +noauth foo.example. any @10.53.0.2 >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth foo.example. any @10.53.0.4 >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# 2 records in the zone, 1 NXT, 3 SIGs -grep "ANSWER: 6" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that validation of a query returning a CNAME works ($n)" -ret=0 -dig_with_opts +noauth cname1.example. txt @10.53.0.2 \ - >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth cname1.example. txt @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# the CNAME & its sig, the TXT and its SIG -grep "ANSWER: 4" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that validation of a query returning a DNAME works ($n)" -ret=0 -dig_with_opts +noauth foo.dname1.example. txt @10.53.0.2 \ - >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth foo.dname1.example. txt @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# The DNAME & its sig, the TXT and its SIG, and the synthesized CNAME. -# It would be nice to test that the CNAME is being synthesized by the -# recursive server and not cached, but I don't know how. -grep "ANSWER: 5" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that validation of an ANY query returning a CNAME works ($n)" -ret=0 -dig_with_opts +noauth cname2.example. any @10.53.0.2 \ - >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth cname2.example. any @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -# The CNAME, NXT, and their SIGs -grep "ANSWER: 4" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that validation of an ANY query returning a DNAME works ($n)" -ret=0 -dig_with_opts +noauth foo.dname2.example. any @10.53.0.2 \ - >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth foo.dname2.example. any @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that lookups succeed after disabling an algorithm ($n)" -ret=0 -dig_with_opts +noauth example. SOA @10.53.0.2 \ - >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth example. SOA @10.53.0.6 \ - >dig.out.ns6.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1 -# Note - this is looking for failure, hence the && -grep "flags:.*ad.*QUERY" dig.out.ns6.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking a non-cachable NODATA works ($n)" -ret=0 -dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.7 \ - >dig.out.ns7.test$n || ret=1 -grep "AUTHORITY: 0" dig.out.ns7.test$n >/dev/null || ret=1 -dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking a non-cachable NXDOMAIN works ($n)" -ret=0 -dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.7 \ - >dig.out.ns7.test$n || ret=1 -grep "AUTHORITY: 0" dig.out.ns7.test$n >/dev/null || ret=1 -dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.4 \ - >dig.out.ns4.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that we can load a rfc2535 signed zone ($n)" -ret=0 -dig_with_opts rfc2535.example. SOA @10.53.0.2 \ - >dig.out.ns2.test$n || ret=1 -grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that we can transfer a rfc2535 signed zone ($n)" -ret=0 -dig_with_opts rfc2535.example. SOA @10.53.0.3 \ - >dig.out.ns3.test$n || ret=1 -grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Test that "rndc secroots" is able to dump trusted keys -echo_i "checking rndc secroots ($n)" -ret=0 -keyid=$(cat ns1/managed.key.id) -rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i -cp ns4/named.secroots named.secroots.test$n -check_secroots_layout named.secroots.test$n || ret=1 -linecount=$(grep -c "./$DEFAULT_ALGORITHM/$keyid ; static" named.secroots.test$n || true) -[ "$linecount" -eq 1 ] || ret=1 -linecount=$(wc /dev/null || ret=1 -ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1 -expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep -E '^(A|NSEC)') || ret=1 -test "$ans" = "$expect" || ret=1 -# also check that RA is set -dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1 -grep "flags:.*ra.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Check direct query for RRSIG: If it's not cached with other records, -# it should result in an empty response. -echo_i "checking RRSIG query not in cache ($n)" -ret=0 -ans=$(dig_with_opts +short rrsigonly.secure.example. @10.53.0.4 rrsig) || ret=1 -test -z "$ans" || ret=1 -# also check that RA is cleared -dig_with_opts rrsigonly.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1 -grep "flags:.*ra.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# -# RT21868 regression test. -# -echo_i "checking NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters ($n)" -ret=0 -dig_with_opts non-exist.badparam. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# -# RT22007 regression test. -# -echo_i "checking optout NSEC3 referral with only insecure delegations ($n)" -ret=0 -dig_with_opts +norec delegation.single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 -grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking optout NSEC3 NXDOMAIN with only insecure delegations ($n)" -ret=0 -dig_with_opts +norec nonexist.single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1 -grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" - -status=$((status + ret)) -echo_i "checking optout NSEC3 nodata with only insecure delegations ($n)" -ret=0 -dig_with_opts +norec single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1 -grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a zone finishing the transition from $ALTERNATIVE_ALGORITHM to $DEFAULT_ALGORITHM validates secure ($n)" -ret=0 -dig_with_opts ns algroll. @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Run a minimal update test if possible. This is really just -# a regression test for RT #2399; more tests should be added. +# Run a minimal update test if possible. This is really just +# a regression test for RT #2399; more tests should be added. if $PERL -e 'use Net::DNS;' 2>/dev/null; then echo_i "running DNSSEC update test" @@ -1466,128 +303,6 @@ else echo_i "The DNSSEC update test requires the Net::DNS library." >&2 fi -n=$((n + 1)) -echo_i "checking managed key maintenance has not started yet ($n)" -ret=0 -[ -f "ns4/managed-keys.bind.jnl" ] && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Reconfigure caching server to use "dnssec-validation auto", and repeat -# some of the DNSSEC validation tests to ensure that it works correctly. -# Also setup a placeholder managed-keys zone to check if named can process it -# correctly. -echo_i "switching to automatic root key configuration" -cp ns4/managed-keys.bind.in ns4/managed-keys.bind -copy_setports ns4/named2.conf.in ns4/named.conf -rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i -sleep 5 - -echo_i "checking managed key maintenance timer has now started ($n)" -ret=0 -[ -f "ns4/managed-keys.bind.jnl" ] || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation NSEC ($n)" -ret=0 -dig_with_opts +noauth a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation NSEC3 ($n)" -ret=0 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.nsec3.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking positive validation OPTOUT ($n)" -ret=0 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.3 a >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth a.optout.example. \ - @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking negative validation ($n)" -ret=0 -dig_with_opts +noauth q.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth q.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that root DS queries validate ($n)" -ret=0 -dig_with_opts +noauth . @10.53.0.1 ds >dig.out.ns1.test$n || ret=1 -dig_with_opts +noauth . @10.53.0.4 ds >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns1.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that DS at a RFC 1918 empty zone lookup succeeds ($n)" -ret=0 -dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.2 >dig.out.ns2.test$n || ret=1 -dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.4 >dig.out.ns6.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1 -grep "status: NOERROR" dig.out.ns6.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking expired signatures remain with "'"allow-update { none; };"'" and no keys available ($n)" -ret=0 -dig_with_opts +noauth expired.example. +dnssec @10.53.0.3 soa >dig.out.ns3.test$n || ret=1 -grep "RRSIG.SOA" dig.out.ns3.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" - -status=$((status + ret)) -echo_i "checking expired signatures do not validate ($n)" -ret=0 -dig_with_opts +noauth expired.example. +dnssec @10.53.0.4 soa >dig.out.ns4.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -grep "expired.example/.*: RRSIG has expired" ns4/named.run >/dev/null || ret=1 -grep "; EDE: 7 (Signature Expired): (expired.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -status=$((status + ret)) -echo_i "checking signatures in the future do not validate ($n)" -ret=0 -dig_with_opts +noauth future.example. +dnssec @10.53.0.4 soa >dig.out.ns4.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -grep "future.example/.*: RRSIG validity period has not begun" ns4/named.run >/dev/null || ret=1 -grep "; EDE: 8 (Signature Not Yet Valid): (future.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "checking that the NSEC3 record for the apex is properly signed when a DNSKEY is added via UPDATE ($n)" ret=0 ( @@ -1602,447 +317,97 @@ ret=0 dig_with_opts +dnssec a update-nsec3.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 -grep "NSEC3 1 0 0 - .*" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that signing records have been marked as complete ($n)" -ret=0 -checkprivate dynamic.example 10.53.0.3 || ret=1 -checkprivate auto-nsec3.example 10.53.0.3 || ret=1 -checkprivate expiring.example 10.53.0.3 || ret=1 -checkprivate auto-nsec.example 10.53.0.3 || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that 'rndc signing' without arguments is handled ($n)" -ret=0 -rndccmd 10.53.0.3 signing >/dev/null 2>&1 && ret=1 -rndccmd 10.53.0.3 status >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that 'rndc signing -list' without zone is handled ($n)" -ret=0 -rndccmd 10.53.0.3 signing -list >/dev/null 2>&1 && ret=1 -rndccmd 10.53.0.3 status >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)" -ret=0 -rndccmd 10.53.0.3 signing -clear >/dev/null 2>&1 && ret=1 -rndccmd 10.53.0.3 status >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that 'rndc signing -clear all' without zone is handled ($n)" -ret=0 -rndccmd 10.53.0.3 signing -clear all >/dev/null 2>&1 && ret=1 -rndccmd 10.53.0.3 status >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check rndc signing -list output ($n)" -ret=0 -{ rndccmd 10.53.0.3 signing -list dynamic.example >signing.out.dynamic.example; } 2>&1 -grep -q "No signing records found" signing.out.dynamic.example || { - ret=1 - sed 's/^/ns3 /' signing.out.dynamic.example | cat_i -} -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a insecure zone beneath a cname resolves ($n)" -ret=0 -dig_with_opts soa insecure.below-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a secure zone beneath a cname resolves ($n)" -ret=0 -dig_with_opts soa secure.below-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -my_dig() { - "$DIG" +noadd +nosea +nostat +noquest +nocomm +nocmd -p "$PORT" @10.53.0.4 "$@" -} - -echo_i "checking DNSKEY query with no data still gets put in cache ($n)" -ret=0 -firstVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }') -sleep 1 -secondVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }') -if [ "${firstVal:-0}" -eq "${secondVal:-0}" ]; then - sleep 1 - thirdVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }') - if [ "${firstVal:-0}" -eq "${thirdVal:-0}" ]; then - echo_i "cannot confirm query answer still in cache" - ret=1 - fi -fi -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that a split dnssec dnssec-signzone work ($n)" -ret=0 -dig_with_opts soa split-dnssec.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that a smart split dnssec dnssec-signzone work ($n)" -ret=0 -dig_with_opts soa split-smart.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check dnssec-dsfromkey from stdin ($n)" -ret=0 -dig_with_opts dnskey algroll. @10.53.0.2 \ - | $DSFROMKEY -f - algroll. >dig.out.ns2.test$n || ret=1 -NF=$(awk '{print NF}' dig.out.ns2.test$n | sort -u) -[ "${NF}" = 7 ] || ret=1 -# make canonical -awk '{ - for (i=1;i<7;i++) printf("%s ", $i); - for (i=7;i<=NF;i++) printf("%s", $i); - printf("\n"); -}' canonical1.$n || ret=1 -awk '{ - for (i=1;i<7;i++) printf("%s ", $i); - for (i=7;i<=NF;i++) printf("%s", $i); - printf("\n"); -}' canonical2.$n || ret=1 -diff -b canonical1.$n canonical2.$n >/dev/null 2>&1 || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Intentionally strip ".key" from keyfile name to ensure the error message -# includes it anyway to avoid confusion (RT #21731) -echo_i "check dnssec-dsfromkey error message when keyfile is not found ($n)" -ret=0 -key=$($KEYGEN -a $DEFAULT_ALGORITHM -q example.) || ret=1 -mv "$key.key" "$key" -$DSFROMKEY "$key" >dsfromkey.out.$n 2>&1 && ret=1 -grep "$key.key: file not found" dsfromkey.out.$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check dnssec-dsfromkey with revoked key ($n)" -ret=0 -dig_with_opts revkey.example dnskey @10.53.0.4 >dig.out.ns4.test$n || ret=1 -grep "DNSKEY.256 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # ZSK -grep "DNSKEY.385 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # revoked KSK -grep "DNSKEY.257 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # KSK -test $(awk '$4 == "DNSKEY" { print }' dig.out.ns4.test$n | wc -l) -eq 3 || ret=1 -$DSFROMKEY -f dig.out.ns4.test$n revkey.example. >dsfromkey.out.test$n || ret=1 -test $(wc -l dig.out.ns3.test$n 2>&1 -# there must be a signature here -[ -s dig.out.ns3.test$n ] || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "testing legacy upper case signer name validation ($n)" -ret=0 -$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa upper.example @10.53.0.4 \ - >dig.out.ns4.test$n 2>&1 || ret=1 -grep "flags:.* ad;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "RRSIG.*SOA.* UPPER\\.EXAMPLE\\. " dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "testing that we lower case signer name ($n)" -ret=0 -$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa LOWER.EXAMPLE @10.53.0.4 \ - >dig.out.ns4.test$n 2>&1 || ret=1 -grep "flags:.* ad;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "RRSIG.*SOA.* lower\\.example\\. " dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "testing TTL is capped at RRSIG expiry time ($n)" -ret=0 -rndccmd 10.53.0.3 freeze expiring.example 2>&1 | sed 's/^/ns3 /' | cat_i -( - cd ns3 || exit 1 - for file in K*.moved; do - mv "$file" "$(basename "$file" .moved)" - done - $SIGNER -S -N increment -e now+1mi -o expiring.example expiring.example.db >/dev/null -) || ret=1 -rndc_reload ns3 10.53.0.3 expiring.example - -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -dig_with_answeropts +cd expiring.example soa @10.53.0.4 >dig.out.ns4.1.$n -dig_with_answeropts expiring.example soa @10.53.0.4 >dig.out.ns4.2.$n -ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) -ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) -for ttl in ${ttls:-0}; do - [ "${ttl}" -eq 300 ] || ret=1 -done -for ttl in ${ttls2:-0}; do - [ "${ttl}" -le 60 ] || ret=1 -done -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (NS) ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -sleep 1 -dig_with_additionalopts +cd expiring.example ns @10.53.0.4 >dig.out.ns4.1.$n -dig_with_additionalopts expiring.example ns @10.53.0.4 >dig.out.ns4.2.$n -ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) -ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) -for ttl in ${ttls:-300}; do - [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1 -done -for ttl in ${ttls2:-0}; do - [ "$ttl" -le 60 ] || ret=1 -done -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (MX) ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -sleep 1 -dig_with_additionalopts +cd expiring.example mx @10.53.0.4 >dig.out.ns4.1.$n -dig_with_additionalopts expiring.example mx @10.53.0.4 >dig.out.ns4.2.$n -ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) -ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) -for ttl in ${ttls:-300}; do - [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1 -done -for ttl in ${ttls2:-0}; do - [ "$ttl" -le 60 ] || ret=1 -done -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -copy_setports ns4/named3.conf.in ns4/named.conf -rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i -sleep 3 - -echo_i "testing TTL of about to expire RRsets with dnssec-accept-expired yes; ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -dig_with_answeropts +cd expiring.example soa @10.53.0.4 >dig.out.ns4.1.$n -dig_with_answeropts expiring.example soa @10.53.0.4 >dig.out.ns4.2.$n -ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) -ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) -for ttl in ${ttls:-0}; do - [ "$ttl" -eq 300 ] || ret=1 -done -for ttl in ${ttls2:-0}; do - [ "$ttl" -eq 120 ] || ret=1 -done -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)" -ret=0 -dig_with_answeropts +cd expired.example soa @10.53.0.4 >dig.out.ns4.1.$n -dig_with_answeropts expired.example soa @10.53.0.4 >dig.out.ns4.2.$n -ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) -ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) -for ttl in ${ttls:-0}; do - [ "$ttl" -eq 300 ] || ret=1 -done -for ttl in ${ttls2:-0}; do - [ "$ttl" -eq 120 ] || ret=1 -done -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section with dnssec-accept-expired yes; ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -dig_with_additionalopts +cd expiring.example mx @10.53.0.4 >dig.out.ns4.1.$n -dig_with_additionalopts expiring.example mx @10.53.0.4 >dig.out.ns4.2.$n -ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n) -ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n) -for ttl in ${ttls:-300}; do - [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1 -done -for ttl in ${ttls2:-0}; do - [ "$ttl" -le 120 ] && [ "$ttl" -gt 60 ] || ret=1 -done +grep "NSEC3 1 0 0 - .*" dig.out.ns4.test$n >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "testing DNSKEY lookup via CNAME ($n)" +echo_i "checking that signing records have been marked as complete ($n)" ret=0 -dig_with_opts +noauth cnameandkey.secure.example. \ - @10.53.0.3 dnskey >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth cnameandkey.secure.example. \ - @10.53.0.4 dnskey >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "CNAME" dig.out.ns4.test$n >/dev/null || ret=1 +checkprivate dynamic.example 10.53.0.3 || ret=1 +checkprivate auto-nsec3.example 10.53.0.3 || ret=1 +checkprivate expiring.example 10.53.0.3 || ret=1 +checkprivate auto-nsec.example 10.53.0.3 || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "testing KEY lookup at CNAME (present) ($n)" +echo_i "check that 'rndc signing' without arguments is handled ($n)" ret=0 -dig_with_opts +noauth cnameandkey.secure.example. \ - @10.53.0.3 key >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth cnameandkey.secure.example. \ - @10.53.0.4 key >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "CNAME" dig.out.ns4.test$n >/dev/null && ret=1 +rndccmd 10.53.0.3 signing >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "testing KEY lookup at CNAME (not present) ($n)" +echo_i "check that 'rndc signing -list' without zone is handled ($n)" ret=0 -dig_with_opts +noauth cnamenokey.secure.example. \ - @10.53.0.3 key >dig.out.ns3.test$n || ret=1 -dig_with_opts +noauth cnamenokey.secure.example. \ - @10.53.0.4 key >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "CNAME" dig.out.ns4.test$n >/dev/null && ret=1 +rndccmd 10.53.0.3 signing -list >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "testing DNSKEY lookup via DNAME ($n)" +echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)" ret=0 -dig_with_opts a.dnameandkey.secure.example. \ - @10.53.0.3 dnskey >dig.out.ns3.test$n || ret=1 -dig_with_opts a.dnameandkey.secure.example. \ - @10.53.0.4 dnskey >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "CNAME" dig.out.ns4.test$n >/dev/null || ret=1 -grep "DNAME" dig.out.ns4.test$n >/dev/null || ret=1 +rndccmd 10.53.0.3 signing -clear >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "testing KEY lookup via DNAME ($n)" +echo_i "check that 'rndc signing -clear all' without zone is handled ($n)" ret=0 -dig_with_opts b.dnameandkey.secure.example. \ - @10.53.0.3 key >dig.out.ns3.test$n || ret=1 -dig_with_opts b.dnameandkey.secure.example. \ - @10.53.0.4 key >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "DNAME" dig.out.ns4.test$n >/dev/null || ret=1 +rndccmd 10.53.0.3 signing -clear all >/dev/null 2>&1 && ret=1 +rndccmd 10.53.0.3 status >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "check that named doesn't loop when all private keys are not available ($n)" +echo_i "check rndc signing -list output ($n)" ret=0 -lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true) -test "${lines:-1000}" -lt 15 || ret=1 +{ rndccmd 10.53.0.3 signing -list dynamic.example >signing.out.dynamic.example; } 2>&1 +grep -q "No signing records found" signing.out.dynamic.example || { + ret=1 + sed 's/^/ns3 /' signing.out.dynamic.example | cat_i +} n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "check against against missing nearest provable proof ($n)" -dig_with_opts +norec b.c.d.optout-tld. \ - @10.53.0.6 ds >dig.out.ds.ns6.test$n || ret=1 -nsec3=$(grep -c "IN.NSEC3" dig.out.ds.ns6.test$n || true) -[ "$nsec3" -eq 2 ] || ret=1 -dig_with_opts +norec b.c.d.optout-tld. \ - @10.53.0.6 A >dig.out.ns6.test$n || ret=1 -nsec3=$(grep -c "IN.NSEC3" dig.out.ns6.test$n || true) -[ "$nsec3" -eq 1 ] || ret=1 -dig_with_opts optout-tld. \ - @10.53.0.4 SOA >dig.out.soa.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.soa.ns4.test$n >/dev/null || ret=1 -dig_with_opts b.c.d.optout-tld. \ - @10.53.0.4 A >dig.out.ns4.test$n || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 +echo_i "check that a split dnssec dnssec-signzone work ($n)" +ret=0 +dig_with_opts soa split-dnssec.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "check that key id are logged when dumping the cache ($n)" +echo_i "check that a smart split dnssec dnssec-signzone work ($n)" ret=0 -rndc_dumpdb ns4 -grep "; key id = " ns4/named_dump.db.test$n >/dev/null || ret=1 +dig_with_opts soa split-smart.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1 +grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 +grep "ANSWER: 2," dig.out.ns4.test$n >/dev/null || ret=1 +grep "flags:.* ad[ ;]" dig.out.ns4.test$n >/dev/null || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "check KEYDATA records are printed in human readable form in key zone ($n)" -# force the managed-keys zone to be written out -rndccmd 10.53.0.4 managed-keys sync 2>&1 | sed 's/^/ns4 /' | cat_i -for i in 1 2 3 4 5 6 7 8 9; do - ret=0 - if test -f ns4/managed-keys.bind; then - grep KEYDATA ns4/managed-keys.bind >/dev/null \ - && grep "next refresh:" ns4/managed-keys.bind >/dev/null \ - && break - fi - ret=1 - sleep 1 -done +echo_i "testing soon-to-expire RRSIGs without a replacement private key ($n)" +ret=0 +dig_with_answeropts +nottlid expiring.example ns @10.53.0.3 | grep RRSIG >dig.out.ns3.test$n 2>&1 +# there must be a signature here +[ -s dig.out.ns3.test$n ] || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -copy_setports ns4/named4.conf.in ns4/named.conf -rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i -sleep 3 - -echo_i "check insecure delegation between static-stub zones ($n)" +echo_i "check that named doesn't loop when all private keys are not available ($n)" ret=0 -dig_with_opts ns insecure.secure.example \ - @10.53.0.4 >dig.out.ns4.1.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.1.test$n >/dev/null && ret=1 -dig_with_opts ns secure.example \ - @10.53.0.4 >dig.out.ns4.2.test$n || ret=1 -grep "SERVFAIL" dig.out.ns4.2.test$n >/dev/null && ret=1 +lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true) +test "${lines:-1000}" -lt 15 || ret=1 n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) @@ -2068,22 +433,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "check that split rrsigs are handled ($n)" -ret=0 -dig_with_opts split-rrsig soa @10.53.0.7 >dig.out.test$n || ret=1 -awk 'BEGIN { ok=0; } $4 == "SOA" { if ($7 > 1) ok=1; } END { if (!ok) exit(1); }' dig.out.test$n || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that not-at-zone-apex RRSIG(SOA) RRsets are removed from the zone after load ($n)" -ret=0 -dig_with_opts split-rrsig AXFR @10.53.0.7 >dig.out.test$n || ret=1 -grep -q "not-at-zone-apex.*RRSIG.*SOA" dig.out.test$n && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "check that CDS records are signed using KSK by dnssec-signzone ($n)" ret=0 dig_with_opts +noall +answer @10.53.0.2 cds cds.secure >dig.out.test$n @@ -2102,18 +451,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "checking that positive unknown NSEC3 hash algorithm does validate ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example SOA >dig.out.ns3.test$n -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example SOA >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "check that CDS records are signed using KSK by with dnssec-policy ($n)" ret=0 dig_with_opts +noall +answer @10.53.0.2 cds cds-auto.secure >dig.out.test$n @@ -2189,18 +526,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example SOA >dig.out.ns3.test$n -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example SOA >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "check that a non matching CDS record is accepted with a matching CDS record ($n)" ret=0 ( @@ -2227,16 +552,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "checking that negative unknown NSEC3 hash algorithm does not validate ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example A >dig.out.ns3.test$n -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example A >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: SERVFAIL," dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)" ret=0 dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey.secure >dig.out.test$n @@ -2255,16 +570,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example A >dig.out.ns3.test$n -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example A >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: SERVFAIL," dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)" ret=0 dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-auto.secure >dig.out.test$n @@ -2274,78 +579,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "checking that unknown DNSKEY algorithm validates as insecure ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unknown.example A >dig.out.ns3.test$n -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unknown.example A >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that unsupported DNSKEY algorithm validates as insecure ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported.example A >dig.out.ns3.test$n -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unsupported.example A >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 -grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 dnskey-unsupported.example/SOA)" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking EDE code 2 for unsupported DS digest ($n)" -ret=0 -dig_with_opts @10.53.0.4 a.ds-unsupported.example >dig.out.ns4.test$n || ret=1 -grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-256 ds-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking EDE code 1 for bad alg mnemonic ($n)" -ret=0 -dig_with_opts @10.53.0.4 badalg.secure.example >dig.out.ns4.test$n || ret=1 -grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP256SHA256 badalg.secure.example/NSEC)" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking both EDE code 1 and 2 for unsupported digest on one DNSKEY and alg on the other ($n)" -ret=0 -dig_with_opts @10.53.0.4 a.digest-alg-unsupported.example >dig.out.ns4.test$n || ret=1 -grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP384SHA384 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 -grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-384 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that unsupported DNSKEY algorithm is in DNSKEY RRset ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported-2.example DNSKEY >dig.out.test$n -grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1 -grep "dnskey-unsupported-2\.example\..*IN.*DNSKEY.*257 3 255" dig.out.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Check that a query for a domain that has a KSK that is not actively signing -# the DNSKEY RRset. This should not result in a broken trust chain if there is -# another KSK that is signing the DNSKEY RRset. -echo_i "checking that a secure chain with one active and one inactive KSK validates as secure ($n)" -ret=0 -dig_with_opts @10.53.0.4 a.lazy-ksk A >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - # TODO: test case for GL #1689. # If we allow the dnssec tools to use deprecated algorithms (such as RSAMD5) # we could write a test that signs a zone with supported and unsupported @@ -2371,17 +604,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)" -ret=0 -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-nsec3-unknown.example A >dig.out.ns3.test$n -dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-nsec3-unknown.example A >dig.out.ns4.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "check that CDNSKEY records are signed using KSK only when added by nsupdate ($n)" ret=0 keyid=$(cat ns2/cdnskey-update.secure.id) @@ -2425,22 +647,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -echo_i "check that a named managed zone that was signed 'in-the-future' is re-signed when loaded ($n)" -ret=0 -dig_with_opts managed-future.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "check that the view is logged in messages from the validator when using views ($n)" -ret=0 -grep "view rec: *validat" ns4/named.run >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - echo_i "check that DNAME at apex with NSEC3 is correctly signed (dnssec-signzone) ($n)" ret=0 dig_with_opts txt dname-at-apex-nsec3.example @10.53.0.3 >dig.out.ns3.test$n || ret=1 @@ -2472,164 +678,6 @@ n=$((n + 1)) test "$ret" -eq 0 || echo_i "failed" status=$((status + ret)) -# -# DNSSEC tests related to unsupported, disabled and revoked trust anchors. -# - -# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of -# them are good (enabled.managed, enabled.trusted, secure.managed, -# secure.trusted), and some of them are bad (disabled.managed, -# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted, -# unsupported.trusted). Make sure that the bad trust anchors are ignored. -# This is tested by looking for the corresponding lines in the logfile. -echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)" -ret=0 -grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1 -grep -q "ignoring static-key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1 -grep -q "ignoring static-key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1 -grep -q "ignoring initial-key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1 -grep -q "ignoring initial-key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1 -grep -q "ignoring initial-key for 'revoked\.managed\.': bad key type" ns8/named.run || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# The next two tests are fairly normal DNSSEC queries to signed zones with a -# default algorithm. First, a query is made against the server that is -# authoritative for the given zone (ns3). Second, a query is made against a -# resolver with trust anchors for the given zone (ns8). Both are expected to -# return an authentic data positive response. -echo_i "checking that a trusted key using a supported algorithm validates as secure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.secure.trusted A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.secure.trusted A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 -grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a managed key using a supported algorithm validates as secure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.secure.managed A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.secure.managed A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 -grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# The next two queries ensure that a zone signed with a DNSKEY with an unsupported -# algorithm will yield insecure positive responses. These trust anchors in ns8 are -# ignored and so this domain is treated as insecure. The AD bit should not be set -# in the response. -echo_i "checking that a trusted key using an unsupported algorithm validates as insecure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.unsupported.trusted A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.unsupported.trusted A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.trusted (cached))" dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a managed key using an unsupported algorithm validates as insecure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.unsupported.managed A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.unsupported.managed A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.managed (cached))" dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# The next two queries ensure that a zone signed with a DNSKEY that the nameserver -# has a disabled algorithm match for will yield insecure positive responses. -# These trust anchors in ns8 are ignored and so this domain is treated as insecure. -# The AD bit should not be set in the response. -echo_i "checking that a trusted key using a disabled algorithm validates as insecure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.disabled.trusted A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.disabled.trusted A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a managed key using a disabled algorithm validates as insecure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.disabled.managed A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.disabled.managed A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# The next two queries ensure that a zone signed with a DNSKEY that the -# nameserver has a disabled algorithm for, but for a different domain, will -# yield secure positive responses. Since "enabled.trusted." and -# "enabled.managed." do not match the "disable-algorithms" option, no -# special rules apply and these zones should validate as secure, with the AD -# bit set. -echo_i "checking that a trusted key using an algorithm disabled for another domain validates as secure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.enabled.trusted A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.enabled.trusted A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a managed key using an algorithm disabled for another domain validates as secure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.enabled.managed A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.enabled.managed A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# A configured revoked trust anchor is ignored and thus the two queries below -# should result in insecure responses, since no trust points for the -# "revoked.trusted." and "revoked.managed." zones are created. -echo_i "checking that a trusted key that is revoked validates as insecure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.revoked.trusted A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.revoked.trusted A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking that a managed key that is revoked validates as insecure ($n)" -ret=0 -dig_with_opts @10.53.0.3 a.revoked.managed A >dig.out.ns3.test$n -dig_with_opts @10.53.0.8 a.revoked.managed A >dig.out.ns8.test$n -grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1 -grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - ### ### Additional checks for when the KSK is offline. ### @@ -2924,216 +972,5 @@ for qtype in "SOA" "TXT"; do status=$((status + ret)) done -echo_i "checking secroots output with multiple views ($n)" -ret=0 -rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i -cp ns4/named.secroots named.secroots.test$n -check_secroots_layout named.secroots.test$n || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking validation succeeds during transition to signed ($n)" -ret=0 -dig_with_opts @10.53.0.4 inprogress A >dig.out.ns4.test$n || ret=1 -grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep 'A.10\.53\.0\.10' dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking excessive NSEC3 iteration warnings in named.run ($n)" -ret=0 -grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 50" ns2/named.run >/dev/null 2>&1 || ret=1 -grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 50" ns3/named.run >/dev/null 2>&1 || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Check that the validating resolver will fallback to insecure if the answer -# contains NSEC3 records with high iteration count. -echo_i "checking fallback to insecure when NSEC3 iterations is too high (nxdomain) ($n)" -ret=0 -dig_with_opts @10.53.0.2 does-not-exist.too-many-iterations >dig.out.ns2.test$n || ret=1 -dig_with_opts @10.53.0.4 does-not-exist.too-many-iterations >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 0, AUTHORITY: 8" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking fallback to insecure when NSEC3 iterations is too high (nodata) ($n)" -ret=0 -dig_with_opts @10.53.0.2 a.too-many-iterations txt >dig.out.ns2.test$n || ret=1 -dig_with_opts @10.53.0.4 a.too-many-iterations txt >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 0, AUTHORITY: 4" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard) ($n)" -ret=0 -dig_with_opts @10.53.0.2 wild.a.too-many-iterations >dig.out.ns2.test$n || ret=1 -dig_with_opts @10.53.0.4 wild.a.too-many-iterations >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep 'wild\.a\.too-many-iterations\..*A.10\.0\.0\.3' dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 2, AUTHORITY: 4" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -echo_i "checking fallback to insecure when NSEC3 iterations is too high (wildcard nodata) ($n)" -ret=0 -dig_with_opts @10.53.0.2 type100 wild.a.too-many-iterations >dig.out.ns2.test$n || ret=1 -dig_with_opts @10.53.0.4 type100 wild.a.too-many-iterations >dig.out.ns4.test$n || ret=1 -digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1 -grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 0, AUTHORITY: 8" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -test "$ret" -eq 0 || echo_i "failed" -status=$((status + ret)) - -# Check that a query against a validating resolver succeeds when there is -# a negative cache entry with trust level "pending" for the DS. Prime -# with a +cd DS query to produce the negative cache entry, then send a -# query that uses that entry as part of the validation process. [GL #3279] -echo_i "check that pending negative DS cache entry validates ($n)" -ret=0 -dig_with_opts @10.53.0.4 +cd insecure2.example. ds >dig.out.prime.ns4.test$n || ret=1 -grep "flags: qr rd ra cd;" dig.out.prime.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1 -grep "ANSWER: 0, AUTHORITY: 4, " dig.out.prime.ns4.test$n >/dev/null || ret=1 -dig_with_opts @10.53.0.4 a.insecure2.example. a >dig.out.ns4.test$n || ret=1 -grep "ANSWER: 1, AUTHORITY: 1, " dig.out.ns4.test$n >/dev/null || ret=1 -grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1 -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking NSEC3 nxdomain response closest encloser with 0 ENT ($n)" -ret=0 -dig_with_opts @10.53.0.4 b.b.b.b.b.a.nsec3.example. >dig.out.ns4.test$n -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# closest encloser (a.nsec3.example) -pat1="^6OVDUHTN094ML2PV8AN90U0DPU823GH2\.nsec3\.example\..*NSEC3 1 0 0 - 7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4 A RRSIG\$" -grep "$pat1" dig.out.ns4.test$n >/dev/null || ret=1 -# no QNAME proof (b.a.nsec3.example / DSPF4R9UKOEPJ9O34E1H4539LSOTL14E) -pat2="^CG2DVCNE20EKU1PDRLMI2L4DGC2FO1H3\.nsec3\.example\..*NSEC3 1 0 0 - EF2S05SGK1IR2K5SKMFIRERGQCLMR18M A RRSIG\$" -grep "$pat2" dig.out.ns4.test$n >/dev/null || ret=1 -# no WILDCARD proof (*.a.nsec3.example / TFGQ60S97BS31IT1EBEDO63ETM0T5JFA) -pat3="^R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\.nsec3\.example\..*NSEC3 1 0 0 - VH656EQUD4J02OFVSO4GKOK5D02MS1TL NS DS RRSIG\$" -grep "$pat3" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking NSEC3 nxdomain response closest encloser with 1 ENTs ($n)" -ret=0 -dig_with_opts @10.53.0.4 b.b.b.b.b.a.a.nsec3.example. >dig.out.ns4.test$n -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# closest encloser (a.a.nsec3.example) -pat1="^NGCJFSOLJUUE27PFNQNJIME4TQ0OU2DH\.nsec3\.example\..*NSEC3 1 0 0 - R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\$" -grep "$pat1" dig.out.ns4.test$n >/dev/null || ret=1 -# no QNAME proof (b.a.a.nsec3.example / V8I8SAIIVC3HOVMOVENSDRA6ATDCEMJI) -pat2="^R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\.nsec3\.example\..*NSEC3 1 0 0 - VH656EQUD4J02OFVSO4GKOK5D02MS1TL NS DS RRSIG\$" -grep "$pat2" dig.out.ns4.test$n >/dev/null || ret=1 -# no WILDCARD proof (*.a.a.nsec3.example / V7JNNDJ4NLRIU195FRB7DLUCSLU4LLFM) -pat3="^R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\.nsec3\.example\..*NSEC3 1 0 0 - VH656EQUD4J02OFVSO4GKOK5D02MS1TL NS DS RRSIG\$" -grep "$pat3" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking NSEC3 nxdomain response closest encloser with 2 ENTs ($n)" -ret=0 -dig_with_opts @10.53.0.4 b.b.b.b.b.a.a.a.nsec3.example. >dig.out.ns4.test$n -grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1 -# closest encloser (a.a.a.nsec3.example) -pat1="^H7RHPDCHSVVRAND332F878C8AB6IBJQV\.nsec3\.example\..*NSEC3 1 0 0 - K8IG76R2UPQ13IKFO49L7IB9JRVB6QJI\$" -grep "$pat1" dig.out.ns4.test$n >/dev/null || ret=1 -# no QNAME proof (b.a.a.a.nsec3.example / 18Q8D89RM8GGRSSOPFRB05QS6VEGB1P4) -pat2="^VH656EQUD4J02OFVSO4GKOK5D02MS1TL\.nsec3\.example\..*NSEC3 1 0 0 - 1HARMGSKJH0EBU2EI2OJIKTDPIQA6KBI NS DS RRSIG\$" -grep "$pat2" dig.out.ns4.test$n >/dev/null || ret=1 -# no WILDCARD proof (*.a.a.a.nsec3.example / 8113LDMSEFPUAG4VGFF1C8KLOUT4Q6PH) -pat3="^7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4\.nsec3\.example\..*NSEC3 1 0 0 - BEJ5GMQA872JF4DAGQ0R3O5Q7A2O5S9L A RRSIG\$" -grep "$pat3" dig.out.ns4.test$n >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking validator behavior with mismatching NS ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -$DIG +tcp +cd -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1 -grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2" dig.out.ns4.test$n.1 >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.1 >/dev/null && ret=1 -$DIG +tcp +cd +dnssec -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1 -grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2" dig.out.ns4.test$n.2 >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.2 >/dev/null && ret=1 -$DIG +tcp +dnssec -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1 -grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns4.test$n.3 >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.3 >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking that a insecure negative response where there is a NSEC without a RRSIG succeeds ($n)" -ret=0 -# check server preconditions -dig_with_opts +notcp @10.53.0.10 nsec-rrsigs-stripped. TXT +dnssec >dig.out.ns10.test$n -grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1 -grep "QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1" dig.out.ns10.test$n >/dev/null || ret=1 -grep "IN.RRSIG.NSEC" dig.out.ns10.test$n >/dev/null && ret=1 -# check resolver succeeds -dig_with_opts @10.53.0.4 nsec-rrsigs-stripped. TXT +dnssec >dig.out.ns4.test$n -grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1 -grep "QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1" dig.out.ns4.test$n >/dev/null || ret=1 -grep "IN.RRSIG.NSEC" dig.out.ns4.test$n >/dev/null && ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking validating forwarder behavior with mismatching NS ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -$DIG +tcp +cd -p "$PORT" -t ns inconsistent @10.53.0.9 >dig.out.ns9.test$n.1 || ret=1 -grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns9.test$n.1 >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns9.test$n.1 >/dev/null && ret=1 -$DIG +tcp +cd +dnssec -p "$PORT" -t ns inconsistent @10.53.0.9 >dig.out.ns9.test$n.2 || ret=1 -grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns9.test$n.2 >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns9.test$n.2 >/dev/null && ret=1 -$DIG +tcp +dnssec -p "$PORT" -t ns inconsistent @10.53.0.9 >dig.out.ns9.test$n.3 || ret=1 -grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns9.test$n.3 >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns9.test$n.3 >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - -echo_i "checking forwarder CD behavior (DS mismatch and local trust anchor) ($n)" -ret=0 -rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i -# confirm invalid DS produces SERVFAIL in resolver -$DIG +tcp +dnssec -p "$PORT" @10.53.0.4 localkey.example soa >dig.out.ns4.test$n || ret=1 -grep "status: SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1 -# check that lookup using forwarder succeeds and that SERVFAIL was received -nextpart ns9/named.run >/dev/null -$DIG +tcp +dnssec -p "$PORT" @10.53.0.9 localkey.example soa >dig.out.ns9.test$n || ret=1 -grep "status: NOERROR" dig.out.ns9.test$n >/dev/null || ret=1 -grep "flags:.*ad.*QUERY" dig.out.ns9.test$n >/dev/null || ret=1 -nextpart ns9/named.run | grep 'status: SERVFAIL' >/dev/null || ret=1 -n=$((n + 1)) -if [ "$ret" -ne 0 ]; then echo_i "failed"; fi -status=$((status + ret)) - echo_i "exit status: $status" [ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/dnssec/tests_sh_dnssec.py b/bin/tests/system/dnssec/tests_sh_dnssec.py index 854c15424d3..9f9cc76bf68 100644 --- a/bin/tests/system/dnssec/tests_sh_dnssec.py +++ b/bin/tests/system/dnssec/tests_sh_dnssec.py @@ -165,9 +165,11 @@ pytestmark = pytest.mark.extra_artifacts( "ns4/named_dump.db.*", "ns5/broken.conf", "ns5/revoked.conf", + "ns5/many-trusted.conf", + "ns5/many-managed.conf", "ns6/optout-tld.db", - "ns7/split-rrsig.db", - "ns7/split-rrsig.db.unsplit", + "ns6/split-rrsig.db", + "ns6/split-rrsig.db.unsplit", "ns9/trusted-localkey.conf", ] ) diff --git a/bin/tests/system/dnssec/tests_validation.py b/bin/tests/system/dnssec/tests_validation.py new file mode 100644 index 00000000000..f0d132b9dca --- /dev/null +++ b/bin/tests/system/dnssec/tests_validation.py @@ -0,0 +1,1606 @@ +# 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 os +import re +import shutil +import time + +from dns import edns, flags, name, rcode, rdataclass, rdatatype + +import pytest + +pytest.importorskip("dns", minversion="2.0.0") +import isctest +import isctest.mark +from isctest.util import param + + +# helper functions +def grep_q(regex, filename): + with open(filename, "r", encoding="utf-8") as f: + blob = f.read().splitlines() + results = [x for x in blob if re.search(regex, x)] + return len(results) != 0 + + +def getfrom(file): + with open(file, encoding="utf-8") as f: + return f.read().strip() + + +@pytest.mark.requires_zones_loaded("ns2", "ns3") +@pytest.mark.parametrize( + "qname, qtype", + [ + param("a.example.", "A"), + param("rfc2535.example.", "SOA"), + ], +) +def test_load_transfer(qname, qtype): + # check that we can load and transfer zone + msg = isctest.query.create(qname, qtype) + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.3") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res1) + + +def test_insecure_glue(): + # check that for a query against a validating resolver where the + # authoritative zone is unsigned (insecure delegation), glue is returned + # in the additional section + msg = isctest.query.create("a.insecure.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.rr_count_eq(res.answer, 1) + isctest.check.rr_count_eq(res.authority, 1) + isctest.check.rr_count_eq(res.additional, 1) + assert str(res.additional[0].name) == "ns.insecure.example." + addrs = [str(a) for a in res.additional[0]] + assert "10.53.0.3" in addrs + + +def test_adflag(): + # compare auth and recursive answers + msg = isctest.query.create("a.example", "A", dnssec=False) + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + + # check no AD flag in authoritative response + isctest.check.noadflag(res1) + + # check validating resolver sends AD=1 if the client sent AD=1 + isctest.check.adflag(res2) + + # check that AD=0 unless the client sent AD=1 + msg = isctest.query.create("a.example", "A", dnssec=False, ad=False) + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noadflag(res2) + + +def test_secure_root(servers): + # check that a query for a secure root validates + msg = isctest.query.create(".", "KEY") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + # check that "rndc secroots" dumps the trusted keys + ns4 = servers["ns4"] + key = int(getfrom("ns1/managed.key.id")) + alg = os.environ["DEFAULT_ALGORITHM"] + expected = f"./{alg}/{key} ; static" + response = ns4.rndc("secroots -", log=False).splitlines() + assert expected in response + assert len(response) == 10 + + +def test_positive_validation_nsec(): + # positive answer + msg = isctest.query.create("a.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # wildcard + msg = isctest.query.create("a.wild.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + assert str(res2.authority[0].name) == "*.wild.example." + assert res2.authority[0].rdtype == rdatatype.NSEC + nsecs = [str(a).split(" ", maxsplit=1)[0] for a in res2.authority[0]] + assert "z.example." in nsecs + assert res2.authority[1].rdtype == rdatatype.RRSIG + assert res2.authority[1].covers == rdatatype.NSEC + + # mixed case + for rrtype in ["a", "txt", "aaaa", "loc"]: + msg = isctest.query.create("mixedcase.secure.example", rrtype) + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + +def test_positive_validation_nsec3(): + # positive answer + msg = isctest.query.create("a.nsec3.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + # wildcard + msg = isctest.query.create("a.wild.nsec3.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + isctest.check.rr_count_eq(res2.authority, 4) + + # unknown NSEC3 hash algorithm + msg = isctest.query.create("nsec3-unknown.example", "SOA", dnssec=False) + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + isctest.check.rr_count_eq(res2.answer, 1) + + +def test_positive_validation_optout(): + # positive answer + msg = isctest.query.create("a.optout.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # wildcard + msg = isctest.query.create("a.wild.optout.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # unknown NSEC3 hash algorithm + msg = isctest.query.create("optout-unknown.example", "SOA", dnssec=False) + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + isctest.check.rr_count_eq(res2.answer, 1) + + +def answer_has(r, rdtype): + return bool([r for r in r.answer if r.rdtype == rdtype]) + + +def test_chain_validation(): + # check validation of ANY response + msg = isctest.query.create("foo.example", "ANY") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.rr_count_eq(res2.answer, 6) # 2 records, 1 NSEC, 3 RRSIGs + + # check validation of CNAME response + msg = isctest.query.create("cname1.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.rr_count_eq(res2.answer, 4) # CNAME, TXT, 2 RRSIGs + + # check validation of DNAME response + msg = isctest.query.create("foo.dname1.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.rr_count_eq(res2.answer, 5) # DNAME, TXT, 2 RRSIGs, synth CNAME + + # check validation of CNAME response to ANY query + msg = isctest.query.create("cname2.example", "ANY") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.rr_count_eq(res2.answer, 4) # CNAME, NSEC, 2 RRSIGs + + # check validation of DNAME response to ANY query + msg = isctest.query.create("foo.dname2.example", "ANY") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.rr_count_eq(res2.answer, 3) # DNAME, RSRIG, synth CNAME + + # check bad CNAME signature is caught after +CD query + msg = isctest.query.create("bad-cname.example", "A", dnssec=False, cd=True) + # query once with CD to prime the cache + res = isctest.query.tcp(msg, "10.53.0.4") + # query again with CD, bogus pending data should be returned + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + assert "a.example." in str(res.answer[0]) + assert "10.0.0.1" in str(res.answer[1]) + # query again without CD, bogus data should be rejected + msg = isctest.query.create("bad-cname.example", "A", dnssec=False) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + + # check bad DNAME signature is caught after +CD query + msg = isctest.query.create("a.bad-dname.example", "A", dnssec=False, cd=True) + # query once with CD to prime the cache + res = isctest.query.tcp(msg, "10.53.0.4") + # query again with CD, bogus pending data should be returned + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + assert "example." in str(res.answer[0]) + assert "a.example." in str(res.answer[1]) + assert "10.0.0.1" in str(res.answer[2]) + # query again without CD, bogus data should be rejected + msg = isctest.query.create("a.bad-dname.example", "A", dnssec=False) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + + # check DNSKEY lookup via CNAME + msg = isctest.query.create("cnameandkey.secure.example", "DNSKEY") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + assert answer_has(res2, rdatatype.CNAME) + + # check KEY lookup via CNAME + msg = isctest.query.create("cnameandkey.secure.example", "KEY") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + assert not answer_has(res2, rdatatype.CNAME) + + # check KEY lookup via CNAME (not present) + msg = isctest.query.create("cnamenokey.secure.example", "KEY") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + assert not answer_has(res2, rdatatype.CNAME) + + # check DNSKEY lookup via DNAME + msg = isctest.query.create("a.dnameandkey.secure.example", "DNSKEY") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + assert answer_has(res2, rdatatype.DNAME) + + # check KEY lookup via DNAME + msg = isctest.query.create("a.dnameandkey.secure.example", "KEY") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + assert answer_has(res2, rdatatype.DNAME) + + +@isctest.mark.rsasha1 +def test_signing_algorithms_rsasha1(): + # rsasha1 (should work with FIPS mode we're as only validating) + msg = isctest.query.create("a.rsasha1.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # rsasha1 (1024 bits) NSEC + msg = isctest.query.create("a.rsasha1-1024.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + +def test_signing_algorithms(): + # rsasha256 + msg = isctest.query.create("a.rsasha256.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # rsasha512 + msg = isctest.query.create("a.rsasha512.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # KSK-only DNSKEY + msg = isctest.query.create("a.kskonly.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + +def test_private_algorithms(servers): + # positive answer, private algorithm + msg = isctest.query.create("a.rsasha256oid.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # positive answer, unknown private algorithm + msg = isctest.query.create("a.unknownoid.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noadflag(res2) + + # positive answer, extra ds for private algorithm + msg = isctest.query.create("a.extradsoid.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # positive anwer, extra ds for unknown private algorithm + ns4 = servers["ns4"] + with ns4.watch_log_from_here() as watcher: + msg = isctest.query.create("a.extradsunknownoid.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res1) + isctest.check.servfail(res2) + watcher.wait_for_line( + "No DNSKEY for extradsunknownoid.example/DS with PRIVATEOID" + ) + + +@isctest.mark.extended_ds_digest +def test_private_algorithms_extended_ds(): + # check positive validation with extra ds using extended digest + # type for unknown private algorithm + msg = isctest.query.create("a.extended-ds-unknown-oid.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + +def test_negative_validation_nsec(): + # nxdomain + msg = isctest.query.create("q.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.adflag(res2) + + # nodata + msg = isctest.query.create("a.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.empty_answer(res2) + isctest.check.adflag(res2) + + # negative wildcard + msg = isctest.query.create("b.wild.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + +def test_negative_validation_nsec3(): + # nxdomain + msg = isctest.query.create("q.nsec3.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.adflag(res2) + + # nodata + msg = isctest.query.create("a.nsec3.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.empty_answer(res2) + isctest.check.adflag(res2) + + # negative wildcard + msg = isctest.query.create("b.wild.nsec3.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + # check NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters + msg = isctest.query.create("non-exist.badparam", "A") + res = isctest.query.tcp(msg, "10.53.0.2") + isctest.check.nxdomain(res) + + # check negative unknown NSEC3 hash algorithm does not validate + msg = isctest.query.create("nsec3-unknown.example", "A", dnssec=False) + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res1) + isctest.check.servfail(res2) + + +def test_excessive_nsec3_iterations(): + assert grep_q( + "zone too-many-iterations/IN: excessive NSEC3PARAM iterations", "ns2/named.run" + ) + assert grep_q( + "zone too-many-iterations/IN: excessive NSEC3PARAM iterations", "ns3/named.run" + ) + + # check fallback to insecure with NSEC3 iterations is too high + msg = isctest.query.create("does-not-exist.too-many-iterations", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noadflag(res2) + isctest.check.rr_count_eq(res2.answer, 0) + isctest.check.rr_count_eq(res2.authority, 8) + + # check fallback to insecure with NSEC3 iterations is too high (nodata) + msg = isctest.query.create("a.too-many-iterations", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noadflag(res2) + isctest.check.rr_count_eq(res2.answer, 0) + isctest.check.rr_count_eq(res2.authority, 4) + + # check fallback to insecure with NSEC3 iterations is too high (wildcard) + msg = isctest.query.create("wild.a.too-many-iterations", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noadflag(res2) + isctest.check.rr_count_eq(res2.answer, 2) + isctest.check.rr_count_eq(res2.authority, 4) + a, _ = res2.answer + assert str(a.name) == "wild.a.too-many-iterations." + assert str(a[0]) == "10.0.0.3" + + # check fallback to insecure with high NSEC3 iterations (wildcard nodata) + msg = isctest.query.create("wild.a.too-many-iterations", 100) + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noadflag(res2) + isctest.check.rr_count_eq(res2.authority, 8) + + +def test_auth_nsec3(): + # nxdomain response, closest encloser with 0 empty non-terminals + msg = isctest.query.create("b.b.b.b.b.a.nsec3.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.nxdomain(res) + # closest encloser (a.nsec3.example): + rrset = res.get_rrset( + res.authority, + name.from_text("6OVDUHTN094ML2PV8AN90U0DPU823GH2.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "NSEC3 missing from AUTHORITY: " + str(res) + assert "7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4" in str(rrset[0]).upper() + # no QNAME (b.a.nsec3.example/DSPF4R9UKOEPJ9O34E1H4539LSOTL14E) + rrset = res.get_rrset( + res.authority, + name.from_text("BEJ5GMQA872JF4DAGQ0R3O5Q7A2O5S9L.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res) + assert "EF2S05SGK1IR2K5SKMFIRERGQCLMR18M" in str(rrset[0]).upper() + # no WILDCARD (*.a.nsec3.example/TFGQ60S97BS31IT1EBEDO63ETM0T5JFA) + rrset = res.get_rrset( + res.authority, + name.from_text("R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res) + assert "VH656EQUD4J02OFVSO4GKOK5D02MS1TL" in str(rrset[0]).upper() + + # nxdomain response, closest encloser with 1 ENT + msg = isctest.query.create("b.b.b.b.b.a.a.nsec3.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.nxdomain(res) + # closest encloser (a.a.nsec3.example): + rrset = res.get_rrset( + res.authority, + name.from_text("NGCJFSOLJUUE27PFNQNJIME4TQ0OU2DH.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res) + assert "R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q" in str(rrset[0]).upper() + # noqname (b.a.a.nsec3.example): + rrset = res.get_rrset( + res.authority, + name.from_text("R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res) + assert "VH656EQUD4J02OFVSO4GKOK5D02MS1TL" in str(rrset[0]).upper() + # no wildcard (*.a.a.nsec3.example/V7JNNDJ4NLRIU195FRB7DLUCSLU4LLFM) + # is covered by the noqname proof in this case + + # nxdomain response, closest encloser with 2 ENTs + msg = isctest.query.create("b.b.b.b.b.a.a.a.nsec3.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.nxdomain(res) + # closest encloser (a.a.a.nsec3.example): + rrset = res.get_rrset( + res.authority, + name.from_text("H7RHPDCHSVVRAND332F878C8AB6IBJQV.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res) + assert "K8IG76R2UPQ13IKFO49L7IB9JRVB6QJI" in str(rrset[0]).upper() + # noqname (b.a.a.a.nsec3.example/18Q8D89RM8GGRSSOPFRB05QS6VEGB1P4) + rrset = res.get_rrset( + res.authority, + name.from_text("0T7VH688AEK0612T69V8692OCMJD50M4.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res) + assert "1HARMGSKJH0EBU2EI2OJIKTDPIQA6KBI" in str(rrset[0]).upper() + # no WILDCARD (*.a.a.a.nsec3.example/8113LDMSEFPUAG4VGFF1C8KLOUT4Q6PH) + rrset = res.get_rrset( + res.authority, + name.from_text("7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4.nsec3.example."), + rdataclass.IN, + rdatatype.NSEC3, + ) + assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res) + assert "BEJ5GMQA872JF4DAGQ0R3O5Q7A2O5S9L" in str(rrset[0]).upper() + + +def test_negative_validation_optout(): + # nxdomain + msg = isctest.query.create("q.optout.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + + # nodata + msg = isctest.query.create("a.optout.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.empty_answer(res2) + isctest.check.adflag(res2) + + # negative wildcard + msg = isctest.query.create("b.wild.optout.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # empty NODATA + msg = isctest.query.create("empty.optout.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # (rt22007 regression tests:) + # check optout NSEC3 referral with only insecure delegatons + msg = isctest.query.create("delegation.single-nsec3", "A") + res = isctest.query.tcp(msg, "10.53.0.2") + isctest.check.noerror(res) + for rrset in res.authority: + if ( + rrset.rdtype != rdatatype.NSEC3 + or "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" not in rrset.name + ): + continue + assert "1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" in str(rrset[0]) + + # check optout NSEC3 NXDOMAIN with only insecure delegatons + msg = isctest.query.create("nonexist.single-nsec3", "A") + res = isctest.query.tcp(msg, "10.53.0.2") + isctest.check.nxdomain(res) + for rrset in res.authority: + if ( + rrset.rdtype != rdatatype.NSEC3 + or "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" not in rrset.name + ): + continue + assert "1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" in str(rrset[0]) + + # check optout NSEC3 NODATA with only insecure delegatons + msg = isctest.query.create("single-nsec3", "A") + res = isctest.query.tcp(msg, "10.53.0.2") + isctest.check.noerror(res) + for rrset in res.authority: + if ( + rrset.rdtype != rdatatype.NSEC3 + or "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" not in rrset.name + ): + continue + assert "1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" in str(rrset[0]) + + # check negative unknown NSEC3-OPTOUT hash algorithm does not validate + msg = isctest.query.create("optout-unknown.example", "A", dnssec=False) + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res1) + isctest.check.servfail(res2) + + +def test_cache(servers): + ns4 = servers["ns4"] + + # check that key id's are logged when dumping the cache + ns4.rndc("dumpdb -cache", log=False) + assert grep_q("; key id = ", "ns4/named_dump.db") + + # check for RRSIG covered type in negative cache + assert grep_q("; example. RRSIG NSEC ", "ns4/named_dump.db") + + # check validated data are not cached longer than originalttl + msg = isctest.query.create("a.ttlpatch.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.rr_count_eq(res1.answer, 2) + isctest.check.rr_count_eq(res2.answer, 2) + for rrset in res1.answer: + assert rrset.ttl <= 3600 + for rrset in res2.answer: + assert rrset.ttl <= 300 + + # query for a record, then follow it with a query for the + # corresponding RRSIG, check that it's answered from the cache + msg = isctest.query.create("normalthenrrsig.secure.example", "A") + isctest.query.tcp(msg, "10.53.0.4") + + msg = isctest.query.create("normalthenrrsig.secure.example", "RRSIG") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.raflag(res2) + + # check direct query for RRSIG: if it's not cached with other records, + # it should result in an empty response. + msg = isctest.query.create("rrsigonly.secure.example", "RRSIG") + res1 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.empty_answer(res1) + isctest.check.noraflag(res1) + + # check that a DNSKEY query with no data still gets cached + msg = isctest.query.create("insecure.example", "DNSKEY") + res1 = isctest.query.tcp(msg, "10.53.0.4") + time.sleep(1) # give the TTL time to change + res2 = isctest.query.tcp(msg, "10.53.0.4") + if res1.authority[0].ttl == res2.authority[0].ttl: + time.sleep(1) + res2 = isctest.query.tcp(msg, "10.53.0.4") + assert res1.authority[0].ttl != res2.authority[0].ttl + + +def test_insecure_proof_nsec(servers): + # 1-server positive + msg = isctest.query.create("a.insecure.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # 1-server negative + msg = isctest.query.create("q.insecure.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + + # 1-server negative with SOA hack + msg = isctest.query.create("r.insecure.example", "SOA") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + assert res2.authority[0].rdtype == rdatatype.SOA + assert res2.authority[0].ttl == 0 + + # 2-server positive + msg = isctest.query.create("a.insecure.secure.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # 2-server negative + msg = isctest.query.create("q.insecure.secure.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + + # 2-server negative with SOA hack + msg = isctest.query.create("r.insecure.secure.example", "SOA") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + + # insecurity proof using negative cache + ns4 = servers["ns4"] + ns4.rndc("flush", log=False) + msg = isctest.query.create("insecure.example", "DS", cd=True) + isctest.query.tcp(msg, "10.53.0.4") + + def query_and_check_nxdomain(): + msg = isctest.query.create("nonexistent.insecure.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.nxdomain(res) + return True + + isctest.run.retry_with_timeout(query_and_check_nxdomain, 20) + + # check insecure negative response with an unsigned NSEC + # first try the auth server... + msg = isctest.query.create("nsec-rrsigs-stripped", "TXT") + res1 = isctest.query.udp(msg, "10.53.0.10") + isctest.check.noerror(res1) + isctest.check.empty_answer(res1) + isctest.check.rr_count_eq(res1.authority, 2) + isctest.check.rr_count_eq(res1.additional, 0) + # make sure there's no RRSIG(NSEC) + for rrset in res1.authority: + assert rrset.rdtype != rdatatype.RRSIG or rrset.covers != rdatatype.NSEC + # now try the resolver + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noadflag(res2) + + +def test_insecure_proof_nsec3(): + # 1-server + msg = isctest.query.create("a.insecure.nsec3.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # 1-server negative + msg = isctest.query.create("q.insecure.nsec3.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + + # 1-server negative with SOA hack + msg = isctest.query.create("r.insecure.nsec3.example", "SOA") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + assert res2.authority[0].rdtype == rdatatype.SOA + assert res2.authority[0].ttl == 0 + + +def test_insecure_proof_optout(): + # 1-server + msg = isctest.query.create("a.insecure.optout.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # 1-server negative + msg = isctest.query.create("q.insecure.optout.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + + # 1-server negative with SOA hack + msg = isctest.query.create("r.insecure.optout.example", "SOA") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.noadflag(res2) + assert res2.authority[0].rdtype == rdatatype.SOA + assert res2.authority[0].ttl == 0 + + +def test_below_cname(): + # check insecure zone below a cname resolves + msg = isctest.query.create("insecure.below-cname.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + isctest.check.rr_count_eq(res.answer, 1) + + # check secure zone below a cname resolves and validates + msg = isctest.query.create("secure.below-cname.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + isctest.check.rr_count_eq(res.answer, 2) + + +@pytest.mark.parametrize( + "qname", + [ + "a.secure.example", # NSEC/NSEC + "a.nsec3.example", # NSEC/NSEC3 + "a.optout.example", # NSEC/OPTOUT + "a.secure.nsec3.example", # NSEC3/NSEC + "a.nsec3.nsec3.example", # NSEC3/NSEC3 + "a.optout.nsec3.example", # NSEC3/OPTOUT + "a.secure.optout.example", # OPTOUT/NSEC + "a.nsec3.optout.example", # OPTOUT/NSEC3 + "a.optout.optout.example", # OPTOUT/OPTOUT + ], +) +def test_positive_validation_multistage(qname): + msg = isctest.query.create(qname, "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + +def test_validation_recovery(servers): + ns2 = servers["ns2"] + ns4 = servers["ns4"] + + # check recovery from spoofed server address. + # prime cache with spoofed address records... + msg = isctest.query.create("target.peer-ns-spoof", "A", cd=True) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + ns4.rndc("dumpdb", log=False) + grep_q("10.53.0.100", "ns4/named_dump.db") + + # then reload server with properly signed zone + shutil.copyfile( + "ns2/peer.peer-ns-spoof.db.next", "ns2/peer.peer-ns-spoof.db.signed" + ) + with ns2.watch_log_from_here() as watcher: + ns2.rndc("reload peer.peer-ns-spoof", log=False) + watcher.wait_for_line("zone peer.peer-ns-spoof/IN: loaded serial 2000042408") + + # and check we can resolve with the correct server address + msg = isctest.query.create("test.target.peer-ns-spoof", "TXT") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.nxdomain(res) + isctest.check.adflag(res) + + # check recovery from stripped DNSKEY RRSIG. + # prime cache with spoofed address records... + msg = isctest.query.create("dnskey-rrsigs-stripped", "DNSKEY", cd=True) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.rr_count_eq(res.answer, 2) + + # then reload server with properly signed zone + shutil.copyfile( + "ns2/dnskey-rrsigs-stripped.db.next", "ns2/dnskey-rrsigs-stripped.db.signed" + ) + with ns2.watch_log_from_here() as watcher: + ns2.rndc("reload dnskey-rrsigs-stripped", log=False) + watcher.wait_for_line( + "zone dnskey-rrsigs-stripped/IN: loaded serial 2000042408" + ) + + # and check we can now resolve with the correct server address + msg = isctest.query.create("b.dnskey-rrsigs-stripped", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # check recovery from stripped DS RRSIG. + # prime cache with spoofed address records... + msg = isctest.query.create("child.ds-rrsigs-stripped", "DS", cd=True) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.rr_count_eq(res.answer, 1) + + # then reload server with properly signed zone + shutil.copyfile( + "ns2/ds-rrsigs-stripped.db.next", "ns2/ds-rrsigs-stripped.db.signed" + ) + with ns2.watch_log_from_here() as watcher: + ns2.rndc("reload ds-rrsigs-stripped", log=False) + watcher.wait_for_line("zone ds-rrsigs-stripped/IN: loaded serial 2000042408") + + # and check we can now resolve with the correct server address + msg = isctest.query.create("b.child.ds-rrsigs-stripped", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + # check recovery with mismatching NS + ns4.rndc("flush", log=False) + msg = isctest.query.create("inconsistent", "NS", dnssec=False, cd=True) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noadflag(res) + isctest.check.rr_count_eq(res.answer, 1) + isctest.check.rr_count_eq(res.additional, 1) + + msg = isctest.query.create("inconsistent", "NS", cd=True) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noadflag(res) + isctest.check.rr_count_eq(res.answer, 1) + isctest.check.rr_count_eq(res.additional, 1) + + msg = isctest.query.create("inconsistent", "NS") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.adflag(res) + isctest.check.rr_count_eq(res.answer, 3) + isctest.check.rr_count_eq(res.additional, 0) + + +def test_failed_validation(): + # bogus zone + msg = isctest.query.create("a.bogus.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + + # missing key record + msg = isctest.query.create("a.b.keyless.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + + +def test_revoked_key(): + # validation should succeed if a revoked key is encountered + msg = isctest.query.create("revkey.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + +def test_standby_key(): + # check that a secure chain with one active and one inactive KSK + # validates as secure + msg = isctest.query.create("a.lazy-ksk", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + +def test_transitions(): + # check that a zone finishing transitioning from one algorithm + # to another validates secure + msg = isctest.query.create("algroll", "NS") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + # check that validation yields insecure during transition to signed + msg = isctest.query.create("inprogress", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + a, _ = res.answer + assert str(a[0]) == "10.53.0.10" + + +def test_validating_forwarder(servers): + ns9 = servers["ns9"] + ns4 = servers["ns4"] + + # check validating forwarder behavior with mismatching NS + ns4.rndc("flush", log=False) + msg = isctest.query.create("inconsistent", "NS", dnssec=False, cd=True) + res = isctest.query.tcp(msg, "10.53.0.9") + isctest.check.noerror(res) + isctest.check.rr_count_eq(res.answer, 1) + isctest.check.rr_count_eq(res.additional, 0) + isctest.check.noadflag(res) + + msg = isctest.query.create("inconsistent", "NS", cd=True) + res = isctest.query.tcp(msg, "10.53.0.9") + isctest.check.rr_count_eq(res.additional, 0) + isctest.check.noadflag(res) + isctest.check.rr_count_eq(res.answer, 1) + isctest.check.rr_count_eq(res.authority, 0) + isctest.check.rr_count_eq(res.additional, 0) + + msg.flags &= ~flags.CD + res = isctest.query.tcp(msg, "10.53.0.9") + isctest.check.rr_count_eq(res.answer, 3) + isctest.check.rr_count_eq(res.authority, 0) + isctest.check.rr_count_eq(res.additional, 0) + isctest.check.adflag(res) + + # check validating forwarder sends CD to validate with a local trust anchor + ns4.rndc("flush", log=False) + msg = isctest.query.create("localkey.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + + with ns9.watch_log_from_here() as watcher: + res = isctest.query.tcp(msg, "10.53.0.9") + isctest.check.noerror(res) + isctest.check.adflag(res) + watcher.wait_for_line("status: SERVFAIL") + + +def test_expired_signatures(servers): + # check expired signatures are still in place when updates are disabled + msg = isctest.query.create("expired.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.3") + soa, sigs = res.answer + assert sigs + + # check expired signatures do not validate + msg = isctest.query.create("expired.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.3") + rrsig = res.get_rrset( + res.answer, + name.from_text("expired.example."), + rdataclass.IN, + rdatatype.RRSIG, + rdatatype.SOA, + ) + assert rrsig, "expected RRSIG(SOA) missing from AUTHORITY: " + str(rrsig) + isctest.check.rr_count_eq(res.answer, 2) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + isctest.check.noadflag(res) + if hasattr(res, "extended_errors"): + assert res.extended_errors()[0].code == edns.EDECode.SIGNATURE_EXPIRED + assert grep_q("expired.example/.*: RRSIG has expired", "ns4/named.run") + + # check future signatures do not validate + msg = isctest.query.create("future.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.servfail(res) + isctest.check.noadflag(res) + if hasattr(res, "extended_errors"): + assert res.extended_errors()[0].code == edns.EDECode.SIGNATURE_NOT_YET_VALID + assert grep_q( + "future.example/.*: RRSIG validity period has not begun", "ns4/named.run" + ) + + # check that a dynamic zone with future signatures is re-signed on load + msg = isctest.query.create("managed-future.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.adflag(res) + isctest.check.noerror(res) + + ns4 = servers["ns4"] + + # test TTL is capped at RRSIG expiry time + ns4.rndc("flush", log=False) + msg = isctest.query.create("expiring.example", "SOA", cd=True) + res1 = isctest.query.tcp(msg, "10.53.0.4") + msg = isctest.query.create("expiring.example", "SOA") + res2 = isctest.query.tcp(msg, "10.53.0.4") + for rrset in res1.answer: + assert rrset.ttl <= 3600 + for rrset in res2.answer: + assert rrset.ttl <= 60 + + # test TTL is capped at RRSIG expiry time in the additional section (NS) + ns4.rndc("flush", log=False) + msg = isctest.query.create("expiring.example", "NS", cd=True) + res1 = isctest.query.tcp(msg, "10.53.0.4") + msg = isctest.query.create("expiring.example", "NS") + res2 = isctest.query.tcp(msg, "10.53.0.4") + for rrset in res1.additional: + assert rrset.ttl <= 3600 + for rrset in res2.additional: + assert rrset.ttl <= 60 + + # test TTL is capped at RRSIG expiry time in the additional section (MX) + ns4.rndc("flush", log=False) + msg = isctest.query.create("expiring.example", "MX", cd=True) + res1 = isctest.query.tcp(msg, "10.53.0.4") + msg = isctest.query.create("expiring.example", "MX") + res2 = isctest.query.tcp(msg, "10.53.0.4") + for rrset in res1.additional: + assert rrset.ttl <= 3600 + for rrset in res2.additional: + assert rrset.ttl <= 60 + + +def test_accept_expired(servers, templates): + ns4 = servers["ns4"] + templates.render("ns4/named.conf", {"accept_expired": True}) + ns4.reconfigure(log=False) + + # test TTL of about-to-expire rrsets with accept-expired + ns4.rndc("flush", log=False) + msg = isctest.query.create("expiring.example", "SOA") + msg.flags |= flags.CD + res1 = isctest.query.tcp(msg, "10.53.0.4") + msg = isctest.query.create("expiring.example", "SOA") + res2 = isctest.query.tcp(msg, "10.53.0.4") + for rrset in res1.answer: + assert rrset.ttl <= 3600 + for rrset in res2.answer: + assert rrset.ttl <= 120 + + # test TTL is capped at RRSIG expiry time in the additional section + # with accept-expired + ns4.rndc("flush", log=False) + msg = isctest.query.create("expiring.example", "MX") + msg.flags |= flags.CD + res1 = isctest.query.tcp(msg, "10.53.0.4") + msg = isctest.query.create("expiring.example", "MX") + res2 = isctest.query.tcp(msg, "10.53.0.4") + for rrset in res1.additional: + assert rrset.ttl <= 3600 + for rrset in res2.additional: + assert rrset.ttl <= 120 + + # test TTL of expired rrsets with accept-expired + ns4.rndc("flush", log=False) + msg = isctest.query.create("expired.example", "SOA") + msg.flags |= flags.CD + res1 = isctest.query.tcp(msg, "10.53.0.4") + msg = isctest.query.create("expired.example", "SOA") + res2 = isctest.query.tcp(msg, "10.53.0.4") + for rrset in res1.additional: + assert rrset.ttl <= 3600 + for rrset in res2.additional: + assert rrset.ttl <= 120 + + +def test_casing(): + # test legacy upper-case signer name validation + msg = isctest.query.create("upper.example", "SOA") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.adflag(res) + _, sig = res.answer + assert sig.rdtype == rdatatype.RRSIG + assert sig.covers == rdatatype.SOA + assert "UPPER.EXAMPLE." in str(sig[0]) + + # test that we lower-case signer name + msg = isctest.query.create("LOWER.EXAMPLE", "SOA") + res = isctest.query.tcp(msg, "10.53.0.4") + _, sig = res.answer + assert sig.rdtype == rdatatype.RRSIG + assert sig.covers == rdatatype.SOA + assert "lower.example." in str(sig[0]) + + +def test_broken_servers(): + # check that a non-cacheable NODATA works + msg = isctest.query.create("a.nosoa.secure.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.6") + isctest.check.rr_count_eq(res1.authority, 0) + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res2) + + # check that a non-cacheable NXDOMAIN works + msg = isctest.query.create("b.nosoa.secure.example", "TXT") + res1 = isctest.query.tcp(msg, "10.53.0.6") + isctest.check.rr_count_eq(res1.authority, 0) + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.nxdomain(res2) + + # check that split RRSIGs are handled + msg = isctest.query.create("split-rrsig", "SOA") + res = isctest.query.tcp(msg, "10.53.0.6") + soa, _ = res.answer + assert soa[0].serial > 1 + + # check that not-at-zone-apex RRSIG(SOA) rrsets are removed + msg = isctest.query.create("split-rrsig", "AXFR") + res = isctest.query.tcp(msg, "10.53.0.6") + + nza = [ + r + for r in res.answer + if str(r.name) == "not-at-zone-apex.split-rrsig." + and r.rdtype == rdatatype.RRSIG + and r.covers == rdatatype.SOA + ] + assert not nza + + # check validation with missing nearest encloser proof + msg = isctest.query.create("b.c.d.optout-tld", "DS") + res = isctest.query.tcp(msg, "10.53.0.6") + nsec3s = [a for a in res.authority if a.rdtype == rdatatype.NSEC3] + assert len(nsec3s) == 2 + + msg = isctest.query.create("b.c.d.optout-tld", "A") + res = isctest.query.tcp(msg, "10.53.0.6") + nsec3s = [a for a in res.authority if a.rdtype == rdatatype.NSEC3] + assert len(nsec3s) == 1 + + res = isctest.query.tcp(msg, "10.53.0.6") + isctest.check.noerror(res) + isctest.check.noadflag(res) + msg = isctest.query.create("optout-tld", "SOA") + res = isctest.query.tcp(msg, "10.53.0.6") + isctest.check.noadflag(res) + + +def test_pending_ds(): + # check that a query against a validating resolver succeeds when there is + # a negative cache entry with trust level "pending" for the DS. prime + # with a +cd DS query to produce the negative cache entry, then send a + # query that uses that entry as part of the validation process. + ns4.rndc("flush", log=False) + msg = isctest.query.create("insecure.example", "DS", cd=True) + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.rr_count_eq(res.authority, 4) + msg = isctest.query.create("a.insecure.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.rr_count_eq(res.answer, 1) + isctest.check.rr_count_eq(res.authority, 1) + isctest.check.noadflag(res) + + +def test_trust_anchors(servers, templates): + # DNSSEC tests related to unsupported, disabled and revoked trust anchors. + # + # This nameserver is loaded with a bunch of trust anchors. + # Some of them are good (enabled.managed, enabled.trusted, + # secure.managed, secure.trusted), and some of them are bad + # (disabled.managed, revoked.managed, unsupported.managed, + # disabled.trusted, revoked.trusted, unsupported.trusted). Make sure + # that the bad trust anchors are ignored. This is tested by looking + # for the corresponding lines in the logfile. + ns5 = servers["ns5"] + templates.render("ns5/named.conf", {"many_anchors": True}) + ns5.reconfigure(log=False) + + # check that keys with unsupported/disabled algorithms are ignored + grep_q( + "ignoring static-key for 'disabled.trusted.': algorithm is disabled", + "ns5/named.run", + ) + grep_q( + "ignoring static-key for 'disabled.managed.': algorithm is disabled", + "ns5/named.run", + ) + grep_q( + "ignoring static-key for 'unsupported.trusted.': algorithm is unsupported", + "ns5/named.run", + ) + grep_q( + "ignoring static-key for 'unsupported.managed.': algorithm is unsupported", + "ns5/named.run", + ) + grep_q("ignoring static-key for 'revoked.trusted.': bad key type", "ns5/named.run") + grep_q("ignoring static-key for 'revoked.managed.': bad key type", "ns5/named.run") + + # check that a key with supported algorithm validates as secure + msg = isctest.query.create("a.secure.trusted", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + if hasattr(res2, "extended_errors"): + assert not res2.extended_errors() + + msg = isctest.query.create("a.secure.managed", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + if hasattr(res2, "extended_errors"): + assert not res2.extended_errors() + + # check that an unsupported signing algorithm yields insecure + msg = isctest.query.create("a.unsupported.trusted", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + if hasattr(res2, "extended_errors"): + assert ( + res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM + ) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + msg = isctest.query.create("a.unsupported.managed", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + if hasattr(res2, "extended_errors"): + assert ( + res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM + ) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # check that a disabled signing algorithm yields insecure + msg = isctest.query.create("a.disabled.trusted", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + msg = isctest.query.create("a.disabled.managed", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # check that zone signed with an algorithm that's disabled for + # some other domain, but not for this one, validates as secure. + # "enabled.trusted." and "enabled.managed." do not match the + # "disable-algorithms" option, so no special rules apply. (static) + msg = isctest.query.create("a.enabled.trusted", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + msg = isctest.query.create("a.enabled.managed", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + # a revoked trust anchor is ignored when configured; check that + # this yields insecure. + msg = isctest.query.create("a.revoked.trusted", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + msg = isctest.query.create("a.revoked.managed", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.5") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + +def test_unknown_algorithms(): + # check that unknown DNSKEY algorithm validates as insecure + msg = isctest.query.create("dnskey-unknown.example", "A", dnssec=False) + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + # check that unsupported DNSKEY algorithms are in the DNSKEY RRsets + msg = isctest.query.create("dnskey-unsupported.example", "DNSKEY") + res = isctest.query.tcp(msg, "10.53.0.3") + isctest.check.noerror(res) + + msg = isctest.query.create("dnskey-unsupported-2.example", "DNSKEY") + res = isctest.query.tcp(msg, "10.53.0.3") + isctest.check.noerror(res) + rrsets = [str(r) for r in res.answer] + assert any("257 3 255" in r for r in rrsets) + + # check that unsupported DNSKEY algorithm validates as insecure + msg = isctest.query.create("dnskey-unsupported.example", "DNSKEY") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.noadflag(res) + if hasattr(res, "extended_errors"): + assert ( + res.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM + ) + + # check that DNSKEY with an unsupported reserve key validates + msg = isctest.query.create("dnskey-unsupported-2.example", "DNSKEY") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + # check EDE code 2 for unsupported DS digest algorithm + msg = isctest.query.create("a.ds-unsupported.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + if hasattr(res, "extended_errors"): + assert res.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DS_DIGEST_TYPE + + # check EDE code 1 for bad algorithm mnemonic + msg = isctest.query.create("badalg.secure.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noadflag(res) + if hasattr(res, "extended_errors"): + assert ( + res.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM + ) + + # check both EDE code 1 and 2 for unsupported digest on one DNSKEY + # and unsupported algorithm on the other + msg = isctest.query.create("a.digest-alg-unsupported.example", "A") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noadflag(res) + if hasattr(res, "extended_errors"): + codes = {ede.code for ede in res.extended_errors()} + assert edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM in codes + assert edns.EDECode.UNSUPPORTED_DS_DIGEST_TYPE in codes + + # check that unknown DNSKEY algorithm + unknown NSEC3 hash algorithm + # validates as insecure + msg = isctest.query.create("dnskey-nsec3-unknown.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res1) + isctest.check.noerror(res2) + isctest.check.noadflag(res2) + + +################################### +##### BEGIN MANAGED KEY TESTS ##### +################################### +def test_switch_managed(servers, templates): + # switch to intializing trust anchor instead of static + ns4 = servers["ns4"] + assert os.path.exists("ns4/managed-keys.bind.jnl") is False + shutil.copyfile("ns4/managed-keys.bind.in", "ns4/managed-keys.bind") + templates.render("ns4/named.conf", {"managed_key": True}) + ns4.reconfigure(log=False) + + +def test_secure_root_managed(servers): + # check that a query for a secure root validates + msg = isctest.query.create(".", "KEY") + res = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.noerror(res) + isctest.check.adflag(res) + + # check that "rndc secroots" dumps the trusted keys + ns4 = servers["ns4"] + key = int(getfrom("ns1/managed.key.id")) + alg = os.environ["DEFAULT_ALGORITHM"] + expected = f"./{alg}/{key} ; managed" + response = ns4.rndc("secroots -", log=False).splitlines() + assert expected in response + assert len(response) == 10 + + +def test_positive_validation_nsec_managed(): + msg = isctest.query.create("a.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + +def test_positive_validation_nsec3_managed(): + msg = isctest.query.create("a.nsec3.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.noerror(res2) + isctest.check.adflag(res2) + + +def test_positive_validation_optout_managed(): + msg = isctest.query.create("a.optout.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.3") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.adflag(res2) + + +def test_negative_validation_nsec_managed(): + # nxdomain + msg = isctest.query.create("q.example", "A") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_answer(res1, res2) + isctest.check.nxdomain(res2) + isctest.check.adflag(res2) + + +def test_ds_managed(): + # check root DS queries validate + msg = isctest.query.create(".", "DS") + res1 = isctest.query.tcp(msg, "10.53.0.1") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.adflag(res2) + isctest.check.noerror(res2) + + # check DS queries succeed at RFC 1918 empty zone + msg = isctest.query.create("10.in-addr.arpa", "DS") + res1 = isctest.query.tcp(msg, "10.53.0.2") + res2 = isctest.query.tcp(msg, "10.53.0.4") + isctest.check.same_data(res1, res2) + isctest.check.noerror(res2) + + +def test_keydata_storage(servers): + ns4 = servers["ns4"] + ns4.rndc("managed-keys sync", log=False) + with isctest.log.WatchLogFromStart("ns4/managed-keys.bind") as watcher: + watcher.wait_for_line(["KEYDATA", "next refresh:"]) + + +############################################ +##### BEGIN MULTIVIEW VALIDATION TESTS ##### +############################################ +def test_insecure_staticstub_delegation(servers, templates): + ns4 = servers["ns4"] + templates.render("ns4/named.conf", {"multi_view": True}) + ns4.reconfigure(log=False) + + # check insecure delegation between static-stub zones + msg = isctest.query.create("insecure.secure.example", "NS") + for _ in range(5): + res = isctest.query.tcp(msg, "10.53.0.4") + if res.rcode() == rcode.SERVFAIL: + time.sleep(1) + continue + isctest.check.noerror(res) + + msg = isctest.query.create("secure.example", "NS") + for _ in range(5): + res = isctest.query.tcp(msg, "10.53.0.4") + if res.rcode() == rcode.SERVFAIL: + time.sleep(1) + continue + isctest.check.noerror(res) diff --git a/bin/tests/system/isctest/mark.py b/bin/tests/system/isctest/mark.py index 0961d9bb141..97a03d217af 100644 --- a/bin/tests/system/isctest/mark.py +++ b/bin/tests/system/isctest/mark.py @@ -42,6 +42,15 @@ def feature_test(feature): return True +rsasha1 = pytest.mark.skipif(not feature_test("--rsasha1"), reason="RSASHA1 disabled") + + +extended_ds_digest = pytest.mark.skipif( + not feature_test("--extended-ds-digest"), + reason="extended DS digest algorithms disabled", +) + + def is_host_freebsd_13(*_): return platform.system() == "FreeBSD" and platform.release().startswith("13") diff --git a/bin/tests/system/start.pl b/bin/tests/system/start.pl index a82bc98f22d..79757fc0a7e 100755 --- a/bin/tests/system/start.pl +++ b/bin/tests/system/start.pl @@ -264,8 +264,8 @@ sub construct_ns_command { foreach my $t_option( "dropedns", "ednsformerr", "ednsnotimp", "ednsrefused", - "cookiealwaysvalid", "noaa", "noedns", "nosoa", - "maxudp512", "maxudp1460", + "cookiealwaysvalid", "noaa", "noedns", "nonearest", + "nosoa", "maxudp512", "maxudp1460", "tat=1", "tat=3" ) { if (-e "$testdir/$server/named.$t_option") { $command .= "-T $t_option "