xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/chain/tests.sh (revision d536862b7d93d77932ef5de7eebdc48d76921b77)
1# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
2#
3# This Source Code Form is subject to the terms of the Mozilla Public
4# License, v. 2.0. If a copy of the MPL was not distributed with this
5# file, you can obtain one at https://mozilla.org/MPL/2.0/.
6#
7# See the COPYRIGHT file distributed with this work for additional
8# information regarding copyright ownership.
9
10SYSTEMTESTTOP=..
11. $SYSTEMTESTTOP/conf.sh
12
13DIGOPTS="-p ${PORT}"
14RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
15SEND="$PERL $SYSTEMTESTTOP/send.pl 10.53.0.4 ${EXTRAPORT1}"
16status=0
17n=0
18
19n=`expr $n + 1`
20echo_i "checking short DNAME from authoritative ($n)"
21ret=0
22$DIG $DIGOPTS a.short-dname.example @10.53.0.2 a > dig.out.ns2.short || ret=1
23grep "status: NOERROR" dig.out.ns2.short > /dev/null || ret=1
24if [ $ret != 0 ]; then echo_i "failed"; fi
25status=`expr $status + $ret`
26
27n=`expr $n + 1`
28echo_i "checking short DNAME from recursive ($n)"
29ret=0
30$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
31$DIG $DIGOPTS a.short-dname.example @10.53.0.7 a > dig.out.ns4.short || ret=1
32grep "status: NOERROR" dig.out.ns4.short > /dev/null || ret=1
33if [ $ret != 0 ]; then echo_i "failed"; fi
34status=`expr $status + $ret`
35
36n=`expr $n + 1`
37echo_i "checking long DNAME from authoritative ($n)"
38ret=0
39$DIG $DIGOPTS a.long-dname.example @10.53.0.2 a > dig.out.ns2.long || ret=1
40grep "status: NOERROR" dig.out.ns2.long > /dev/null || ret=1
41if [ $ret != 0 ]; then echo_i "failed"; fi
42status=`expr $status + $ret`
43
44n=`expr $n + 1`
45echo_i "checking long DNAME from recursive ($n)"
46ret=0
47$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
48$DIG $DIGOPTS a.long-dname.example @10.53.0.7 a > dig.out.ns4.long || ret=1
49grep "status: NOERROR" dig.out.ns4.long > /dev/null || ret=1
50if [ $ret != 0 ]; then echo_i "failed"; fi
51status=`expr $status + $ret`
52
53n=`expr $n + 1`
54echo_i "checking (too) long DNAME from authoritative ($n)"
55ret=0
56$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.2 a > dig.out.ns2.toolong || ret=1
57grep "status: YXDOMAIN" dig.out.ns2.toolong > /dev/null || ret=1
58if [ $ret != 0 ]; then echo_i "failed"; fi
59status=`expr $status + $ret`
60
61n=`expr $n + 1`
62echo_i "checking (too) long DNAME from recursive with cached DNAME ($n)"
63ret=0
64$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
65$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.long-dname.example @10.53.0.7 a > dig.out.ns4.cachedtoolong || ret=1
66grep "status: YXDOMAIN" dig.out.ns4.cachedtoolong > /dev/null || ret=1
67grep '^long-dname\.example\..*DNAME.*long' dig.out.ns4.cachedtoolong > /dev/null || ret=1
68if [ $ret != 0 ]; then echo_i "failed"; fi
69status=`expr $status + $ret`
70
71n=`expr $n + 1`
72echo_i "checking (too) long DNAME from recursive without cached DNAME ($n)"
73ret=0
74$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
75$DIG $DIGOPTS 01234567890123456789012345678901234567890123456789.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglonglong.longlonglonglonglonglonglonglonglonglonglonglonglonglong.toolong-dname.example @10.53.0.7 a > dig.out.ns4.uncachedtoolong || ret=1
76grep "status: YXDOMAIN" dig.out.ns4.uncachedtoolong > /dev/null || ret=1
77grep '^toolong-dname\.example\..*DNAME.*long' dig.out.ns4.uncachedtoolong > /dev/null || ret=1
78if [ $ret != 0 ]; then echo_i "failed"; fi
79status=`expr $status + $ret`
80
81find_records() {
82	owner_name="$1"
83	rr_type="$2"
84	file="$3"
85	awk '$1 == "'"$owner_name"'" && $4 == "'"$rr_type"'" { print }' < "$file"
86}
87
88count_records() {
89	owner_name="$1"
90	rr_type="$2"
91	file="$3"
92	find_records "$owner_name" "$rr_type" "$file" | wc -l
93}
94
95exactly_one_record_exists_for() {
96	owner_name="$1"
97	rr_type="$2"
98	file="$3"
99	test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 1
100}
101
102no_records_exist_for() {
103	owner_name="$1"
104	rr_type="$2"
105	file="$3"
106	test "$(count_records "$owner_name" "$rr_type" "$file")" -eq 0
107}
108
109ensure_no_ds_in_bitmap() {
110	owner_name="$1"
111	rr_type="$2"
112	file="$3"
113	case "$rr_type" in
114		NSEC) start_index=6 ;;
115		NSEC3) start_index=10 ;;
116		*) exit 1 ;;
117	esac
118	find_records "$owner_name" "$rr_type" "$file" | awk '{ for (i='"$start_index"'; i<=NF; i++) if ($i == "DS") exit 1 }'
119}
120
121n=`expr $n + 1`
122echo_i "checking secure delegation prepared using CNAME chaining ($n)"
123ret=0
124# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
125# DS RRset.
126$DIG $DIGOPTS @10.53.0.2 cname.wildcard-secure.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
127# Ensure that the AUTHORITY section contains the expected NS and DS RRsets.
128exactly_one_record_exists_for "delegation.wildcard-secure.example." NS dig.out.2.$n || ret=1
129exactly_one_record_exists_for "delegation.wildcard-secure.example." DS dig.out.2.$n || ret=1
130if [ $ret != 0 ]; then echo_i "failed"; fi
131status=`expr $status + $ret`
132
133n=`expr $n + 1`
134echo_i "checking secure delegation prepared using wildcard expansion + CNAME chaining ($n)"
135ret=0
136# QNAME does not exist, so the AUTHORITY section should contain an NS RRset, an
137# NSEC record proving nonexistence of QNAME, and a DS RRset at the zone cut.
138$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-secure.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
139# Ensure that the AUTHORITY section contains the expected NS and DS RRsets.
140exactly_one_record_exists_for "delegation.wildcard-secure.example." NS dig.out.2.$n || ret=1
141exactly_one_record_exists_for "delegation.wildcard-secure.example." DS dig.out.2.$n || ret=1
142# Check NSEC records in the AUTHORITY section.
143no_records_exist_for "wildcard-secure.example." NSEC dig.out.2.$n || ret=1
144exactly_one_record_exists_for "*.wildcard-secure.example." NSEC dig.out.2.$n || ret=1
145no_records_exist_for "cname.wildcard-secure.example." NSEC dig.out.2.$n || ret=1
146no_records_exist_for "delegation.wildcard-secure.example." NSEC dig.out.2.$n || ret=1
147if [ $ret != 0 ]; then echo_i "failed"; fi
148status=`expr $status + $ret`
149
150n=`expr $n + 1`
151echo_i "checking insecure delegation prepared using CNAME chaining, NSEC ($n)"
152ret=0
153# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
154# single NSEC record proving nonexistence of a DS RRset at the zone cut.
155$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
156# Ensure that the AUTHORITY section contains an NS RRset without an associated
157# DS RRset.
158exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
159no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1
160# Check NSEC records in the AUTHORITY section.
161no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
162no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
163no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
164exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
165# Ensure the NSEC record for the zone cut does not have the DS bit set in the
166# type bit map.
167ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
168if [ $ret != 0 ]; then echo_i "failed"; fi
169status=`expr $status + $ret`
170
171n=`expr $n + 1`
172echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #1 ($n)"
173ret=0
174# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
175# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone
176# cut.  In this test case, these two NSEC records are different.
177$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
178# Ensure that the AUTHORITY section contains an NS RRset without an associated
179# DS RRset.
180exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
181no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1
182# Check NSEC records in the AUTHORITY section.
183no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
184exactly_one_record_exists_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
185no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
186exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
187# Ensure the NSEC record for the zone cut does not have the DS bit set in the
188# type bit map.
189ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
190if [ $ret != 0 ]; then echo_i "failed"; fi
191status=`expr $status + $ret`
192
193n=`expr $n + 1`
194echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC, QNAME #2 ($n)"
195ret=0
196# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
197# NSEC records proving nonexistence of both QNAME and a DS RRset at the zone
198# cut.  In this test case, the same NSEC record proves nonexistence of both the
199# QNAME and the DS RRset at the zone cut.
200$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
201# Ensure that the AUTHORITY section contains an NS RRset without an associated
202# DS RRset.
203exactly_one_record_exists_for "delegation.wildcard-nsec.example." NS dig.out.2.$n || ret=1
204no_records_exist_for "delegation.wildcard-nsec.example." DS dig.out.2.$n || ret=1
205# Check NSEC records in the AUTHORITY section.
206no_records_exist_for "wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
207no_records_exist_for "*.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
208no_records_exist_for "cname.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
209exactly_one_record_exists_for "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
210# Ensure the NSEC record for the zone cut does not have the DS bit set in the
211# type bit map.
212ensure_no_ds_in_bitmap "delegation.wildcard-nsec.example." NSEC dig.out.2.$n || ret=1
213if [ $ret != 0 ]; then echo_i "failed"; fi
214status=`expr $status + $ret`
215
216# Relevant NSEC3 hashes:
217#
218# - existing names:
219#
220#       $ nsec3hash - 1 0 wildcard-nsec3.example.
221#       38IVP9CN0LBISO6H3V5REQCKMTHLI5AN (salt=-, hash=1, iterations=0)
222#       $ nsec3hash - 1 0 cname.wildcard-nsec3.example.
223#       3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D (salt=-, hash=1, iterations=0)
224#       $ nsec3hash - 1 0 delegation.wildcard-nsec3.example.
225#       AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC (salt=-, hash=1, iterations=0)
226#       $ nsec3hash - 1 0 *.wildcard-nsec3.example.
227#       Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2 (salt=-, hash=1, iterations=0)
228#
229# - nonexistent names:
230#
231#       $ nsec3hash - 1 0 a-nonexistent-name.wildcard-nsec3.example.
232#       PST9IH6M0DG3M139CO3G12NUP4ER88SH (salt=-, hash=1, iterations=0)
233#       $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3.example.
234#       SG2DEHEAOGCKP7FTNQAUVC3I3TIPJH0J (salt=-, hash=1, iterations=0)
235
236n=`expr $n + 1`
237echo_i "checking insecure delegation prepared using CNAME chaining, NSEC3 ($n)"
238ret=0
239# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
240# single NSEC3 record proving nonexistence of a DS RRset at the zone cut.
241$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
242# Ensure that the AUTHORITY section contains an NS RRset without an associated
243# DS RRset.
244exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
245no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1
246# Check NSEC3 records in the AUTHORITY section.
247no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
248no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
249exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
250no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
251# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
252# the type bit map.
253ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
254if [ $ret != 0 ]; then echo_i "failed"; fi
255status=`expr $status + $ret`
256
257n=`expr $n + 1`
258echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #1 ($n)"
259ret=0
260# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
261# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
262# cut.  In this test case, these two NSEC3 records are different.
263$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
264# Ensure that the AUTHORITY section contains an NS RRset without an associated
265# DS RRset.
266exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
267no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1
268# Check NSEC3 records in the AUTHORITY section.
269no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
270no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
271exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
272exactly_one_record_exists_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
273# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
274# the type bit map.
275ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
276if [ $ret != 0 ]; then echo_i "failed"; fi
277status=`expr $status + $ret`
278
279n=`expr $n + 1`
280echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3, QNAME #2 ($n)"
281ret=0
282# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
283# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
284# cut.  In this test case, the same NSEC3 record proves nonexistence of both the
285# QNAME and the DS RRset at the zone cut.
286$DIG $DIGOPTS @10.53.0.2 a-nonexistent-name.wildcard-nsec3.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
287# Ensure that the AUTHORITY section contains an NS RRset without an associated
288# DS RRset.
289exactly_one_record_exists_for "delegation.wildcard-nsec3.example." NS dig.out.2.$n || ret=1
290no_records_exist_for "delegation.wildcard-nsec3.example." DS dig.out.2.$n || ret=1
291# Check NSEC3 records in the AUTHORITY section.
292no_records_exist_for "38IVP9CN0LBISO6H3V5REQCKMTHLI5AN.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
293no_records_exist_for "3DV6GNNVR0O8LA4DC4CHL2JTVNHT8Q1D.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
294exactly_one_record_exists_for "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
295no_records_exist_for "Q64D8L8HLSB3L98S59PM8OSSMI7SMQA2.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
296# Ensure the NSEC3 record matching the zone cut does not have the DS bit set in
297# the type bit map.
298ensure_no_ds_in_bitmap "AVKOGGGVJHFSLQA68TILKFKJ94AV4MNC.wildcard-nsec3.example." NSEC3 dig.out.2.$n || ret=1
299if [ $ret != 0 ]; then echo_i "failed"; fi
300status=`expr $status + $ret`
301
302# Relevant NSEC3 hashes:
303#
304# - existing names with corresponding NSEC3 records:
305#
306#       $ nsec3hash - 1 0 *.wildcard-nsec3-optout.example.
307#       2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO (salt=-, hash=1, iterations=0)
308#       $ nsec3hash - 1 0 cname.wildcard-nsec3-optout.example.
309#       OKRFKC9SS1O60E8U2980UD62MUSMKGUG (salt=-, hash=1, iterations=0)
310#       $ nsec3hash - 1 0 wildcard-nsec3-optout.example.
311#       SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI (salt=-, hash=1, iterations=0)
312#
313# - existing name with no corresponding NSEC3 record due to opt-out:
314#
315#       $ nsec3hash - 1 0 delegation.wildcard-nsec3-optout.example.
316#       UFP8PVECFTD57HU5PUD2HE0ES37QEOAP (salt=-, hash=1, iterations=0)
317#
318# - nonexistent names:
319#
320#       $ nsec3hash - 1 0 b-nonexistent-name.wildcard-nsec3-optout.example.
321#       3J38JE2OU0O7B4CE2ADMBBKJ5HT994S5 (salt=-, hash=1, iterations=0)
322#       $ nsec3hash - 1 0 z-nonexistent-name.wildcard-nsec3-optout.example.
323#       V7OTS4791T9SU0HKVL93EVNAJ9JH2CH3 (salt=-, hash=1, iterations=0)
324
325n=`expr $n + 1`
326echo_i "checking insecure delegation prepared using CNAME chaining, NSEC3 with opt-out ($n)"
327ret=0
328# QNAME exists, so the AUTHORITY section should only contain an NS RRset and a
329# single NSEC3 record proving nonexistence of a DS RRset at the zone cut.
330$DIG $DIGOPTS @10.53.0.2 cname.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
331# Ensure that the AUTHORITY section contains an NS RRset without an associated
332# DS RRset.
333exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
334no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1
335# Check NSEC3 records in the AUTHORITY section.
336no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
337no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
338exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
339# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
340# the type bit map.
341ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
342if [ $ret != 0 ]; then echo_i "failed"; fi
343status=`expr $status + $ret`
344
345n=`expr $n + 1`
346echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #1 ($n)"
347ret=0
348# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
349# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
350# cut.  In this test case, these two NSEC3 records are different.
351$DIG $DIGOPTS @10.53.0.2 b-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
352# Ensure that the AUTHORITY section contains an NS RRset without an associated
353# DS RRset.
354exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
355no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1
356# Check NSEC3 records in the AUTHORITY section.
357exactly_one_record_exists_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
358no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
359exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
360# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
361# the type bit map.
362ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
363if [ $ret != 0 ]; then echo_i "failed"; fi
364status=`expr $status + $ret`
365
366n=`expr $n + 1`
367echo_i "checking insecure delegation prepared using wildcard expansion + CNAME chaining, NSEC3 with opt-out, QNAME #2 ($n)"
368ret=0
369# QNAME does not exist, so the AUTHORITY section should contain an NS RRset and
370# NSEC3 records proving nonexistence of both QNAME and a DS RRset at the zone
371# cut.  In this test case, the same NSEC3 record proves nonexistence of both the
372# QNAME and the DS RRset at the zone cut.
373$DIG $DIGOPTS @10.53.0.2 z-nonexistent-name.wildcard-nsec3-optout.example A +norec +dnssec > dig.out.2.$n 2>&1 || ret=1
374# Ensure that the AUTHORITY section contains an NS RRset without an associated
375# DS RRset.
376exactly_one_record_exists_for "delegation.wildcard-nsec3-optout.example." NS dig.out.2.$n || ret=1
377no_records_exist_for "delegation.wildcard-nsec3-optout.example." DS dig.out.2.$n || ret=1
378# Check NSEC3 records in the AUTHORITY section.
379no_records_exist_for "2JGSPT59VJ7R9SQB5B9P6HPM5JBATOOO.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
380no_records_exist_for "OKRFKC9SS1O60E8U2980UD62MUSMKGUG.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
381exactly_one_record_exists_for "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
382# Ensure the NSEC3 record covering the zone cut does not have the DS bit set in
383# the type bit map.
384ensure_no_ds_in_bitmap "SS5M1RUBSGMANEQ1VLRDDEC6SOAT7HNI.wildcard-nsec3-optout.example." NSEC3 dig.out.2.$n || ret=1
385if [ $ret != 0 ]; then echo_i "failed"; fi
386status=`expr $status + $ret`
387
388n=`expr $n + 1`
389echo_i "checking CNAME to DNAME from authoritative ($n)"
390ret=0
391$DIG $DIGOPTS cname.example @10.53.0.2 a > dig.out.ns2.cname
392grep "status: NOERROR" dig.out.ns2.cname > /dev/null || ret=1
393if [ $ret != 0 ]; then echo_i "failed"; fi
394status=`expr $status + $ret`
395
396n=`expr $n + 1`
397echo_i "checking CNAME to DNAME from recursive"
398ret=0
399$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
400$DIG $DIGOPTS cname.example @10.53.0.7 a > dig.out.ns4.cname
401grep "status: NOERROR" dig.out.ns4.cname > /dev/null || ret=1
402grep '^cname.example.' dig.out.ns4.cname > /dev/null || ret=1
403grep '^cnamedname.example.' dig.out.ns4.cname > /dev/null || ret=1
404grep '^a.cnamedname.example.' dig.out.ns4.cname > /dev/null || ret=1
405grep '^a.target.example.' dig.out.ns4.cname > /dev/null || ret=1
406if [ $ret != 0 ]; then echo_i "failed"; fi
407status=`expr $status + $ret`
408
409n=`expr $n + 1`
410echo_i "checking DNAME is returned with synthesized CNAME before DNAME ($n)"
411ret=0
412$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
413$DIG $DIGOPTS @10.53.0.7 name.synth-then-dname.example.broken A > dig.out.test$n
414grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
415grep '^name.synth-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1
416grep '^synth-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1
417if [ $ret != 0 ]; then echo_i "failed"; fi
418status=`expr $status + $ret`
419
420n=`expr $n + 1`
421echo_i "checking DNAME is returned with CNAME to synthesized CNAME before DNAME ($n)"
422ret=0
423$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
424$DIG $DIGOPTS @10.53.0.7 cname-to-synth2-then-dname.example.broken A > dig.out.test$n
425grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
426grep '^cname-to-synth2-then-dname\.example\.broken\..*CNAME.*name\.synth2-then-dname\.example\.broken.$' dig.out.test$n > /dev/null || ret=1
427grep '^name\.synth2-then-dname\.example\.broken\..*CNAME.*name.$' dig.out.test$n > /dev/null || ret=1
428grep '^synth2-then-dname\.example\.broken\..*DNAME.*\.$' dig.out.test$n > /dev/null || ret=1
429if [ $ret != 0 ]; then echo_i "failed"; fi
430status=`expr $status + $ret`
431
432n=`expr $n + 1`
433echo_i "checking CNAME loops are detected ($n)"
434ret=0
435$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
436$DIG $DIGOPTS @10.53.0.7 loop.example > dig.out.test$n
437grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
438grep "ANSWER: 17" dig.out.test$n > /dev/null || ret=1
439if [ $ret != 0 ]; then echo_i "failed"; fi
440status=`expr $status + $ret`
441
442n=`expr $n + 1`
443echo_i "checking CNAME to external delegated zones is handled ($n)"
444ret=0
445$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
446$DIG $DIGOPTS @10.53.0.7 a.example > dig.out.test$n
447grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
448grep "ANSWER: 2" dig.out.test$n > /dev/null || ret=1
449if [ $ret != 0 ]; then echo_i "failed"; fi
450status=`expr $status + $ret`
451
452n=`expr $n + 1`
453echo_i "checking CNAME to internal delegated zones is handled ($n)"
454ret=0
455$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
456$DIG $DIGOPTS @10.53.0.7 b.example > dig.out.test$n
457grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
458grep "ANSWER: 2" dig.out.test$n > /dev/null || ret=1
459if [ $ret != 0 ]; then echo_i "failed"; fi
460status=`expr $status + $ret`
461
462n=`expr $n + 1`
463echo_i "checking CNAME to signed external delegation is handled ($n)"
464ret=0
465$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
466$DIG $DIGOPTS @10.53.0.7 c.example > dig.out.$n
467grep "status: NOERROR" dig.out.$n > /dev/null || ret=1
468if [ $ret != 0 ]; then echo_i "failed"; fi
469status=`expr $status + $ret`
470
471n=`expr $n + 1`
472echo_i "checking CNAME to signed internal delegation is handled ($n)"
473ret=0
474$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
475$DIG $DIGOPTS @10.53.0.7 d.example > dig.out.$n
476grep "status: NOERROR" dig.out.$n > /dev/null || ret=1
477if [ $ret != 0 ]; then echo_i "failed"; fi
478status=`expr $status + $ret`
479
480n=`expr $n + 1`
481echo_i "checking CNAME chains in various orders ($n)"
482ret=0
483$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i
484echo "cname,cname,cname|1,2,3,4,s1,s2,s3,s4" | $SEND
485$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
486grep 'status: NOERROR' dig.out.1.$n > /dev/null 2>&1 || ret=1
487grep 'ANSWER: 2' dig.out.1.$n > /dev/null 2>&1 || ret=1
488$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i
489$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
490echo "cname,cname,cname|1,1,2,2,3,4,s4,s3,s1" | $SEND
491$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.2.$n 2>&1
492grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
493grep 'ANSWER: 2' dig.out.2.$n > /dev/null 2>&1 || ret=1
494$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i
495$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
496echo "cname,cname,cname|2,1,3,4,s3,s1,s2,s4" | $SEND
497$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.3.$n 2>&1
498grep 'status: NOERROR' dig.out.3.$n > /dev/null 2>&1 || ret=1
499grep 'ANSWER: 2' dig.out.3.$n > /dev/null 2>&1 || ret=1
500$RNDCCMD 10.53.0.7 null --- start test$n - step 4 --- 2>&1 | sed 's/^/ns7 /' | cat_i
501$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
502echo "cname,cname,cname|4,3,2,1,s4,s3,s2,s1" | $SEND
503$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.4.$n 2>&1
504grep 'status: NOERROR' dig.out.4.$n > /dev/null 2>&1 || ret=1
505grep 'ANSWER: 2' dig.out.4.$n > /dev/null 2>&1 || ret=1
506echo "cname,cname,cname|4,3,2,1,s4,s3,s2,s1" | $SEND
507$RNDCCMD 10.53.0.7 null --- start test$n - step 5 --- 2>&1 | sed 's/^/ns7 /' | cat_i
508$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
509$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.5.$n 2>&1
510grep 'status: NOERROR' dig.out.5.$n > /dev/null 2>&1 || ret=1
511grep 'ANSWER: 2' dig.out.5.$n > /dev/null 2>&1 || ret=1
512$RNDCCMD 10.53.0.7 null --- start test$n - step 6 --- 2>&1 | sed 's/^/ns7 /' | cat_i
513$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
514echo "cname,cname,cname|4,3,3,3,s1,s1,1,3,4" | $SEND
515$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.6.$n 2>&1
516grep 'status: NOERROR' dig.out.6.$n > /dev/null 2>&1 || ret=1
517grep 'ANSWER: 2' dig.out.6.$n > /dev/null 2>&1 || ret=1
518if [ $ret != 0 ]; then echo_i "failed"; fi
519status=`expr $status + $ret`
520
521n=`expr $n + 1`
522echo_i "checking that only the initial CNAME is cached ($n)"
523ret=0
524$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
525echo "cname,cname,cname|1,2,3,4,s1,s2,s3,s4" | $SEND
526$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
527$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
528sleep 1
529$DIG $DIGOPTS +noall +answer @10.53.0.7 cname1.domain.nil > dig.out.2.$n 2>&1
530ttl=`awk '{print $2}' dig.out.2.$n`
531[ "$ttl" -eq 86400 ] || ret=1
532if [ $ret != 0 ]; then echo_i "failed"; fi
533status=`expr $status + $ret`
534
535n=`expr $n + 1`
536echo_i "checking DNAME chains in various orders ($n)"
537ret=0
538$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i
539$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
540echo "dname,dname|5,4,3,2,1,s5,s4,s3,s2,s1" | $SEND
541$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
542grep 'status: NOERROR' dig.out.1.$n > /dev/null 2>&1 || ret=1
543grep 'ANSWER: 3' dig.out.1.$n > /dev/null 2>&1 || ret=1
544$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i
545$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
546echo "dname,dname|5,4,3,2,1,s5,s4,s3,s2,s1" | $SEND
547$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.2.$n 2>&1
548grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
549grep 'ANSWER: 3' dig.out.2.$n > /dev/null 2>&1 || ret=1
550$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i
551$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
552echo "dname,dname|2,3,s1,s2,s3,s4,1" | $SEND
553$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.3.$n 2>&1
554grep 'status: NOERROR' dig.out.3.$n > /dev/null 2>&1 || ret=1
555grep 'ANSWER: 3' dig.out.3.$n > /dev/null 2>&1 || ret=1
556$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
557if [ $ret != 0 ]; then echo_i "failed"; fi
558status=`expr $status + $ret`
559
560n=`expr $n + 1`
561echo_i "checking external CNAME/DNAME chains in various orders ($n)"
562ret=0
563$RNDCCMD 10.53.0.7 null --- start test$n - step 1 --- 2>&1 | sed 's/^/ns7 /' | cat_i
564echo "xname,dname|1,2,3,4,s1,s2,s3,s4" | $SEND
565$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.1.$n 2>&1
566grep 'status: NOERROR' dig.out.1.$n > /dev/null 2>&1 || ret=1
567grep 'ANSWER: 2' dig.out.1.$n > /dev/null 2>&1 || ret=1
568$RNDCCMD 10.53.0.7 null --- start test$n - step 2 --- 2>&1 | sed 's/^/ns7 /' | cat_i
569$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
570echo "xname,dname|s2,2,s1,1,4,s4,3" | $SEND
571$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.2.$n 2>&1
572grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
573grep 'ANSWER: 2' dig.out.2.$n > /dev/null 2>&1 || ret=1
574$RNDCCMD 10.53.0.7 null --- start test$n - step 3 --- 2>&1 | sed 's/^/ns7 /' | cat_i
575$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
576echo "xname,dname|s2,2,2,2" | $SEND
577$DIG $DIGOPTS @10.53.0.7 test.domain.nil > dig.out.3.$n 2>&1
578grep 'status: SERVFAIL' dig.out.3.$n > /dev/null 2>&1 || ret=1
579$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
580if [ $ret != 0 ]; then echo_i "failed"; fi
581status=`expr $status + $ret`
582
583n=`expr $n + 1`
584echo_i "checking explicit DNAME query ($n)"
585ret=0
586$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
587$DIG $DIGOPTS @10.53.0.7 dname short-dname.example > dig.out.7.$n 2>&1
588grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
589if [ $ret != 0 ]; then echo_i "failed"; fi
590status=`expr $status + $ret`
591
592n=`expr $n + 1`
593echo_i "checking DNAME via ANY query ($n)"
594ret=0
595$RNDCCMD 10.53.0.7 null --- start test$n --- 2>&1 | sed 's/^/ns7 /' | cat_i
596$RNDCCMD 10.53.0.7 flush 2>&1 | sed 's/^/ns7 /' | cat_i
597$DIG $DIGOPTS @10.53.0.7 any short-dname.example > dig.out.7.$n 2>&1
598grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
599if [ $ret != 0 ]; then echo_i "failed"; fi
600status=`expr $status + $ret`
601
602# Regression test for CVE-2021-25215 (authoritative server).
603n=`expr $n + 1`
604echo_i "checking DNAME resolution via itself (authoritative) ($n)"
605ret=0
606$DIG $DIGOPTS @10.53.0.2 DNAME self.domain0.self.domain0.nil. > dig.out.2.$n 2>&1
607grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
608if [ $ret != 0 ]; then echo_i "failed"; fi
609status=`expr $status + $ret`
610
611# Regression test for CVE-2021-25215 (recursive resolver).
612n=`expr $n + 1`
613echo_i "checking DNAME resolution via itself (recursive) ($n)"
614ret=0
615$DIG $DIGOPTS @10.53.0.7 DNAME self.example.self.example.dname. > dig.out.7.$n 2>&1
616grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
617if [ $ret != 0 ]; then echo_i "failed"; fi
618status=`expr $status + $ret`
619
620echo_i "exit status: $status"
621[ $status -eq 0 ] || exit 1
622