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