1#!/bin/sh
2#
3# Copyright (C) 2009-2014  Internet Systems Consortium, Inc. ("ISC")
4#
5# Permission to use, copy, modify, and/or distribute this software for any
6# purpose with or without fee is hereby granted, provided that the above
7# copyright notice and this permission notice appear in all copies.
8#
9# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15# PERFORMANCE OF THIS SOFTWARE.
16
17SYSTEMTESTTOP=..
18. $SYSTEMTESTTOP/conf.sh
19
20status=0
21n=0
22
23DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
24
25# convert private-type records to readable form
26showprivate () {
27    echo "-- $@ --"
28    $DIG $DIGOPTS +nodnssec +short @$2 -t type65534 $1 | cut -f3 -d' ' |
29        while read record; do
30            $PERL -e 'my $rdata = pack("H*", @ARGV[0]);
31                die "invalid record" unless length($rdata) == 5;
32                my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
33                my $action = "signing";
34                $action = "removing" if $remove;
35                my $state = " (incomplete)";
36                $state = " (complete)" if $complete;
37                print ("$action: alg: $alg, key: $key$state\n");' $record
38        done
39}
40
41# check that signing records are marked as complete
42checkprivate () {
43    _ret=0
44    expected="${3:-0}"
45    x=`showprivate "$@"`
46    echo $x | grep incomplete > /dev/null && _ret=1
47
48    if [ $_ret = $expected ]; then
49        return 0
50    fi
51
52    echo "$x"
53    echo "I:failed"
54    return 1
55}
56
57#
58#  The NSEC record at the apex of the zone and its RRSIG records are
59#  added as part of the last step in signing a zone.  We wait for the
60#  NSEC records to appear before proceeding with a counter to prevent
61#  infinite loops if there is a error.
62#
63echo "I:waiting for autosign changes to take effect"
64i=0
65while [ $i -lt 30 ]
66do
67	ret=0
68	#
69	# Wait for the root DNSKEY RRset to be fully signed.
70	#
71	$DIG $DIGOPTS . @10.53.0.1 dnskey > dig.out.ns1.test$n || ret=1
72	grep "ANSWER: 10," dig.out.ns1.test$n > /dev/null || ret=1
73	for z in .
74	do
75		$DIG $DIGOPTS $z @10.53.0.1 nsec > dig.out.ns1.test$n || ret=1
76		grep "NS SOA" dig.out.ns1.test$n > /dev/null || ret=1
77	done
78	for z in bar. example. private.secure.example.
79	do
80		$DIG $DIGOPTS $z @10.53.0.2 nsec > dig.out.ns2.test$n || ret=1
81		grep "NS SOA" dig.out.ns2.test$n > /dev/null || ret=1
82	done
83	for z in bar. example.
84	do
85		$DIG $DIGOPTS $z @10.53.0.3 nsec > dig.out.ns3.test$n || ret=1
86		grep "NS SOA" dig.out.ns3.test$n > /dev/null || ret=1
87	done
88	i=`expr $i + 1`
89	if [ $ret = 0 ]; then break; fi
90	echo "I:waiting ... ($i)"
91	sleep 2
92done
93n=`expr $n + 1`
94if [ $ret != 0 ]; then echo "I:failed"; else echo "I:done"; fi
95status=`expr $status + $ret`
96
97echo "I:checking NSEC->NSEC3 conversion prerequisites ($n)"
98ret=0
99# these commands should result in an empty file:
100$DIG $DIGOPTS +noall +answer nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
101grep "NSEC3PARAM" dig.out.ns3.1.test$n > /dev/null && ret=1
102$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
103grep "NSEC3PARAM" dig.out.ns3.2.test$n > /dev/null && ret=1
104n=`expr $n + 1`
105if [ $ret != 0 ]; then echo "I:failed"; fi
106status=`expr $status + $ret`
107
108echo "I:checking NSEC3->NSEC conversion prerequisites ($n)"
109ret=0
110$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1
111grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null || ret=1
112n=`expr $n + 1`
113if [ $ret != 0 ]; then echo "I:failed"; fi
114status=`expr $status + $ret`
115
116echo "I:converting zones from nsec to nsec3"
117$NSUPDATE > /dev/null 2>&1 <<END	|| status=1
118server 10.53.0.3 5300
119zone nsec3.nsec3.example.
120update add nsec3.nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
121send
122zone optout.nsec3.example.
123update add optout.nsec3.example. 3600 NSEC3PARAM 1 1 10 BEEF
124send
125zone nsec3.example.
126update add nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
127send
128zone autonsec3.example.
129update add autonsec3.example. 3600 NSEC3PARAM 1 0 20 DEAF
130send
131zone nsec3.optout.example.
132update add nsec3.optout.example. 3600 NSEC3PARAM 1 0 10 BEEF
133send
134zone optout.optout.example.
135update add optout.optout.example. 3600 NSEC3PARAM 1 1 10 BEEF
136send
137zone optout.example.
138update add optout.example. 3600 NSEC3PARAM 1 1 10 BEEF
139send
140END
141
142# try to convert nsec.example; this should fail due to non-NSEC key
143echo "I:preset nsec3param in unsigned zone via nsupdate ($n)"
144$NSUPDATE > nsupdate.out 2>&1 <<END
145server 10.53.0.3 5300
146zone nsec.example.
147update add nsec.example. 3600 NSEC3PARAM 1 0 10 BEEF
148send
149END
150
151echo "I:checking for nsec3param in unsigned zone ($n)"
152ret=0
153$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1
154grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null && ret=1
155n=`expr $n + 1`
156if [ $ret != 0 ]; then echo "I:failed"; fi
157status=`expr $status + $ret`
158
159echo "I:checking for nsec3param signing record ($n)"
160ret=0
161$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list autonsec3.example. > signing.out.test$n 2>&1
162grep "Pending NSEC3 chain 1 0 20 DEAF" signing.out.test$n > /dev/null || ret=1
163n=`expr $n + 1`
164if [ $ret != 0 ]; then echo "I:failed"; fi
165status=`expr $status + $ret`
166
167echo "I:resetting nsec3param via rndc signing ($n)"
168ret=0
169$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -clear all autonsec3.example. > /dev/null 2>&1
170$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -nsec3param 1 1 10 beef autonsec3.example. > /dev/null 2>&1
171for i in 0 1 2 3 4 5 6 7 8 9; do
172	ret=0
173	$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -list autonsec3.example. > signing.out.test$n 2>&1
174	grep "Pending NSEC3 chain 1 1 10 BEEF" signing.out.test$n > /dev/null || ret=1
175	num=`grep "Pending " signing.out.test$n | wc -l`
176	[ $num -eq 1 ] || ret=1
177	[ $ret -eq 0 ] && break
178	echo "I:waiting ... ($i)"
179	sleep 2
180done
181n=`expr $n + 1`
182if [ $ret != 0 ]; then echo "I:failed"; fi
183status=`expr $status + $ret`
184
185echo "I:signing preset nsec3 zone"
186zsk=`cat autozsk.key`
187ksk=`cat autoksk.key`
188$SETTIME -K ns3 -P now -A now $zsk > /dev/null 2>&1
189$SETTIME -K ns3 -P now -A now $ksk > /dev/null 2>&1
190$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 loadkeys autonsec3.example. 2>&1 | sed 's/^/I:ns3 /'
191
192echo "I:waiting for changes to take effect"
193sleep 3
194
195echo "I:converting zone from nsec3 to nsec"
196$NSUPDATE > /dev/null 2>&1 << END	|| status=1
197server 10.53.0.3 5300
198zone nsec3-to-nsec.example.
199update delete nsec3-to-nsec.example. NSEC3PARAM
200send
201END
202
203echo "I:waiting for change to take effect"
204sleep 3
205
206echo "I:checking that expired RRSIGs from missing key are not deleted ($n)"
207ret=0
208missing=`sed 's/^K.*+007+0*\([0-9]\)/\1/' < missingzsk.key`
209$JOURNALPRINT ns3/nozsk.example.db.jnl | \
210   awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$missing || ret=1
211n=`expr $n + 1`
212if [ $ret != 0 ]; then echo "I:failed"; fi
213status=`expr $status + $ret`
214
215echo "I:checking that expired RRSIGs from inactive key are not deleted ($n)"
216ret=0
217inactive=`sed 's/^K.*+007+0*\([0-9]\)/\1/' < inactivezsk.key`
218$JOURNALPRINT ns3/inaczsk.example.db.jnl | \
219   awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$inactive || ret=1
220n=`expr $n + 1`
221if [ $ret != 0 ]; then echo "I:failed"; fi
222status=`expr $status + $ret`
223
224echo "I:checking that non-replaceable RRSIGs are logged only once (missing private key) ($n)"
225ret=0
226loglines=`grep "Key nozsk.example/NSEC3RSASHA1/$missing .* retaining signatures" ns3/named.run | wc -l`
227[ "$loglines" -eq 1 ] || ret=1
228n=`expr $n + 1`
229if [ $ret != 0 ]; then echo "I:failed"; fi
230status=`expr $status + $ret`
231
232echo "I:checking that non-replaceable RRSIGs are logged only once (inactive private key) ($n)"
233ret=0
234loglines=`grep "Key inaczsk.example/NSEC3RSASHA1/$inactive .* retaining signatures" ns3/named.run | wc -l`
235[ "$loglines" -eq 1 ] || ret=1
236n=`expr $n + 1`
237if [ $ret != 0 ]; then echo "I:failed"; fi
238status=`expr $status + $ret`
239
240# Send rndc sync command to ns1, ns2 and ns3, to force the dynamically
241# signed zones to be dumped to their zone files
242echo "I:dumping zone files"
243$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 sync 2>&1 | sed 's/^/I:ns1 /'
244$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 sync 2>&1 | sed 's/^/I:ns2 /'
245$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 sync 2>&1 | sed 's/^/I:ns3 /'
246
247echo "I:checking expired signatures were updated ($n)"
248for i in 1 2 3 4 5 6 7 8 9
249do
250	ret=0
251	$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
252	$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
253	$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n > digcomp.out.test$n || ret=1
254	grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
255	[ $ret = 0 ] && break
256	sleep 1
257done
258if [ $ret != 0 ]; then cat digcomp.out.test$n; echo "I:failed"; fi
259n=`expr $n + 1`
260status=`expr $status + $ret`
261
262echo "I:checking NSEC->NSEC3 conversion succeeded ($n)"
263ret=0
264$DIG $DIGOPTS nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.ok.test$n || ret=1
265grep "status: NOERROR" dig.out.ns3.ok.test$n > /dev/null || ret=1
266$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
267$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
268$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
269grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
270grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
271n=`expr $n + 1`
272if [ $ret != 0 ]; then echo "I:failed"; fi
273status=`expr $status + $ret`
274
275echo "I:checking direct NSEC3 autosigning succeeded ($n)"
276ret=0
277$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.ok.test$n || ret=1
278[ -s  dig.out.ns3.ok.test$n ] || ret=1
279grep "NSEC3PARAM" dig.out.ns3.ok.test$n > /dev/null || ret=1
280$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
281$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
282$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
283grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
284grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
285n=`expr $n + 1`
286if [ $ret != 0 ]; then echo "I:failed"; fi
287status=`expr $status + $ret`
288
289echo "I:checking NSEC->NSEC3 conversion failed with NSEC-only key ($n)"
290ret=0
291grep "failed: REFUSED" nsupdate.out > /dev/null || ret=1
292n=`expr $n + 1`
293if [ $ret != 0 ]; then echo "I:failed"; fi
294status=`expr $status + $ret`
295
296echo "I:checking NSEC3->NSEC conversion succeeded ($n)"
297ret=0
298# this command should result in an empty file:
299$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || ret=1
300grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && ret=1
301$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
302$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
303$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
304grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
305grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
306n=`expr $n + 1`
307if [ $ret != 0 ]; then echo "I:failed"; fi
308status=`expr $status + $ret`
309
310echo "I:checking NSEC3->NSEC conversion with 'rndc signing -nsec3param none' ($n)"
311ret=0
312$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 signing -nsec3param none autonsec3.example. > /dev/null 2>&1
313sleep 2
314# this command should result in an empty file:
315$DIG $DIGOPTS +noall +answer autonsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || ret=1
316grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && ret=1
317$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
318$DIG $DIGOPTS +noauth q.autonsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
319$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
320grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
321grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
322n=`expr $n + 1`
323if [ $ret != 0 ]; then echo "I:failed"; fi
324status=`expr $status + $ret`
325
326echo "I:checking TTLs of imported DNSKEYs (no default) ($n)"
327ret=0
328$DIG $DIGOPTS +tcp +noall +answer dnskey ttl1.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
329[ -s dig.out.ns3.test$n ] || ret=1
330awk 'BEGIN {r=0} $2 != 300 {r=1; print "I:found TTL " $2} END {exit r}' dig.out.ns3.test$n || ret=1
331n=`expr $n + 1`
332if [ $ret != 0 ]; then echo "I:failed"; fi
333status=`expr $status + $ret`
334
335echo "I:checking TTLs of imported DNSKEYs (with default) ($n)"
336ret=0
337$DIG $DIGOPTS +tcp +noall +answer dnskey ttl2.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
338[ -s dig.out.ns3.test$n ] || ret=1
339awk 'BEGIN {r=0} $2 != 60 {r=1; print "I:found TTL " $2} END {exit r}' dig.out.ns3.test$n || ret=1
340n=`expr $n + 1`
341if [ $ret != 0 ]; then echo "I:failed"; fi
342status=`expr $status + $ret`
343
344echo "I:checking TTLs of imported DNSKEYs (mismatched) ($n)"
345ret=0
346$DIG $DIGOPTS +tcp +noall +answer dnskey ttl3.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
347[ -s dig.out.ns3.test$n ] || ret=1
348awk 'BEGIN {r=0} $2 != 30 {r=1; print "I:found TTL " $2} END {exit r}' dig.out.ns3.test$n || ret=1
349n=`expr $n + 1`
350if [ $ret != 0 ]; then echo "I:failed"; fi
351status=`expr $status + $ret`
352
353echo "I:checking TTLs of imported DNSKEYs (existing RRset) ($n)"
354ret=0
355$DIG $DIGOPTS +tcp +noall +answer dnskey ttl4.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
356[ -s dig.out.ns3.test$n ] || ret=1
357awk 'BEGIN {r=0} $2 != 30 {r=1; print "I:found TTL " $2} END {exit r}' dig.out.ns3.test$n || ret=1
358n=`expr $n + 1`
359if [ $ret != 0 ]; then echo "I:failed"; fi
360status=`expr $status + $ret`
361
362echo "I:checking positive validation NSEC ($n)"
363ret=0
364$DIG $DIGOPTS +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
365$DIG $DIGOPTS +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
366$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
367grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
368n=`expr $n + 1`
369if [ $ret != 0 ]; then echo "I:failed"; fi
370status=`expr $status + $ret`
371
372echo "I:checking positive validation NSEC3 ($n)"
373ret=0
374$DIG $DIGOPTS +noauth a.nsec3.example. \
375	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
376$DIG $DIGOPTS +noauth a.nsec3.example. \
377	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
378$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
379grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
380n=`expr $n + 1`
381if [ $ret != 0 ]; then echo "I:failed"; fi
382status=`expr $status + $ret`
383
384echo "I:checking positive validation OPTOUT ($n)"
385ret=0
386$DIG $DIGOPTS +noauth a.optout.example. \
387	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
388$DIG $DIGOPTS +noauth a.optout.example. \
389	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
390$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
391grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
392n=`expr $n + 1`
393if [ $ret != 0 ]; then echo "I:failed"; fi
394status=`expr $status + $ret`
395
396echo "I:checking negative validation NXDOMAIN NSEC ($n)"
397ret=0
398$DIG $DIGOPTS +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
399$DIG $DIGOPTS +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
400$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
401grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
402grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
403n=`expr $n + 1`
404if [ $ret != 0 ]; then echo "I:failed"; fi
405status=`expr $status + $ret`
406
407echo "I:checking negative validation NXDOMAIN NSEC3 ($n)"
408ret=0
409$DIG $DIGOPTS +noauth q.nsec3.example. \
410	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
411$DIG $DIGOPTS +noauth q.nsec3.example. \
412	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
413$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
414grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
415grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
416n=`expr $n + 1`
417if [ $ret != 0 ]; then echo "I:failed"; fi
418status=`expr $status + $ret`
419
420echo "I:checking negative validation NXDOMAIN OPTOUT ($n)"
421ret=0
422$DIG $DIGOPTS +noauth q.optout.example. \
423	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
424$DIG $DIGOPTS +noauth q.optout.example. \
425	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
426$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
427grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
428# Note - this is looking for failure, hence the &&
429grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
430n=`expr $n + 1`
431if [ $ret != 0 ]; then echo "I:failed"; fi
432status=`expr $status + $ret`
433
434echo "I:checking negative validation NODATA NSEC ($n)"
435ret=0
436$DIG $DIGOPTS +noauth a.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
437$DIG $DIGOPTS +noauth a.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
438$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
439grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
440grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
441grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
442n=`expr $n + 1`
443if [ $ret != 0 ]; then echo "I:failed"; fi
444status=`expr $status + $ret`
445
446echo "I:checking negative validation NODATA NSEC3 ($n)"
447ret=0
448$DIG $DIGOPTS +noauth a.nsec3.example. \
449	@10.53.0.3 txt > dig.out.ns3.test$n || ret=1
450$DIG $DIGOPTS +noauth a.nsec3.example. \
451	@10.53.0.4 txt > dig.out.ns4.test$n || ret=1
452$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
453grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
454grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
455grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
456n=`expr $n + 1`
457if [ $ret != 0 ]; then echo "I:failed"; fi
458status=`expr $status + $ret`
459
460echo "I:checking negative validation NODATA OPTOUT ($n)"
461ret=0
462$DIG $DIGOPTS +noauth a.optout.example. \
463	@10.53.0.3 txt > dig.out.ns3.test$n || ret=1
464$DIG $DIGOPTS +noauth a.optout.example. \
465	@10.53.0.4 txt > dig.out.ns4.test$n || ret=1
466$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
467grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
468grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
469grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
470n=`expr $n + 1`
471if [ $ret != 0 ]; then echo "I:failed"; fi
472status=`expr $status + $ret`
473
474# Check the insecure.example domain
475
476echo "I:checking 1-server insecurity proof NSEC ($n)"
477ret=0
478$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
479$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
480$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
481grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
482# Note - this is looking for failure, hence the &&
483grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
484n=`expr $n + 1`
485if [ $ret != 0 ]; then echo "I:failed"; fi
486status=`expr $status + $ret`
487
488echo "I:checking 1-server negative insecurity proof NSEC ($n)"
489ret=0
490$DIG $DIGOPTS q.insecure.example. a @10.53.0.3 \
491	> dig.out.ns3.test$n || ret=1
492$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \
493	> dig.out.ns4.test$n || ret=1
494$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
495grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
496# Note - this is looking for failure, hence the &&
497grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
498n=`expr $n + 1`
499if [ $ret != 0 ]; then echo "I:failed"; fi
500status=`expr $status + $ret`
501
502# Check the secure.example domain
503
504echo "I:checking multi-stage positive validation NSEC/NSEC ($n)"
505ret=0
506$DIG $DIGOPTS +noauth a.secure.example. \
507	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
508$DIG $DIGOPTS +noauth a.secure.example. \
509	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
510$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
511grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
512grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
513n=`expr $n + 1`
514if [ $ret != 0 ]; then echo "I:failed"; fi
515status=`expr $status + $ret`
516
517echo "I:checking multi-stage positive validation NSEC/NSEC3 ($n)"
518ret=0
519$DIG $DIGOPTS +noauth a.nsec3.example. \
520	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
521$DIG $DIGOPTS +noauth a.nsec3.example. \
522	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
523$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
524grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
525grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
526n=`expr $n + 1`
527if [ $ret != 0 ]; then echo "I:failed"; fi
528status=`expr $status + $ret`
529
530echo "I:checking multi-stage positive validation NSEC/OPTOUT ($n)"
531ret=0
532$DIG $DIGOPTS +noauth a.optout.example. \
533	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
534$DIG $DIGOPTS +noauth a.optout.example. \
535	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
536$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
537grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
538grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
539n=`expr $n + 1`
540if [ $ret != 0 ]; then echo "I:failed"; fi
541status=`expr $status + $ret`
542
543echo "I:checking multi-stage positive validation NSEC3/NSEC ($n)"
544ret=0
545$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
546	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
547$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
548	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
549$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
550grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
551grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
552n=`expr $n + 1`
553if [ $ret != 0 ]; then echo "I:failed"; fi
554status=`expr $status + $ret`
555
556echo "I:checking multi-stage positive validation NSEC3/NSEC3 ($n)"
557ret=0
558$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
559	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
560$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
561	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
562$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
563grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
564grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
565n=`expr $n + 1`
566if [ $ret != 0 ]; then echo "I:failed"; fi
567status=`expr $status + $ret`
568
569echo "I:checking multi-stage positive validation NSEC3/OPTOUT ($n)"
570ret=0
571$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
572	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
573$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
574	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
575$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
576grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
577grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
578n=`expr $n + 1`
579if [ $ret != 0 ]; then echo "I:failed"; fi
580status=`expr $status + $ret`
581
582echo "I:checking multi-stage positive validation OPTOUT/NSEC ($n)"
583ret=0
584$DIG $DIGOPTS +noauth a.secure.optout.example. \
585	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
586$DIG $DIGOPTS +noauth a.secure.optout.example. \
587	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
588$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
589grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
590grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
591n=`expr $n + 1`
592if [ $ret != 0 ]; then echo "I:failed"; fi
593status=`expr $status + $ret`
594
595echo "I:checking multi-stage positive validation OPTOUT/NSEC3 ($n)"
596ret=0
597$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
598	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
599$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
600	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
601$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
602grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
603grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
604n=`expr $n + 1`
605if [ $ret != 0 ]; then echo "I:failed"; fi
606status=`expr $status + $ret`
607
608echo "I:checking multi-stage positive validation OPTOUT/OPTOUT ($n)"
609ret=0
610$DIG $DIGOPTS +noauth a.optout.optout.example. \
611	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
612$DIG $DIGOPTS +noauth a.optout.optout.example. \
613	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
614$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
615grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
616grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
617n=`expr $n + 1`
618if [ $ret != 0 ]; then echo "I:failed"; fi
619status=`expr $status + $ret`
620
621echo "I:checking empty NODATA OPTOUT ($n)"
622ret=0
623$DIG $DIGOPTS +noauth empty.optout.example. \
624	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
625$DIG $DIGOPTS +noauth empty.optout.example. \
626	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
627$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
628grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
629#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
630n=`expr $n + 1`
631if [ $ret != 0 ]; then echo "I:failed"; fi
632status=`expr $status + $ret`
633
634# Check the insecure.secure.example domain (insecurity proof)
635
636echo "I:checking 2-server insecurity proof ($n)"
637ret=0
638$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.2 a \
639	> dig.out.ns2.test$n || ret=1
640$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.4 a \
641	> dig.out.ns4.test$n || ret=1
642$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
643grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
644# Note - this is looking for failure, hence the &&
645grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
646n=`expr $n + 1`
647if [ $ret != 0 ]; then echo "I:failed"; fi
648status=`expr $status + $ret`
649
650# Check a negative response in insecure.secure.example
651
652echo "I:checking 2-server insecurity proof with a negative answer ($n)"
653ret=0
654$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.2 a > dig.out.ns2.test$n \
655	|| ret=1
656$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.4 a > dig.out.ns4.test$n \
657	|| ret=1
658$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
659grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
660# Note - this is looking for failure, hence the &&
661grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
662n=`expr $n + 1`
663if [ $ret != 0 ]; then echo "I:failed"; fi
664status=`expr $status + $ret`
665
666echo "I:checking security root query ($n)"
667ret=0
668$DIG $DIGOPTS . @10.53.0.4 key > dig.out.ns4.test$n || ret=1
669grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
670grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
671n=`expr $n + 1`
672if [ $ret != 0 ]; then echo "I:failed"; fi
673status=`expr $status + $ret`
674
675echo "I:checking positive validation RSASHA256 NSEC ($n)"
676ret=0
677$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
678$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
679$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
680grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
681n=`expr $n + 1`
682if [ $ret != 0 ]; then echo "I:failed"; fi
683status=`expr $status + $ret`
684
685echo "I:checking positive validation RSASHA512 NSEC ($n)"
686ret=0
687$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
688$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
689$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
690grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
691n=`expr $n + 1`
692if [ $ret != 0 ]; then echo "I:failed"; fi
693status=`expr $status + $ret`
694
695echo "I:checking that positive validation in a privately secure zone works ($n)"
696ret=0
697$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.2 \
698	> dig.out.ns2.test$n || ret=1
699$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.4 \
700	> dig.out.ns4.test$n || ret=1
701$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
702grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
703# Note - this is looking for failure, hence the &&
704grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
705n=`expr $n + 1`
706if [ $ret != 0 ]; then echo "I:failed"; fi
707status=`expr $status + $ret`
708
709echo "I:checking that negative validation in a privately secure zone works ($n)"
710ret=0
711$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.2 \
712	> dig.out.ns2.test$n || ret=1
713$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.4 \
714	> dig.out.ns4.test$n || ret=1
715$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
716grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
717# Note - this is looking for failure, hence the &&
718grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
719n=`expr $n + 1`
720if [ $ret != 0 ]; then echo "I:failed"; fi
721status=`expr $status + $ret`
722
723echo "I:checking privately secure to nxdomain works ($n)"
724ret=0
725$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.2 \
726	> dig.out.ns2.test$n || ret=1
727$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \
728	> dig.out.ns4.test$n || ret=1
729$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
730# Note - this is looking for failure, hence the &&
731grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
732n=`expr $n + 1`
733if [ $ret != 0 ]; then echo "I:failed"; fi
734status=`expr $status + $ret`
735
736# Try validating with a revoked trusted key.
737# This should fail.
738
739echo "I:checking that validation returns insecure due to revoked trusted key ($n)"
740ret=0
741$DIG $DIGOPTS example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
742grep "flags:.*; QUERY" dig.out.ns5.test$n > /dev/null || ret=1
743grep "flags:.* ad.*; QUERY" dig.out.ns5.test$n > /dev/null && ret=1
744n=`expr $n + 1`
745if [ $ret != 0 ]; then echo "I:failed"; fi
746status=`expr $status + $ret`
747
748echo "I:checking that revoked key is present ($n)"
749ret=0
750id=`cat rev.key`
751$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
752grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null || ret=1
753n=`expr $n + 1`
754if [ $ret != 0 ]; then echo "I:failed"; fi
755status=`expr $status + $ret`
756
757echo "I:checking that revoked key self-signs ($n)"
758ret=0
759id=`cat rev.key`
760$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
761grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
762n=`expr $n + 1`
763if [ $ret != 0 ]; then echo "I:failed"; fi
764status=`expr $status + $ret`
765
766echo "I:checking for unpublished key ($n)"
767ret=0
768id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < unpub.key`
769$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
770grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
771n=`expr $n + 1`
772if [ $ret != 0 ]; then echo "I:failed"; fi
773status=`expr $status + $ret`
774
775echo "I:checking for activated but unpublished key ($n)"
776ret=0
777id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < activate-now-publish-1day.key`
778$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
779grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
780n=`expr $n + 1`
781if [ $ret != 0 ]; then echo "I:failed"; fi
782status=`expr $status + $ret`
783
784echo "I:checking that standby key does not sign records ($n)"
785ret=0
786id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < standby.key`
787$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
788grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
789n=`expr $n + 1`
790if [ $ret != 0 ]; then echo "I:failed"; fi
791status=`expr $status + $ret`
792
793echo "I:checking that deactivated key does not sign records  ($n)"
794ret=0
795id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < inact.key`
796$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
797grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
798n=`expr $n + 1`
799if [ $ret != 0 ]; then echo "I:failed"; fi
800status=`expr $status + $ret`
801
802echo "I:checking insertion of public-only key ($n)"
803ret=0
804id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < nopriv.key`
805file="ns1/`cat nopriv.key`.key"
806keydata=`grep DNSKEY $file`
807$NSUPDATE > /dev/null 2>&1 <<END	|| status=1
808server 10.53.0.1 5300
809zone .
810ttl 3600
811update add $keydata
812send
813END
814sleep 1
815$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
816grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
817n=`expr $n + 1`
818if [ $ret != 0 ]; then echo "I:failed"; fi
819status=`expr $status + $ret`
820
821echo "I:checking key deletion ($n)"
822ret=0
823id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < del.key`
824$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
825grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
826n=`expr $n + 1`
827if [ $ret != 0 ]; then echo "I:failed"; fi
828status=`expr $status + $ret`
829
830echo "I:checking secure-to-insecure transition, nsupdate ($n)"
831ret=0
832$NSUPDATE > /dev/null 2>&1 <<END	|| status=1
833server 10.53.0.3 5300
834zone secure-to-insecure.example
835update delete secure-to-insecure.example dnskey
836send
837END
838for i in 0 1 2 3 4 5 6 7 8 9; do
839	ret=0
840	$DIG $DIGOPTS axfr secure-to-insecure.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
841	egrep '(RRSIG|DNSKEY|NSEC)' dig.out.ns3.test$n > /dev/null && ret=1
842	[ $ret -eq 0 ] && break
843	echo "I:waiting ... ($i)"
844	sleep 2
845done
846n=`expr $n + 1`
847if [ $ret != 0 ]; then echo "I:failed"; fi
848status=`expr $status + $ret`
849
850echo "I:checking secure-to-insecure transition, scheduled ($n)"
851ret=0
852file="ns3/`cat del1.key`.key"
853$SETTIME -I now -D now $file > /dev/null
854file="ns3/`cat del2.key`.key"
855$SETTIME -I now -D now $file > /dev/null
856$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 sign secure-to-insecure2.example. 2>&1 | sed 's/^/I:ns3 /'
857for i in 0 1 2 3 4 5 6 7 8 9; do
858	ret=0
859	$DIG $DIGOPTS axfr secure-to-insecure2.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
860	egrep '(RRSIG|DNSKEY|NSEC3)' dig.out.ns3.test$n > /dev/null && ret=1
861	[ $ret -eq 0 ] && break
862	echo "I:waiting ... ($i)"
863	sleep 2
864done
865n=`expr $n + 1`
866if [ $ret != 0 ]; then echo "I:failed"; fi
867status=`expr $status + $ret`
868
869echo "I:checking that serial number and RRSIGs are both updated (rt21045) ($n)"
870ret=0
871oldserial=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '$0 !~ /SOA/ {print $3}'`
872oldinception=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u`
873
874$KEYGEN -3 -q -r $RANDFILE -K ns3 -P 0 -A +6d -I +38d -D +45d prepub.example > /dev/null
875
876$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 sign prepub.example 2>&1 | sed 's/^/I:ns1 /'
877newserial=$oldserial
878try=0
879while [ $oldserial -eq $newserial -a $try -lt 42 ]
880do
881	newserial=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 |
882		 awk '$0 !~ /SOA/ {print $3}'`
883	sleep 1
884	try=`expr $try + 1`
885done
886newinception=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u`
887#echo "$oldserial : $newserial"
888#echo "$oldinception : $newinception"
889
890[ "$oldserial" = "$newserial" ] && ret=1
891[ "$oldinception" = "$newinception" ] && ret=1
892if [ $ret != 0 ]; then echo "I:failed"; fi
893status=`expr $status + $ret`
894
895echo "I:preparing to test key change corner cases"
896echo "I:removing a private key file"
897file="ns1/`cat vanishing.key`.private"
898rm -f $file
899
900echo "I:preparing ZSK roll"
901starttime=`$PERL -e 'print time(), "\n";'`
902oldfile=`cat active.key`
903oldid=`sed 's/^K.+007+0*\([0-9]\)/\1/' < active.key`
904newfile=`cat standby.key`
905newid=`sed 's/^K.+007+0*\([0-9]\)/\1/' < standby.key`
906$SETTIME -K ns1 -I now+2s -D now+25 $oldfile > /dev/null
907$SETTIME -K ns1 -i 0 -S $oldfile $newfile > /dev/null
908
909# note previous zone serial number
910oldserial=`$DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}'`
911
912$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . 2>&1 | sed 's/^/I:ns1 /'
913sleep 4
914
915echo "I:revoking key to duplicated key ID"
916$SETTIME -R now -K ns2 Kbar.+005+30676.key > /dev/null
917
918$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 loadkeys bar. 2>&1 | sed 's/^/I:ns2 /'
919
920echo "I:waiting for changes to take effect"
921sleep 5
922
923echo "I:checking former standby key is now active ($n)"
924ret=0
925$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
926grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
927n=`expr $n + 1`
928if [ $ret != 0 ]; then echo "I:failed"; fi
929status=`expr $status + $ret`
930
931echo "I:checking former standby key has only signed incrementally ($n)"
932ret=0
933$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
934grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
935grep 'RRSIG.*'" $oldid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
936n=`expr $n + 1`
937if [ $ret != 0 ]; then echo "I:failed"; fi
938status=`expr $status + $ret`
939
940echo "I:checking that signing records have been marked as complete ($n)"
941ret=0
942checkprivate . 10.53.0.1 || ret=1
943checkprivate bar 10.53.0.2 || ret=1
944checkprivate example 10.53.0.2 || ret=1
945checkprivate private.secure.example 10.53.0.3 || ret=1
946checkprivate nsec3.example 10.53.0.3 || ret=1
947checkprivate nsec3.nsec3.example 10.53.0.3 || ret=1
948checkprivate nsec3.optout.example 10.53.0.3 || ret=1
949checkprivate nsec3-to-nsec.example 10.53.0.3 || ret=1
950checkprivate nsec.example 10.53.0.3 || ret=1
951checkprivate oldsigs.example 10.53.0.3 || ret=1
952checkprivate optout.example 10.53.0.3 || ret=1
953checkprivate optout.nsec3.example 10.53.0.3 || ret=1
954checkprivate optout.optout.example 10.53.0.3 || ret=1
955checkprivate prepub.example 10.53.0.3 1 || ret=1
956checkprivate rsasha256.example 10.53.0.3 || ret=1
957checkprivate rsasha512.example 10.53.0.3 || ret=1
958checkprivate secure.example 10.53.0.3 || ret=1
959checkprivate secure.nsec3.example 10.53.0.3 || ret=1
960checkprivate secure.optout.example 10.53.0.3 || ret=1
961checkprivate secure-to-insecure2.example 10.53.0.3 || ret=1
962checkprivate secure-to-insecure.example 10.53.0.3 || ret=1
963checkprivate ttl1.example 10.53.0.3 || ret=1
964checkprivate ttl2.example 10.53.0.3 || ret=1
965checkprivate ttl3.example 10.53.0.3 || ret=1
966checkprivate ttl4.example 10.53.0.3 || ret=1
967n=`expr $n + 1`
968status=`expr $status + $ret`
969
970echo "I:forcing full sign"
971$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 sign . 2>&1 | sed 's/^/I:ns1 /'
972
973echo "I:waiting for change to take effect"
974sleep 5
975
976echo "I:checking former standby key has now signed fully ($n)"
977ret=0
978$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
979grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
980n=`expr $n + 1`
981if [ $ret != 0 ]; then echo "I:failed"; fi
982status=`expr $status + $ret`
983
984echo "I:checking SOA serial number has been incremented ($n)"
985ret=0
986newserial=`$DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}'`
987[ "$newserial" != "$oldserial" ] || ret=1
988n=`expr $n + 1`
989if [ $ret != 0 ]; then echo "I:failed"; fi
990status=`expr $status + $ret`
991
992echo "I:checking delayed key publication/activation ($n)"
993ret=0
994zsk=`cat delayzsk.key`
995ksk=`cat delayksk.key`
996# publication and activation times should be unset
997$SETTIME -K ns3 -pA -pP $zsk | grep -v UNSET > /dev/null 2>&1 && ret=1
998$SETTIME -K ns3 -pA -pP $ksk | grep -v UNSET > /dev/null 2>&1 && ret=1
999$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
1000# DNSKEY not expected:
1001awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1
1002n=`expr $n + 1`
1003if [ $ret != 0 ]; then echo "I:failed"; fi
1004status=`expr $status + $ret`
1005
1006echo "I:checking scheduled key publication, not activation ($n)"
1007ret=0
1008$SETTIME -K ns3 -P now+3s -A none $zsk > /dev/null 2>&1
1009$SETTIME -K ns3 -P now+3s -A none $ksk > /dev/null 2>&1
1010$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 loadkeys delay.example. 2>&1 | sed 's/^/I:ns2 /'
1011
1012echo "I:waiting for changes to take effect"
1013sleep 5
1014
1015$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
1016# DNSKEY expected:
1017awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n || ret=1
1018# RRSIG not expected:
1019awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1
1020n=`expr $n + 1`
1021if [ $ret != 0 ]; then echo "I:failed"; fi
1022status=`expr $status + $ret`
1023
1024echo "I:checking scheduled key activation ($n)"
1025ret=0
1026$SETTIME -K ns3 -A now+3s $zsk > /dev/null 2>&1
1027$SETTIME -K ns3 -A now+3s $ksk > /dev/null 2>&1
1028$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 loadkeys delay.example. 2>&1 | sed 's/^/I:ns2 /'
1029
1030echo "I:waiting for changes to take effect"
1031sleep 5
1032
1033$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
1034# DNSKEY expected:
1035awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.1.test$n || ret=1
1036# RRSIG expected:
1037awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.1.test$n || ret=1
1038$DIG $DIGOPTS +noall +answer a a.delay.example. @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
1039# A expected:
1040awk 'BEGIN {r=1} $4=="A" {r=0} END {exit r}' dig.out.ns3.2.test$n || ret=1
1041# RRSIG expected:
1042awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.2.test$n || ret=1
1043n=`expr $n + 1`
1044if [ $ret != 0 ]; then echo "I:failed"; fi
1045status=`expr $status + $ret`
1046
1047echo "I:checking former active key was removed ($n)"
1048#
1049# Work out how long we need to sleep. Allow 4 seconds for the records
1050# to be removed.
1051#
1052now=`$PERL -e 'print time(), "\n";'`
1053sleep=`expr $starttime + 29 - $now`
1054case $sleep in
1055-*|0);;
1056*) echo "I:waiting for timer to have activated"; sleep $sleep;;
1057esac
1058ret=0
1059$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
1060grep '; key id = '"$oldid"'$' dig.out.ns1.test$n > /dev/null && ret=1
1061n=`expr $n + 1`
1062if [ $ret != 0 ]; then echo "I:failed"; fi
1063status=`expr $status + $ret`
1064
1065echo "I:checking private key file removal caused no immediate harm ($n)"
1066ret=0
1067id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < vanishing.key`
1068$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
1069grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
1070n=`expr $n + 1`
1071if [ $ret != 0 ]; then echo "I:failed"; fi
1072status=`expr $status + $ret`
1073
1074echo "I:checking revoked key with duplicate key ID (failure expected) ($n)"
1075lret=0
1076id=30676
1077$DIG $DIGOPTS +multi dnskey bar @10.53.0.2 > dig.out.ns2.test$n || lret=1
1078grep '; key id = '"$id"'$' dig.out.ns2.test$n > /dev/null || lret=1
1079$DIG $DIGOPTS dnskey bar @10.53.0.4 > dig.out.ns4.test$n || lret=1
1080grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || lret=1
1081n=`expr $n + 1`
1082if [ $lret != 0 ]; then echo "I:not yet implemented"; fi
1083
1084echo "I:checking key event timers are always set ($n)"
1085# this is a regression test for a bug in which the next key event could
1086# be scheduled for the present moment, and then never fire.  check for
1087# visible evidence of this error in the logs:
1088awk '/next key event/ {if ($1 == $8 && $2 == $9) exit 1}' */named.run || ret=1
1089n=`expr $n + 1`
1090if [ $ret != 0 ]; then echo "I:failed"; fi
1091status=`expr $status + $ret`
1092
1093# this confirms that key events are never scheduled more than
1094# 'dnssec-loadkeys-interval' minutes in the future, and that the
1095# event scheduled is within 10 seconds of expected interval.
1096check_interval () {
1097        awk '/next key event/ {print $2 ":" $9}' $1/named.run |
1098	sed 's/\.//g' |
1099            awk -F: '
1100                     {
1101                       x = ($6+ $5*60000 + $4*3600000) - ($3+ $2*60000 + $1*3600000);
1102		       # abs(x) < 1000 ms treat as 'now'
1103		       if (x < 1000 && x > -1000)
1104                         x = 0;
1105		       # convert to seconds
1106		       x = x/1000;
1107		       # handle end of day roll over
1108		       if (x < 0)
1109			 x = x + 24*3600;
1110		       # handle log timestamp being a few milliseconds later
1111                       if (x != int(x))
1112                         x = int(x + 1);
1113                       if (int(x) > int(interval))
1114                         exit (1);
1115                     }
1116                     END { if (int(x) > int(interval) || int(x) < int(interval-10)) exit(1) }' interval=$2
1117        return $?
1118}
1119
1120echo "I:checking automatic key reloading interval ($n)"
1121ret=0
1122check_interval ns1 3600 || ret=1
1123check_interval ns2 1800 || ret=1
1124check_interval ns3 600 || ret=1
1125n=`expr $n + 1`
1126if [ $ret != 0 ]; then echo "I:failed"; fi
1127status=`expr $status + $ret`
1128
1129echo "I:checking for key reloading loops ($n)"
1130ret=0
1131# every key event should schedule a successor, so these should be equal
1132rekey_calls=`grep "reconfiguring zone keys" ns*/named.run | wc -l`
1133rekey_events=`grep "next key event" ns*/named.run | wc -l`
1134[ "$rekey_calls" = "$rekey_events" ] || ret=1
1135n=`expr $n + 1`
1136if [ $ret != 0 ]; then echo "I:failed"; fi
1137status=`expr $status + $ret`
1138
1139echo "I:forcing full sign with unreadable keys ($n)"
1140ret=0
1141chmod 0 ns1/K.+*+*.key ns1/K.+*+*.private || ret=1
1142$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 sign . 2>&1 | sed 's/^/I:ns1 /'
1143$DIG $DIGOPTS . @10.53.0.1 dnskey > dig.out.ns1.test$n || ret=1
1144grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
1145n=`expr $n + 1`
1146if [ $ret != 0 ]; then echo "I:failed"; fi
1147status=`expr $status + $ret`
1148
1149echo "I:test turning on auto-dnssec during reconfig ($n)"
1150ret=0
1151# first create a zone that doesn't have auto-dnssec
1152rm -f ns3/*.nzf
1153$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 addzone reconf.example '{ type master; file "reconf.example.db"; };' 2>&1 | sed 's/^/I:ns3 /'
1154rekey_calls=`grep "zone reconf.example.*next key event" ns3/named.run | wc -l`
1155[ "$rekey_calls" -eq 0 ] || ret=1
1156# ...then we add auto-dnssec and reconfigure
1157nzf=`ls ns3/*.nzf`
1158echo 'zone reconf.example { type master; file "reconf.example.db"; allow-update { any; }; auto-dnssec maintain; };' > $nzf
1159$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reconfig 2>&1 | sed 's/^/I:ns3 /'
1160for i in 0 1 2 3 4 5 6 7 8 9; do
1161    lret=0
1162    rekey_calls=`grep "zone reconf.example.*next key event" ns3/named.run | wc -l`
1163    [ "$rekey_calls" -gt 0 ] || lret=1
1164    if [ "$lret" -eq 0 ]; then break; fi
1165    echo "I:waiting ... ($i)"
1166    sleep 1
1167done
1168n=`expr $n + 1`
1169if [ "$lret" != 0 ]; then ret=$lret; fi
1170if [ $ret != 0 ]; then echo "I:failed"; fi
1171status=`expr $status + $ret`
1172
1173echo "I:exit status: $status"
1174exit $status
1175