summaryrefslogtreecommitdiffstats
path: root/bin/tests/system/checkds
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bin/tests/system/checkds/README26
-rw-r--r--bin/tests/system/checkds/clean.sh26
-rw-r--r--bin/tests/system/checkds/ns2/named.conf.in45
-rw-r--r--bin/tests/system/checkds/ns2/setup.sh34
-rw-r--r--bin/tests/system/checkds/ns2/template.db.in38
-rw-r--r--bin/tests/system/checkds/ns4/named.conf.in41
-rw-r--r--bin/tests/system/checkds/ns5/named.conf.in45
-rw-r--r--bin/tests/system/checkds/ns5/setup.sh26
-rw-r--r--bin/tests/system/checkds/ns5/template.db.in38
-rw-r--r--bin/tests/system/checkds/ns6/named.conf.in45
-rw-r--r--bin/tests/system/checkds/ns7/named.conf.in46
-rw-r--r--bin/tests/system/checkds/ns9/named.conf.in218
-rw-r--r--bin/tests/system/checkds/ns9/setup.sh63
-rw-r--r--bin/tests/system/checkds/ns9/template.db.in27
-rw-r--r--bin/tests/system/checkds/prereq.sh31
-rw-r--r--bin/tests/system/checkds/setup.sh40
-rwxr-xr-xbin/tests/system/checkds/tests_checkds.py450
-rw-r--r--bin/tests/system/checkdstool/clean.sh15
-rwxr-xr-xbin/tests/system/checkdstool/dig.bat32
-rw-r--r--bin/tests/system/checkdstool/dig.pl41
-rwxr-xr-xbin/tests/system/checkdstool/dig.sh24
-rw-r--r--bin/tests/system/checkdstool/missing.example.dnskey.db3
-rw-r--r--bin/tests/system/checkdstool/missing.example.ds.db2
-rw-r--r--bin/tests/system/checkdstool/none.example.dnskey.db3
-rw-r--r--bin/tests/system/checkdstool/none.example.ds.db0
-rw-r--r--bin/tests/system/checkdstool/ok.example.dnskey.db2
-rw-r--r--bin/tests/system/checkdstool/ok.example.ds.db2
-rw-r--r--bin/tests/system/checkdstool/prep.example.db121
-rw-r--r--bin/tests/system/checkdstool/prep.example.ds.db2
-rw-r--r--bin/tests/system/checkdstool/tests.sh117
-rw-r--r--bin/tests/system/checkdstool/wrong.example.dnskey.db2
-rw-r--r--bin/tests/system/checkdstool/wrong.example.ds.db2
32 files changed, 1607 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.
diff --git a/bin/tests/system/checkdstool/clean.sh b/bin/tests/system/checkdstool/clean.sh
new file mode 100644
index 0000000..fb853c5
--- /dev/null
+++ b/bin/tests/system/checkdstool/clean.sh
@@ -0,0 +1,15 @@
+#!/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.
+
+rm -f checkds.*
+rm -f ns*/named.lock
diff --git a/bin/tests/system/checkdstool/dig.bat b/bin/tests/system/checkdstool/dig.bat
new file mode 100755
index 0000000..9465a46
--- /dev/null
+++ b/bin/tests/system/checkdstool/dig.bat
@@ -0,0 +1,32 @@
+@echo off
+set ext=
+set file=
+
+:loop
+@set arg=%1
+if "%arg%" == "" goto end
+if "%arg:~0,1%" == "+" goto next
+if "%arg%" == "-t" goto next
+if "%arg%" == "ds" goto ds
+if "%arg%" == "DS" goto ds
+if "%arg%" == "dnskey" goto dnskey
+if "%arg%" == "DNSKEY" goto dnskey
+set file=%arg%
+goto next
+
+:ds
+set ext=ds
+goto next
+
+:dnskey
+set ext=dnskey
+goto next
+
+:next
+shift
+goto loop
+
+:end
+
+set name=%file%.%ext%.db
+type %name%
diff --git a/bin/tests/system/checkdstool/dig.pl b/bin/tests/system/checkdstool/dig.pl
new file mode 100644
index 0000000..3713b2c
--- /dev/null
+++ b/bin/tests/system/checkdstool/dig.pl
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+# 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.
+
+my $arg;
+my $ext;
+my $file;
+
+foreach $arg (@ARGV) {
+ if ($arg =~ /^\+/) {
+ next;
+ }
+ if ($arg =~ /^-t/) {
+ next;
+ }
+ if ($arg =~ /^ds$/i) {
+ $ext = "ds";
+ next;
+ }
+ if ($arg =~ /^dnskey$/i) {
+ $ext = "dnskey";
+ next;
+ }
+ $file = $arg;
+ next;
+}
+
+open F, $file . "." . $ext . ".db" || die $!;
+while (<F>) {
+ print;
+}
+close F;
diff --git a/bin/tests/system/checkdstool/dig.sh b/bin/tests/system/checkdstool/dig.sh
new file mode 100755
index 0000000..7b3a1b2
--- /dev/null
+++ b/bin/tests/system/checkdstool/dig.sh
@@ -0,0 +1,24 @@
+#!/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.
+
+while [ "$#" != 0 ]; do
+ case $1 in
+ +*) shift ;;
+ -t) shift ;;
+ DS|ds) ext=ds ; shift ;;
+ DNSKEY|dnskey) ext=dnskey ; shift ;;
+ *) file=$1 ; shift ;;
+ esac
+done
+
+cat ${file}.${ext}.db
diff --git a/bin/tests/system/checkdstool/missing.example.dnskey.db b/bin/tests/system/checkdstool/missing.example.dnskey.db
new file mode 100644
index 0000000..e372130
--- /dev/null
+++ b/bin/tests/system/checkdstool/missing.example.dnskey.db
@@ -0,0 +1,3 @@
+missing.example. 3600 IN DNSKEY 257 3 5 AwEAAc6Cz10GXEh5lxA9ujTY/QarTajcUOBwwBYIeldjRsgoouK/UioY FYgxEFL0O5JK6YCRUoGzl3EgLr5GvNyhIp1PZpOpHf7o/4MVOZTGJzm/ sHWP5B+KcYjQOxJiDb433iCmRM4DpHPUUoxw0QbZglzAzl5MfKBoyZud lH59DdT/50bkBg8iVu35EzuW0SYt31k70hxHBSb2wAGWeqxEPKJ1nQiI UcrWNDeem7byrqjPN9wyZhq0XkQ9qbcYxAkRNd8Y7P0FyR1YKJMc6SWZ Ru7muvxqTHgCtJVgxVz4qndCFKdYidiDeKe2/X/z5gf7pyYl3549O8JR tWdNKqutppk=
+missing.example. 3600 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjG rhhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA +u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy 347cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQ zBkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysy LKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/b ByBNsO70aEFTd
+missing.example. 3600 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkdstool/missing.example.ds.db b/bin/tests/system/checkdstool/missing.example.ds.db
new file mode 100644
index 0000000..540ec0b
--- /dev/null
+++ b/bin/tests/system/checkdstool/missing.example.ds.db
@@ -0,0 +1,2 @@
+missing.example. 3600 IN DS 12892 5 2 EF59E5C70BC4153B7DB4C11F9C36B729577DA71474E0A5C9B8875173 6E583200
+missing.example. 3600 IN DS 12892 5 1 9D4CD60491D372207FA584D2EE460CC51D7FF8A7
diff --git a/bin/tests/system/checkdstool/none.example.dnskey.db b/bin/tests/system/checkdstool/none.example.dnskey.db
new file mode 100644
index 0000000..76ae905
--- /dev/null
+++ b/bin/tests/system/checkdstool/none.example.dnskey.db
@@ -0,0 +1,3 @@
+none.example. 3600 IN DNSKEY 257 3 5 AwEAAc6Cz10GXEh5lxA9ujTY/QarTajcUOBwwBYIeldjRsgoouK/UioY FYgxEFL0O5JK6YCRUoGzl3EgLr5GvNyhIp1PZpOpHf7o/4MVOZTGJzm/ sHWP5B+KcYjQOxJiDb433iCmRM4DpHPUUoxw0QbZglzAzl5MfKBoyZud lH59DdT/50bkBg8iVu35EzuW0SYt31k70hxHBSb2wAGWeqxEPKJ1nQiI UcrWNDeem7byrqjPN9wyZhq0XkQ9qbcYxAkRNd8Y7P0FyR1YKJMc6SWZ Ru7muvxqTHgCtJVgxVz4qndCFKdYidiDeKe2/X/z5gf7pyYl3549O8JR tWdNKqutppk=
+none.example. 3600 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjG rhhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA +u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy 347cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQ zBkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysy LKOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/b ByBNsO70aEFTd
+none.example. 3600 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkdstool/none.example.ds.db b/bin/tests/system/checkdstool/none.example.ds.db
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bin/tests/system/checkdstool/none.example.ds.db
diff --git a/bin/tests/system/checkdstool/ok.example.dnskey.db b/bin/tests/system/checkdstool/ok.example.dnskey.db
new file mode 100644
index 0000000..c767c8f
--- /dev/null
+++ b/bin/tests/system/checkdstool/ok.example.dnskey.db
@@ -0,0 +1,2 @@
+ok.example. 625 IN DNSKEY 257 3 5 BEAAAAOhHQDBrhQbtphgq2wQUpEQ5t4DtUHxoMVFu2hWLDMvoOMRXjGr hhCeFvAZih7yJHf8ZGfW6hd38hXG/xylYCO6Krpbdojwx8YMXLA5/kA+ u50WIL8ZR1R6KTbsYVMf/Qx5RiNbPClw+vT+U8eXEJmO20jIS1ULgqy3 47cBB1zMnnz/4LJpA0da9CbKj3A254T515sNIMcwsB8/2+2E63/zZrQz Bkj0BrN/9Bexjpiks3jRhZatEsXn3dTy47R09Uix5WcJt+xzqZ7+ysyL KOOedS39Z7SDmsn2eA0FKtQpwA6LXeG2w+jxmw3oA8lVUgEf/rzeC/bB yBNsO70aEFTd
+ok.example. 625 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkdstool/ok.example.ds.db b/bin/tests/system/checkdstool/ok.example.ds.db
new file mode 100644
index 0000000..96b159b
--- /dev/null
+++ b/bin/tests/system/checkdstool/ok.example.ds.db
@@ -0,0 +1,2 @@
+ok.example. 3600 IN DS 12892 5 2 26584835CA80C81C91999F31CFAF2A0E89D4FF1C8FAFD0DDB31A85C7 19277C13
+ok.example. 3600 IN DS 12892 5 1 7AA4A3F416C2F2391FB7AB0D434F762CD62D1390
diff --git a/bin/tests/system/checkdstool/prep.example.db b/bin/tests/system/checkdstool/prep.example.db
new file mode 100644
index 0000000..5ba5987
--- /dev/null
+++ b/bin/tests/system/checkdstool/prep.example.db
@@ -0,0 +1,121 @@
+; File written on Thu Oct 5 23:44:34 2017
+; dnssec_signzone version 9.12.0a1
+prep.example. 300 IN SOA ns1.prep.example. hostmaster.prep.example. (
+ 1 ; serial
+ 2000 ; refresh (33 minutes 20 seconds)
+ 2000 ; retry (33 minutes 20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ 300 RRSIG SOA 8 2 300 (
+ 20171105054434 20171006054434 19260 prep.example.
+ 1fX0z7Swu4gMPews/ZE8bzNg+JXNedFBDGIH
+ PTSfVQtVLIvRWpME+PylX7MdVMZE/PST+x4/
+ mWyveyjetEOo7/7aQL236FfI0y6TxQFy7HwC
+ FMieqoQCUluuKOvToxg4vUp4GOdlUGbqC63h
+ DbX5Z37VptJXLkt4niF4Kl2iD+U9/bk7HAEU
+ 4zDiKroYnusGKfVB9xAWddzoHdLxhVuPi7ut
+ 328suPdgX0bfs7uB+y4cikhGzAmPpNMlGHju
+ qYG74NcFGQNutLB7ayx/m87t7mTty7jbNKm3
+ QWJSPf5IR8/kmzAi8HMnapY5vUmm+hX8JOfU
+ UtH7i0iEsUqRbEwu5A== )
+ 300 NS ns1.prep.example.
+ 300 RRSIG NS 8 2 300 (
+ 20171105054434 20171006054434 19260 prep.example.
+ u5sU2cfqNqIyCLw18ZNnFw28/GyRt0EOiPYS
+ dygmpfMDrvDaxjiiai8zWYjnl/E3qzVH9Zku
+ 07lEDORZdVb0uCDe1NynjAyw4AHps85cAwVc
+ 8HTSbzdVZsQTELpunYFJffh24PDr9unw7KOY
+ jzTP6qNedJ1uM54TOr177zfmBh7N2fkAoGyV
+ NjvTKrlgDYGNIn8/YMgHb4sNgyfe54MYY00f
+ kehVxfKnRCgDsbJ0Pk6jhBMCQWvOh8jG8WyV
+ ElAa/eMqlxUC1idF8ydWefjsI/7lPcjSalw9
+ qZw4CDCLHHZy0TOSmCYRRZuIeVXzBfDPJyi4
+ 2A3iLntKFJ4AOLFMJg== )
+ 3600 NSEC ns1.prep.example. NS SOA RRSIG NSEC DNSKEY
+ 3600 RRSIG NSEC 8 2 3600 (
+ 20171105054434 20171006054434 19260 prep.example.
+ Aed99/jdG82YAkKVWjoKOsAGtB3JnyKkCaAq
+ zgMrYkXU41y3KDCAmGzooGPQY7NN+WxX7FJ2
+ 1nXkgljma/azgpsbi9ssneFtv7PPFClVmN+u
+ j+mM4MK/ZR7eJOsMqETg4PAO5VAh6c/GVmyA
+ RD/m6EhJVZEjPfLWbDoC4hVAgem7DP/NMjyI
+ GfztpDjMmyLQyv6tL+UEXSJHGp3ZEa5Z5i7X
+ Nl/bRTUlZs7L4rTgoqHv6LEmsXKAf9rZYq4b
+ eP6GF9I1Ry41MfHLc7lPUmtR38ErEsM5uGzw
+ trCQYEFhuRWUBxZ8OSL2EZK9rUBXZX+cwK/8
+ ZP7mIfDfljkXPQcmow== )
+ 3600 DNSKEY 256 3 8 (
+ AwEAAfMzj6aZIgZDVcpH1pKOtq998E85+nEY
+ YJa0lLS8+QTCC1Efke8GLwsXT0IPTuwnOuXM
+ RjySirab0NuEr69T8KP/43YxcRdmCg89mjjN
+ szoVPPstC9xBKVOc0pRMDF7sfsTrSye3RY7+
+ Z6uZEH5FOAkz2hNbJJHOn4HpNUhLPJGRauhf
+ 0evamwUmQ/mlhkVW5q4WmqPCDMNY3K6XtkEm
+ cvm8n9ZCXC9Z5AX6KpynujzLdKyxpdGqUk6r
+ lavp9ILPpRKoTZDX+2q1pDgP5cDndwtgNSvU
+ DBQZoD0psS2cyB3PHo+dPwwpEyM//ZSKsH9m
+ e85Ti0413TOWFyFd/jUOUA8=
+ ) ; ZSK; alg = RSASHA256 ; key id = 19260
+ 3600 DNSKEY 257 3 8 (
+ AwEAAbV8X06Qvk350aZ6eZ1d7WbT1H/Y0Sv7
+ qAdbk5fbYIKpMvZ8D9xqoTHgD0z0uCgWWIcm
+ /xyKBfmax76oLwMBpR/kdtuJz0irgFITnJCH
+ pEfR9AJ/Mfm7NyMglq+/39I03E1/LXvpXQLG
+ tg+Mo/2CUE5sbG31jmPNK/2J8RMESkIi87fW
+ azZU/oyUEtECE5PGbdyw+4PacAsXNjnwl30T
+ aatL277wX4pt+IUPdE6EIph3t+dxXJ7OpHgW
+ 8g+YSHLlCImLVapdg3oD/cs6ncaBq9z7la5Y
+ dHNw2QAIAvQ11EsonrkonPqO6zNVZAVdT2VB
+ X5YzGAoCFUvbCvlnl2a7SxM=
+ ) ; KSK; alg = RSASHA256 ; key id = 65482
+ 3600 RRSIG DNSKEY 8 2 3600 (
+ 20171105054434 20171006054434 19260 prep.example.
+ pPw81pJ3PeF+tqEswTul9N8Qsl9JKgK4v8SV
+ lPfP0pnlMBMbtMFFkx5ZmhQg3Z3U8SdE64Bt
+ C5St3qItyyKdTQ0Rbm9mfV6twxDB8lVry8F7
+ Pv7gJmmcWzBcbLGcrXIrVNSZhigkemQXTElj
+ P8y1j7kaNFWBWbDMn7KesiZ9BiC6sqvuKa3R
+ wSofjwXTESspWZP0NtXr5ymaBIMR9UtNj5Wh
+ jm1+tg6BxNBKxhCHlSC0ltPS/qq9J1ZUmtJz
+ sj/EAFfPVJVuEveebMvi1oDWPTgajO9+EHl4
+ ELrgnQHCgaybMzbpd/A5+Tr1hQkv48I8Mb0/
+ 8LJ2/6xrvJm64yRteg== )
+ 3600 RRSIG DNSKEY 8 2 3600 (
+ 20171105054434 20171006054434 65482 prep.example.
+ WeIWiC9SnBe2+UocVjpap62O8Rz+iljwJiu9
+ VlGUwct3Vydq4/4FVAKdPklXV5cYbBLhO2MB
+ 3R4toX8RNU/0Ny8DnugQzLKvVfg0xoyU/UAJ
+ k4aWa/vPivSLGouLQPiNp71bdXN4LB/2xmzu
+ cPYXzS9ePpwCOp/9JLoNjBSMQkfjfWAcaNtj
+ 1DKDmHHL1sPMizninxSJLQOAKb+JwUAjAkOM
+ O1JqwkB12/IZuzxN5hly+uNsbFFxPzQkcnJ4
+ 5bhzxuh5D/JRXW0nF5aO4aR+9X+lSUpDJQZ1
+ 5fOt1cybZCn/ag68RA92zrnisdbrggJGS003
+ wn/VKbLVfFj3eQrfNA== )
+ns1.prep.example. 300 IN A 1.1.1.1
+ 300 RRSIG A 8 3 300 (
+ 20171105054434 20171006054434 19260 prep.example.
+ QUyDyJVk3JGEq+VTZtY3firzsRqOA0LUm3Tf
+ /fnemQBeOlMda2ErA7DqYVriIGfM8jph416E
+ YX8SKAZXGEAlsEbC9cWBVyc5TYH6tZ43sV51
+ 55kGTiUY92NnrH10Q+m2SLAEEaKCA/cgBwOR
+ tN2Wb1meHgiLbGYN2LbANfDQzoEk4AYAgT6r
+ wDKVVg/V9Ed7JnCnBQc9MN9+LQ3h4NBGUiEY
+ mr7HX2w+yzqcGFNLI1aFPe2IwFt120QPLyyl
+ cZgc6FUBX4YCnWoCb0aFyyOT76AQkKF5YBRn
+ gAv6S8q1pZ/0B5w4gjaLEGlts3LG0bxZ1GJd
+ gCQMEhgYgyXUchTtZA== )
+ 3600 NSEC prep.example. A RRSIG NSEC
+ 3600 RRSIG NSEC 8 3 3600 (
+ 20171105054434 20171006054434 19260 prep.example.
+ rDWN40u1a3DSzWOrS+4YR2XOxaem0BAQ/glN
+ QkXNDew1WsZo3fe0IHIhDKlJ/5MJAfAHq8Xs
+ A5UGUw2efoNAN/0LuWsI/9IPm4dwQOXiTCly
+ uxugXf5islPYyvn1Z14ay/7/2P3W6HZknXzo
+ lZFpwqfFZQCxz7c/1aH+2ntAMeqx8LHuewSr
+ Rz/sLsSiCcZQ6NMWnZdoC5SGy4CTcIIPPS8z
+ 9dQ6QYTC5iq4MKRfyJUyvODyU9be4e6jbo5b
+ mjRcov4ttbImhD5jrLAZIfjO6DSazGNVFf/x
+ 6rjxjrc8SISPkt2xYwcOlYch9OZuoH86wcZu
+ 3Don6yAnLDYDrZylAA== )
diff --git a/bin/tests/system/checkdstool/prep.example.ds.db b/bin/tests/system/checkdstool/prep.example.ds.db
new file mode 100644
index 0000000..dddcad6
--- /dev/null
+++ b/bin/tests/system/checkdstool/prep.example.ds.db
@@ -0,0 +1,2 @@
+prep.example. IN DS 65482 8 1 F3673708FBADDEC3EB55933E2E393ACE85EAC2BB
+prep.example. IN DS 65482 8 2 51A7C97AAC42803DA515D1CAFEE28031A5018F6345F12F4B6C1B6D20 02B59820
diff --git a/bin/tests/system/checkdstool/tests.sh b/bin/tests/system/checkdstool/tests.sh
new file mode 100644
index 0000000..4248b11
--- /dev/null
+++ b/bin/tests/system/checkdstool/tests.sh
@@ -0,0 +1,117 @@
+#!/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 [ "$CYGWIN" ]; then
+ DIG=".\dig.bat"
+ WINDSFROMKEY=`cygpath -w $DSFROMKEY`
+ CHECKDS="$CHECKDS -a sha1 -a sha256 -d $DIG -D $WINDSFROMKEY"
+else
+ DIG="./dig.sh"
+ CHECKDS="$CHECKDS -a sha1 -a sha256 -d $DIG -D $DSFROMKEY"
+fi
+chmod +x $DIG
+
+status=0
+n=1
+
+echo_i "checking for correct DS, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS ok.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for correct DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f ok.example.dnskey.db ok.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for incorrect DS, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS wrong.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for incorrect DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f wrong.example.dnskey.db wrong.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for partially missing DS, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS missing.example > checkds.out.$n 2>&1 && ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for partially missing DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f missing.example.dnskey.db missing.example > checkds.out.$n 2>&1 && ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-1.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*missing' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for entirely missing DS, looking up key via 'dig' ($n)"
+ret=0
+$CHECKDS none.example > checkds.out.$n 2>&1 && ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking for entirely missing DS, obtaining key from file ($n)"
+ret=0
+$CHECKDS -f none.example.dnskey.db none.example > checkds.out.$n 2>&1 && ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+echo_i "checking with prepared dsset file ($n)"
+ret=0
+$CHECKDS -f prep.example.db -s prep.example.ds.db prep.example > checkds.out.$n 2>&1 || ret=1
+grep 'SHA-1.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+grep 'SHA-256.*found' checkds.out.$n > /dev/null 2>&1 || ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
+if [ $status = 0 ]; then $SHELL clean.sh; fi
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/checkdstool/wrong.example.dnskey.db b/bin/tests/system/checkdstool/wrong.example.dnskey.db
new file mode 100644
index 0000000..cc5bfd6
--- /dev/null
+++ b/bin/tests/system/checkdstool/wrong.example.dnskey.db
@@ -0,0 +1,2 @@
+wrong.example. 3600 IN DNSKEY 257 3 5 AwEAAc6Cz10GXEh5lxA9ujTY/QarTajcUOBwwBYIeldjRsgoouK/UioY FYgxEFL0O5JK6YCRUoGzl3EgLr5GvNyhIp1PZpOpHf7o/4MVOZTGJzm/ sHWP5B+KcYjQOxJiDb433iCmRM4DpHPUUoxw0QbZglzAzl5MfKBoyZud lH59DdT/50bkBg8iVu35EzuW0SYt31k70hxHBSb2wAGWeqxEPKJ1nQiI UcrWNDeem7byrqjPN9wyZhq0XkQ9qbcYxAkRNd8Y7P0FyR1YKJMc6SWZ Ru7muvxqTHgCtJVgxVz4qndCFKdYidiDeKe2/X/z5gf7pyYl3549O8JR tWdNKqutppk=
+wrong.example. 3600 IN DNSKEY 256 3 5 BQEAAAAB2F1v2HWzCCE9vNsKfk0K8vd4EBwizNT9KO6WYXj0oxEL4eOJ aXbax/BzPFx+3qO8B8pu8E/JjkWH0oaYz4guUyTVmT5Eelg44Vb1kssy q8W27oQ+9qNiP8Jv6zdOj0uCB/N0fxfVL3371xbednFqoECfSFDZa6Hw jU1qzveSsW0=
diff --git a/bin/tests/system/checkdstool/wrong.example.ds.db b/bin/tests/system/checkdstool/wrong.example.ds.db
new file mode 100644
index 0000000..d7df610
--- /dev/null
+++ b/bin/tests/system/checkdstool/wrong.example.ds.db
@@ -0,0 +1,2 @@
+wrong.example. 3600 IN DS 1192 5 1 684BB5119673C9272A0A7582AF8576561B5D80EC
+wrong.example. 3600 IN DS 1192 5 2 14E4A873360E512CD2E8C2C331C4472F5EDAB0736669901F4D42E976 3D7B1F5C