diff options
Diffstat (limited to 'bin/tests/system/checkds')
-rw-r--r-- | bin/tests/system/checkds/README | 26 | ||||
-rw-r--r-- | bin/tests/system/checkds/clean.sh | 26 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns2/named.conf.in | 45 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns2/setup.sh | 34 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns2/template.db.in | 38 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns4/named.conf.in | 41 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns5/named.conf.in | 45 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns5/setup.sh | 26 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns5/template.db.in | 38 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns6/named.conf.in | 45 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns7/named.conf.in | 46 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns9/named.conf.in | 218 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns9/setup.sh | 63 | ||||
-rw-r--r-- | bin/tests/system/checkds/ns9/template.db.in | 27 | ||||
-rw-r--r-- | bin/tests/system/checkds/prereq.sh | 31 | ||||
-rw-r--r-- | bin/tests/system/checkds/setup.sh | 40 | ||||
-rwxr-xr-x | bin/tests/system/checkds/tests_checkds.py | 450 |
17 files changed, 1239 insertions, 0 deletions
diff --git a/bin/tests/system/checkds/README b/bin/tests/system/checkds/README new file mode 100644 index 0000000..759c4bd --- /dev/null +++ b/bin/tests/system/checkds/README @@ -0,0 +1,26 @@ +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. + +The test setup for the checkds tests. + +These servers are parent servers: +- ns2 is a primary authoritative server that serves the parent zone for zones + configured in ns9. +- ns4 is the secondary server for ns2. +- ns5 is a primary authoritative server that serves the parent zone for zones + configured in ns9, but this one does not publish DS records (to test cases + where the DS is missing). +- ns6 is an authoritative server for a different zone, to test badly configured + parental agents. +- ns7 is the secondary server for ns5. + +Finally, ns9 is the authoritative server for the various DNSSEC enabled test +domains. diff --git a/bin/tests/system/checkds/clean.sh b/bin/tests/system/checkds/clean.sh new file mode 100644 index 0000000..74bf421 --- /dev/null +++ b/bin/tests/system/checkds/clean.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# 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. + +set -e + +rm -f dig.out* +rm -f ns*/named.conf ns*/named.memstats ns*/named.run* +rm -f ns*/*.jnl ns*/*.jbk +rm -f ns*/K*.private ns*/K*.key ns*/K*.state +rm -f ns*/dsset-* +rm -f ns*/*.db ns*/*.jnl ns*/*.jbk ns*/*.db.signed ns*/*.db.infile +rm -f ns*/keygen.out.* ns*/settime.out.* ns*/signer.out.* +rm -f ns*/managed-keys.bind* +rm -f ns*/*.mkeys +rm -f ns*/zones +rm -f *.checkds.out diff --git a/bin/tests/system/checkds/ns2/named.conf.in b/bin/tests/system/checkds/ns2/named.conf.in new file mode 100644 index 0000000..44a5776 --- /dev/null +++ b/bin/tests/system/checkds/ns2/named.conf.in @@ -0,0 +1,45 @@ +/* + * 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. + */ + +// NS2 + +options { + query-source address 10.53.0.2; + notify-source 10.53.0.2; + transfer-source 10.53.0.2; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.2; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; + +zone "checkds" { + type primary; + file "checkds.db"; +}; diff --git a/bin/tests/system/checkds/ns2/setup.sh b/bin/tests/system/checkds/ns2/setup.sh new file mode 100644 index 0000000..57c7f0a --- /dev/null +++ b/bin/tests/system/checkds/ns2/setup.sh @@ -0,0 +1,34 @@ +#!/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 + +echo_i "ns2/setup.sh" + +for subdomain in dspublished reference missing-dspublished bad-dspublished \ + multiple-dspublished incomplete-dspublished bad2-dspublished \ + dswithdrawn missing-dswithdrawn bad-dswithdrawn \ + multiple-dswithdrawn incomplete-dswithdrawn bad2-dswithdrawn +do + cp "../ns9/dsset-$subdomain.checkds$TP" . +done + +zone="checkds" +infile="checkds.db.infile" +zonefile="checkds.db" + +CSK=$($KEYGEN -k default $zone 2> keygen.out.$zone) +cat template.db.in "${CSK}.key" > "$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile" +$SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone 2>&1 diff --git a/bin/tests/system/checkds/ns2/template.db.in b/bin/tests/system/checkds/ns2/template.db.in new file mode 100644 index 0000000..ede62ef --- /dev/null +++ b/bin/tests/system/checkds/ns2/template.db.in @@ -0,0 +1,38 @@ +; 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. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns2 +ns2 A 10.53.0.2 + +dspublished NS ns9.dspublished +reference NS ns9.reference +missing-dspublished NS ns9.missing-dspublished +bad-dspublished NS ns9.bad-dspublished +multiple-dspublished NS ns9.multiple-dspublished +incomplete-dspublished NS ns9.incomplete-dspublished +bad2-dspublished NS ns9.bad2-dspublished + +dswithdrawn NS ns9.dswithdrawn +missing-dswithdrawn NS ns9.missing-dswithdrawn +bad-dswithdrawn NS ns9.bad-dswithdrawn +multiple-dswithdrawn NS ns9.multiple-dswithdrawn +incomplete-dswithdrawn NS ns9.incomplete-dswithdrawn +bad2-dswithdrawn NS ns9.bad2-dswithdrawn + diff --git a/bin/tests/system/checkds/ns4/named.conf.in b/bin/tests/system/checkds/ns4/named.conf.in new file mode 100644 index 0000000..b5421eb --- /dev/null +++ b/bin/tests/system/checkds/ns4/named.conf.in @@ -0,0 +1,41 @@ +/* + * 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; }; + allow-transfer { any; }; + recursion no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "checkds" { + type secondary; + file "checkds.db"; + primaries { 10.53.0.2 port @PORT@; }; +}; diff --git a/bin/tests/system/checkds/ns5/named.conf.in b/bin/tests/system/checkds/ns5/named.conf.in new file mode 100644 index 0000000..baab6be --- /dev/null +++ b/bin/tests/system/checkds/ns5/named.conf.in @@ -0,0 +1,45 @@ +/* + * 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. + */ + +// NS5 + +options { + query-source address 10.53.0.5; + notify-source 10.53.0.5; + transfer-source 10.53.0.5; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.5; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.5 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; + +zone "checkds" { + type primary; + file "checkds.db"; +}; diff --git a/bin/tests/system/checkds/ns5/setup.sh b/bin/tests/system/checkds/ns5/setup.sh new file mode 100644 index 0000000..79d7b71 --- /dev/null +++ b/bin/tests/system/checkds/ns5/setup.sh @@ -0,0 +1,26 @@ +#!/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 + +echo_i "ns5/setup.sh" + +zone="checkds" +infile="checkds.db.infile" +zonefile="checkds.db" + +CSK=$($KEYGEN -k default $zone 2> keygen.out.$zone) +cat template.db.in "${CSK}.key" > "$infile" +private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile" +$SIGNER -S -g -z -x -s now-1h -e now+30d -o $zone -O full -f $zonefile $infile > signer.out.$zone 2>&1 diff --git a/bin/tests/system/checkds/ns5/template.db.in b/bin/tests/system/checkds/ns5/template.db.in new file mode 100644 index 0000000..ac3eb8e --- /dev/null +++ b/bin/tests/system/checkds/ns5/template.db.in @@ -0,0 +1,38 @@ +; 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. + +$TTL 300 +@ IN SOA secondary.example. hostmaster.example. ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns5 +ns5 A 10.53.0.5 + +dspublished NS ns9.dspublished +reference NS ns9.reference +missing-dspublished NS ns9.missing-dspublished +bad-dspublished NS ns9.bad-dspublished +multiple-dspublished NS ns9.multiple-dspublished +incomplete-dspublished NS ns9.incomplete-dspublished +bad2-dspublished NS ns9.bad2-dspublished + +dswithdrawn NS ns9.dswithdrawn +missing-dswithdrawn NS ns9.missing-dswithdrawn +bad-dswithdrawn NS ns9.bad-dswithdrawn +multiple-dswithdrawn NS ns9.multiple-dswithdrawn +incomplete-dswithdrawn NS ns9.incomplete-dswithdrawn +bad2-dswithdrawn NS ns9.bad2-dswithdrawn + diff --git a/bin/tests/system/checkds/ns6/named.conf.in b/bin/tests/system/checkds/ns6/named.conf.in new file mode 100644 index 0000000..53d3a16 --- /dev/null +++ b/bin/tests/system/checkds/ns6/named.conf.in @@ -0,0 +1,45 @@ +/* + * 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. + */ + +// NS2 + +options { + query-source address 10.53.0.6; + notify-source 10.53.0.6; + transfer-source 10.53.0.6; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.6; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.6 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; + +zone "foo" { + type primary; + file "foo.db"; +}; diff --git a/bin/tests/system/checkds/ns7/named.conf.in b/bin/tests/system/checkds/ns7/named.conf.in new file mode 100644 index 0000000..a3e3e15 --- /dev/null +++ b/bin/tests/system/checkds/ns7/named.conf.in @@ -0,0 +1,46 @@ +/* + * 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. + */ + +// NS7 + +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; }; + allow-transfer { any; }; + recursion no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.7 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; + +zone "checkds" { + type secondary; + file "checkds.db"; + primaries { 10.53.0.5 port @PORT@; }; +}; diff --git a/bin/tests/system/checkds/ns9/named.conf.in b/bin/tests/system/checkds/ns9/named.conf.in new file mode 100644 index 0000000..0899f8a --- /dev/null +++ b/bin/tests/system/checkds/ns9/named.conf.in @@ -0,0 +1,218 @@ +/* + * 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. + */ + +// NS9 + +options { + query-source address 10.53.0.9; + notify-source 10.53.0.9; + transfer-source 10.53.0.9; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.9; }; + listen-on-v6 { none; }; + allow-transfer { any; }; + recursion no; +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm hmac-sha256; +}; + +controls { + inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + +parental-agents "ns2" port @PORT@ { + 10.53.0.2; +}; + +zone "." { + type hint; + file "../../common/root.hint"; +}; + +/* + * Zone with parental agent configured, due for DS checking. + */ +zone "dspublished.checkds" { + type primary; + file "dspublished.checkds.db"; + inline-signing yes; + dnssec-policy "default"; + parental-agents { 10.53.0.2 port @PORT@; }; +}; + +/* + * Zone with parental agent configured, due for DS checking. + * Same as above, but now with a reference to parental-agents. + */ +zone "reference.checkds" { + type primary; + file "reference.checkds.db"; + inline-signing yes; + dnssec-policy "default"; + parental-agents { "ns2"; }; +}; + +/* + * Zone with parental agent configured, due for DS checking. + * The parental agent does not have the DS yet. + */ +zone "missing-dspublished.checkds" { + type primary; + file "missing-dspublished.checkds.db"; + inline-signing yes; + dnssec-policy "default"; + parental-agents { + 10.53.0.5 port @PORT@; // missing + }; +}; + + +/* + * Zone with parental agent configured, due for DS checking. + * This case, the server is badly configured. + */ +zone "bad-dspublished.checkds" { + type primary; + file "bad-dspublished.checkds.db"; + inline-signing yes; + dnssec-policy "default"; + parental-agents { + 10.53.0.6 port @PORT@; // bad + }; +}; + +/* + * Zone with multiple parental agents configured, due for DS checking. + * All need to have the DS before the rollover may continue. + */ +zone "multiple-dspublished.checkds" { + type primary; + file "multiple-dspublished.checkds.db"; + inline-signing yes; + dnssec-policy "default"; + parental-agents { + 10.53.0.2 port @PORT@; + 10.53.0.4 port @PORT@; + }; +}; + +/* + * Zone with multiple parental agents configured, due for DS checking. + * All need to have the DS before the rollover may continue. + * This case, one server is still missing the DS. + */ +zone "incomplete-dspublished.checkds" { + type primary; + file "incomplete-dspublished.checkds.db"; + inline-signing yes; + dnssec-policy "default"; + parental-agents { + 10.53.0.2 port @PORT@; + 10.53.0.4 port @PORT@; + 10.53.0.5 port @PORT@; // missing + }; +}; + + +/* + * Zone with multiple parental agents configured, due for DS checking. + * All need to have the DS before the rollover may continue. + * This case, one server is badly configured. + */ +zone "bad2-dspublished.checkds" { + type primary; + file "bad2-dspublished.checkds.db"; + inline-signing yes; + dnssec-policy "default"; + parental-agents { + 10.53.0.2 port @PORT@; + 10.53.0.4 port @PORT@; + 10.53.0.6 port @PORT@; // bad + }; +}; + +// TODO: Other test cases: +// - Test with bogus response +// - check with TSIG +// - check with TLS + + +/* + * Zones that are going insecure (test DS withdrawn polling). + */ +zone "dswithdrawn.checkds" { + type primary; + file "dswithdrawn.checkds.db"; + inline-signing yes; + dnssec-policy "insecure"; + parental-agents { 10.53.0.5 port @PORT@; }; +}; + +zone "missing-dswithdrawn.checkds" { + type primary; + file "missing-dswithdrawn.checkds.db"; + inline-signing yes; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.2 port @PORT@; // still published + }; +}; + +zone "bad-dswithdrawn.checkds" { + type primary; + file "bad-dswithdrawn.checkds.db"; + inline-signing yes; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.6 port @PORT@; // bad + }; +}; + +zone "multiple-dswithdrawn.checkds" { + type primary; + file "multiple-dswithdrawn.checkds.db"; + inline-signing yes; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.5 port @PORT@; + 10.53.0.7 port @PORT@; + }; +}; + +zone "incomplete-dswithdrawn.checkds" { + type primary; + file "incomplete-dswithdrawn.checkds.db"; + inline-signing yes; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.2 port @PORT@; // still published + 10.53.0.5 port @PORT@; + 10.53.0.7 port @PORT@; + }; +}; + +zone "bad2-dswithdrawn.checkds" { + type primary; + file "bad2-dswithdrawn.checkds.db"; + inline-signing yes; + dnssec-policy "insecure"; + parental-agents { + 10.53.0.5 port @PORT@; + 10.53.0.7 port @PORT@; + 10.53.0.6 port @PORT@; // bad + }; +}; diff --git a/bin/tests/system/checkds/ns9/setup.sh b/bin/tests/system/checkds/ns9/setup.sh new file mode 100644 index 0000000..0990fa3 --- /dev/null +++ b/bin/tests/system/checkds/ns9/setup.sh @@ -0,0 +1,63 @@ +#!/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 + +echo_i "ns9/setup.sh" + +setup() { + zone="$1" + echo_i "setting up zone: $zone" + zonefile="${zone}.db" + infile="${zone}.db.infile" + echo "$zone" >> zones +} + +# Short environment variable names for key states and times. +H="HIDDEN" +R="RUMOURED" +O="OMNIPRESENT" +U="UNRETENTIVE" +T="now-30d" +Y="now-1y" + +# DS Publication. +for zn in dspublished reference missing-dspublished bad-dspublished \ + multiple-dspublished incomplete-dspublished bad2-dspublished +do + setup "${zn}.checkds" + cp template.db.in "$zonefile" + keytimes="-P $T -P sync $T -A $T" + CSK=$($KEYGEN -k default $keytimes $zone 2> keygen.out.$zone) + $SETTIME -s -g $O -k $O $T -r $O $T -z $O $T -d $R $T "$CSK" > settime.out.$zone 2>&1 + cat template.db.in "${CSK}.key" > "$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile" + cp $infile $zonefile + $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1 +done + +# DS Withdrawal. +for zn in dswithdrawn missing-dswithdrawn bad-dswithdrawn multiple-dswithdrawn \ + incomplete-dswithdrawn bad2-dswithdrawn +do + setup "${zn}.checkds" + cp template.db.in "$zonefile" + keytimes="-P $Y -P sync $Y -A $Y" + CSK=$($KEYGEN -k default $keytimes $zone 2> keygen.out.$zone) + $SETTIME -s -g $H -k $O $T -r $O $T -z $O $T -d $U $T "$CSK" > settime.out.$zone 2>&1 + cat template.db.in "${CSK}.key" > "$infile" + private_type_record $zone $DEFAULT_ALGORITHM_NUMBER "$CSK" >> "$infile" + cp $infile $zonefile + $SIGNER -S -z -x -s now-1h -e now+30d -o $zone -O raw -f "${zonefile}.signed" $infile > signer.out.$zone.1 2>&1 +done diff --git a/bin/tests/system/checkds/ns9/template.db.in b/bin/tests/system/checkds/ns9/template.db.in new file mode 100644 index 0000000..cf06015 --- /dev/null +++ b/bin/tests/system/checkds/ns9/template.db.in @@ -0,0 +1,27 @@ +; 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. + +$TTL 300 +@ IN SOA mname1. . ( + 1 ; serial + 20 ; refresh (20 seconds) + 20 ; retry (20 seconds) + 1814400 ; expire (3 weeks) + 3600 ; minimum (1 hour) + ) + + NS ns9 +ns9 A 10.53.0.9 + +a A 10.0.0.1 +b A 10.0.0.2 +c A 10.0.0.3 + diff --git a/bin/tests/system/checkds/prereq.sh b/bin/tests/system/checkds/prereq.sh new file mode 100644 index 0000000..2204695 --- /dev/null +++ b/bin/tests/system/checkds/prereq.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +# 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. + +SYSTEMTESTTOP=.. +. $SYSTEMTESTTOP/conf.sh + +if test -n "$PYTHON" +then + if [ "$($PYTHON -c "import dns.version; print(dns.version.MAJOR)" 2> /dev/null)" -ge 2 ] + then + : + else + echo_i "This test requires the dnspython >= 2.0.0 module." >&2 + exit 1 + fi +else + echo_i "This test requires Python and the dnspython module." >&2 + exit 1 +fi + +exit 0 diff --git a/bin/tests/system/checkds/setup.sh b/bin/tests/system/checkds/setup.sh new file mode 100644 index 0000000..93c73b6 --- /dev/null +++ b/bin/tests/system/checkds/setup.sh @@ -0,0 +1,40 @@ +#!/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 + +$SHELL clean.sh + +copy_setports ns2/named.conf.in ns2/named.conf +copy_setports ns4/named.conf.in ns4/named.conf +copy_setports ns5/named.conf.in ns5/named.conf +copy_setports ns6/named.conf.in ns6/named.conf +copy_setports ns7/named.conf.in ns7/named.conf +copy_setports ns9/named.conf.in ns9/named.conf + +# Setup zones +( + cd ns9 + $SHELL setup.sh +) +( + cd ns5 + $SHELL setup.sh +) +( + cd ns2 + $SHELL setup.sh +) diff --git a/bin/tests/system/checkds/tests_checkds.py b/bin/tests/system/checkds/tests_checkds.py new file mode 100755 index 0000000..a52833e --- /dev/null +++ b/bin/tests/system/checkds/tests_checkds.py @@ -0,0 +1,450 @@ +#!/usr/bin/python3 + +# 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 mmap +import os +import subprocess +import sys +import time + +import pytest + +pytest.importorskip("dns", minversion="2.0.0") +import dns.exception +import dns.message +import dns.name +import dns.query +import dns.rcode +import dns.rdataclass +import dns.rdatatype +import dns.resolver + + +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 7), reason="Python >= 3.7 required [GL #3001]" +) + + +def has_signed_apex_nsec(zone, response): + has_nsec = False + has_rrsig = False + + ttl = 300 + nextname = "a." + types = "NS SOA RRSIG NSEC DNSKEY CDS CDNSKEY" + match = "{0} {1} IN NSEC {2}{0} {3}".format(zone, ttl, nextname, types) + sig = "{0} {1} IN RRSIG NSEC 13 2 300".format(zone, ttl) + + for rr in response.answer: + if match in rr.to_text(): + has_nsec = True + if sig in rr.to_text(): + has_rrsig = True + + if not has_nsec: + print("error: missing apex NSEC record in response") + if not has_rrsig: + print("error: missing NSEC signature in response") + + return has_nsec and has_rrsig + + +def do_query(server, qname, qtype, tcp=False): + query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True) + try: + if tcp: + response = dns.query.tcp( + query, server.nameservers[0], timeout=3, port=server.port + ) + else: + response = dns.query.udp( + query, server.nameservers[0], timeout=3, port=server.port + ) + except dns.exception.Timeout: + print( + "error: query timeout for query {} {} to {}".format( + qname, qtype, server.nameservers[0] + ) + ) + return None + + return response + + +def verify_zone(zone, transfer): + verify = os.getenv("VERIFY") + assert verify is not None + + filename = "{}out".format(zone) + with open(filename, "w", encoding="utf-8") as file: + for rr in transfer.answer: + file.write(rr.to_text()) + file.write("\n") + + # dnssec-verify command with default arguments. + verify_cmd = [verify, "-z", "-o", zone, filename] + + verifier = subprocess.run(verify_cmd, capture_output=True, check=True) + + if verifier.returncode != 0: + print("error: dnssec-verify {} failed".format(zone)) + sys.stderr.buffer.write(verifier.stderr) + + return verifier.returncode == 0 + + +def read_statefile(server, zone): + addr = server.nameservers[0] + count = 0 + keyid = 0 + state = {} + + response = do_query(server, zone, "DS", tcp=True) + if not isinstance(response, dns.message.Message): + print("error: no response for {} DS from {}".format(zone, addr)) + return {} + + if response.rcode() == dns.rcode.NOERROR: + # fetch key id from response. + for rr in response.answer: + if rr.match( + dns.name.from_text(zone), + dns.rdataclass.IN, + dns.rdatatype.DS, + dns.rdatatype.NONE, + ): + if count == 0: + keyid = list(dict(rr.items).items())[0][0].key_tag + count += 1 + + if count != 1: + print( + "error: expected a single DS in response for {} from {}," + "got {}".format(zone, addr, count) + ) + return {} + else: + print( + "error: {} response for {} DNSKEY from {}".format( + dns.rcode.to_text(response.rcode()), zone, addr + ) + ) + return {} + + filename = "ns9/K{}+013+{:05d}.state".format(zone, keyid) + print("read state file {}".format(filename)) + + try: + with open(filename, "r", encoding="utf-8") as file: + for line in file: + if line.startswith(";"): + continue + key, val = line.strip().split(":", 1) + state[key.strip()] = val.strip() + + except FileNotFoundError: + # file may not be written just yet. + return {} + + return state + + +def zone_check(server, zone): + addr = server.nameservers[0] + + # wait until zone is fully signed. + signed = False + for _ in range(10): + response = do_query(server, zone, "NSEC") + if not isinstance(response, dns.message.Message): + print("error: no response for {} NSEC from {}".format(zone, addr)) + elif response.rcode() == dns.rcode.NOERROR: + signed = has_signed_apex_nsec(zone, response) + else: + print( + "error: {} response for {} NSEC from {}".format( + dns.rcode.to_text(response.rcode()), zone, addr + ) + ) + + if signed: + break + + time.sleep(1) + + assert signed + + # check if zone if DNSSEC valid. + verified = False + transfer = do_query(server, zone, "AXFR", tcp=True) + if not isinstance(transfer, dns.message.Message): + print("error: no response for {} AXFR from {}".format(zone, addr)) + elif transfer.rcode() == dns.rcode.NOERROR: + verified = verify_zone(zone, transfer) + else: + print( + "error: {} response for {} AXFR from {}".format( + dns.rcode.to_text(transfer.rcode()), zone, addr + ) + ) + + assert verified + + +def keystate_check(server, zone, key): + val = 0 + deny = False + + search = key + if key.startswith("!"): + deny = True + search = key[1:] + + for _ in range(10): + state = read_statefile(server, zone) + try: + val = state[search] + except KeyError: + pass + + if not deny and val != 0: + break + if deny and val == 0: + break + + time.sleep(1) + + if deny: + assert val == 0 + else: + assert val != 0 + + +def wait_for_log(filename, log): + found = False + + for _ in range(10): + print("read log file {}".format(filename)) + + try: + with open(filename, "r", encoding="utf-8") as file: + s = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) + if s.find(bytes(log, "ascii")) != -1: + found = True + except FileNotFoundError: + print("file not found {}".format(filename)) + + if found: + break + + print("sleep") + time.sleep(1) + + assert found + + +def test_checkds_dspublished(named_port): + # We create resolver instances that will be used to send queries. + server = dns.resolver.Resolver() + server.nameservers = ["10.53.0.9"] + server.port = named_port + + parent = dns.resolver.Resolver() + parent.nameservers = ["10.53.0.2"] + parent.port = named_port + + # DS correctly published in parent. + zone_check(server, "dspublished.checkds.") + wait_for_log( + "ns9/named.run", + "zone dspublished.checkds/IN (signed): checkds: DS response from 10.53.0.2", + ) + keystate_check(parent, "dspublished.checkds.", "DSPublish") + + # DS correctly published in parent (reference to parental-agent). + zone_check(server, "reference.checkds.") + wait_for_log( + "ns9/named.run", + "zone reference.checkds/IN (signed): checkds: DS response from 10.53.0.2", + ) + keystate_check(parent, "reference.checkds.", "DSPublish") + + # DS not published in parent. + zone_check(server, "missing-dspublished.checkds.") + wait_for_log( + "ns9/named.run", + "zone missing-dspublished.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + keystate_check(parent, "missing-dspublished.checkds.", "!DSPublish") + + # Badly configured parent. + zone_check(server, "bad-dspublished.checkds.") + wait_for_log( + "ns9/named.run", + "zone bad-dspublished.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) + keystate_check(parent, "bad-dspublished.checkds.", "!DSPublish") + + # TBD: DS published in parent, but bogus signature. + + # DS correctly published in all parents. + zone_check(server, "multiple-dspublished.checkds.") + wait_for_log( + "ns9/named.run", + "zone multiple-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone multiple-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) + keystate_check(parent, "multiple-dspublished.checkds.", "DSPublish") + + # DS published in only one of multiple parents. + zone_check(server, "incomplete-dspublished.checkds.") + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dspublished.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + keystate_check(parent, "incomplete-dspublished.checkds.", "!DSPublish") + + # One of the parents is badly configured. + zone_check(server, "bad2-dswithdrawn.checkds.") + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "DS response from 10.53.0.4", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dspublished.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) + keystate_check(parent, "bad2-dspublished.checkds.", "!DSPublish") + + # TBD: DS published in all parents, but one has bogus signature. + + # TBD: Check with TSIG + + +def test_checkds_dswithdrawn(named_port): + # We create resolver instances that will be used to send queries. + server = dns.resolver.Resolver() + server.nameservers = ["10.53.0.9"] + server.port = named_port + + parent = dns.resolver.Resolver() + parent.nameservers = ["10.53.0.2"] + parent.port = named_port + + # DS correctly published in single parent. + zone_check(server, "dswithdrawn.checkds.") + wait_for_log( + "ns9/named.run", + "zone dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + keystate_check(parent, "dswithdrawn.checkds.", "DSRemoved") + + # DS not withdrawn from parent. + zone_check(server, "missing-dswithdrawn.checkds.") + wait_for_log( + "ns9/named.run", + "zone missing-dswithdrawn.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + keystate_check(parent, "missing-dswithdrawn.checkds.", "!DSRemoved") + + # Badly configured parent. + zone_check(server, "bad-dswithdrawn.checkds.") + wait_for_log( + "ns9/named.run", + "zone bad-dswithdrawn.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) + keystate_check(parent, "bad-dswithdrawn.checkds.", "!DSRemoved") + + # TBD: DS published in parent, but bogus signature. + + # DS correctly withdrawn from all parents. + zone_check(server, "multiple-dswithdrawn.checkds.") + wait_for_log( + "ns9/named.run", + "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone multiple-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) + keystate_check(parent, "multiple-dswithdrawn.checkds.", "DSRemoved") + + # DS withdrawn from only one of multiple parents. + zone_check(server, "incomplete-dswithdrawn.checkds.") + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "DS response from 10.53.0.2", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone incomplete-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) + keystate_check(parent, "incomplete-dswithdrawn.checkds.", "!DSRemoved") + + # One of the parents is badly configured. + zone_check(server, "bad2-dswithdrawn.checkds.") + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.5", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "empty DS response from 10.53.0.7", + ) + wait_for_log( + "ns9/named.run", + "zone bad2-dswithdrawn.checkds/IN (signed): checkds: " + "bad DS response from 10.53.0.6", + ) + keystate_check(parent, "bad2-dswithdrawn.checkds.", "!DSRemoved") + + # TBD: DS withdrawn from all parents, but one has bogus signature. |