1#!/bin/sh
2#
3# Copyright (C) 2009-2012  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
17# $Id: tests.sh,v 1.12.18.27 2012/02/07 00:34:20 each Exp $
18
19SYSTEMTESTTOP=..
20. $SYSTEMTESTTOP/conf.sh
21
22RANDFILE=random.data
23
24status=0
25n=0
26
27DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
28
29# convert private-type records to readable form
30showprivate () {
31    echo "-- $@ --"
32    $DIG $DIGOPTS +nodnssec +short @$2 -t type65534 $1 | cut -f3 -d' ' |
33        while read record; do
34            perl -e 'my $rdata = pack("H*", @ARGV[0]);
35                die "invalid record" unless length($rdata) == 5;
36                my ($alg, $key, $remove, $complete) = unpack("CnCC", $rdata);
37                my $action = "signing";
38                $action = "removing" if $remove;
39                my $state = " (incomplete)";
40                $state = " (complete)" if $complete;
41                print ("$action: alg: $alg, key: $key$state\n");' $record
42        done
43}
44
45# check that signing records are marked as complete
46checkprivate () {
47    ret=0
48    x=`showprivate "$@"`
49    echo $x | grep incomplete >&- 2>&- && ret=1
50    [ $ret = 1 ] && {
51        echo "$x"
52        echo "I:failed"
53    }
54    return $ret
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# this command should result in an empty file:
100$DIG $DIGOPTS +noall +answer nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1
101grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null && ret=1
102n=`expr $n + 1`
103if [ $ret != 0 ]; then echo "I:failed"; fi
104status=`expr $status + $ret`
105
106echo "I:checking NSEC3->NSEC conversion prerequisites ($n)"
107ret=0
108$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.test$n || ret=1
109grep "NSEC3PARAM" dig.out.ns3.test$n > /dev/null || ret=1
110n=`expr $n + 1`
111if [ $ret != 0 ]; then echo "I:failed"; fi
112status=`expr $status + $ret`
113
114echo "I:converting zones from nsec to nsec3"
115$NSUPDATE > /dev/null 2>&1 <<END	|| status=1
116server 10.53.0.3 5300
117zone nsec3.nsec3.example.
118update add nsec3.nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
119send
120zone optout.nsec3.example.
121update add optout.nsec3.example. 3600 NSEC3PARAM 1 1 10 BEEF
122send
123zone nsec3.example.
124update add nsec3.example. 3600 NSEC3PARAM 1 0 10 BEEF
125send
126zone nsec3.optout.example.
127update add nsec3.optout.example. 3600 NSEC3PARAM 1 0 10 BEEF
128send
129zone optout.optout.example.
130update add optout.optout.example. 3600 NSEC3PARAM 1 1 10 BEEF
131send
132zone optout.example.
133update add optout.example. 3600 NSEC3PARAM 1 1 10 BEEF
134send
135END
136
137# try to convert nsec.example; this should fail due to non-NSEC key
138$NSUPDATE > nsupdate.out 2>&1 <<END
139server 10.53.0.3 5300
140zone nsec.example.
141update add nsec.example. 3600 NSEC3PARAM 1 0 10 BEEF
142send
143END
144
145echo "I:waiting for changes to take effect"
146sleep 3
147
148echo "I:converting zone from nsec3 to nsec"
149$NSUPDATE > /dev/null 2>&1 << END	|| status=1
150server 10.53.0.3 5300
151zone nsec3-to-nsec.example.
152update delete nsec3-to-nsec.example. NSEC3PARAM
153send
154END
155
156echo "I:waiting for change to take effect"
157sleep 3
158
159echo "I:checking that expired RRSIGs from missing key are not deleted ($n)"
160ret=0
161missing=`sed 's/^K.*+007+0*\([0-9]\)/\1/' < missingzsk.key`
162$JOURNALPRINT ns3/nozsk.example.db.jnl | \
163   awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$missing || ret=1
164if [ $ret != 0 ]; then echo "I:failed"; fi
165status=`expr $status + $ret`
166
167echo "I:checking that expired RRSIGs from inactive key are not deleted ($n)"
168ret=0
169inactive=`sed 's/^K.*+007+0*\([0-9]\)/\1/' < inactivezsk.key`
170$JOURNALPRINT ns3/inaczsk.example.db.jnl | \
171   awk '{if ($1 == "del" && $5 == "RRSIG" && $12 == id) {exit 1}} END {exit 0}' id=$inactive || ret=1
172if [ $ret != 0 ]; then echo "I:failed"; fi
173status=`expr $status + $ret`
174
175echo "I:checking that non-replaceable RRSIGs are logged only once ($n)"
176ret=0
177loglines=`grep "Key nozsk.example/NSEC3RSASHA1/$missing .* retaining signatures" ns3/named.run | wc -l`
178[ "$loglines" -eq 1 ] || ret=1
179loglines=`grep "Key inaczsk.example/NSEC3RSASHA1/$missing .* retaining signatures" ns3/named.run | wc -l`
180[ "$loglines" -eq 1 ] || ret=1
181if [ $ret != 0 ]; then echo "I:failed"; fi
182status=`expr $status + $ret`
183
184# This test is above the rndc freeze/thaw calls because the apex node
185# will be resigned on thaw, increasing the serial number again.
186echo "I:checking serial is not incremented when signatures are unchanged ($n)"
187ret=0
188newserial=`$DIG $DIGOPTS +short soa nozsk.example @10.53.0.3 | awk '$0 !~ /SOA/ {print $3}'`
189[ "$newserial" -eq 2 ] || ret=1
190newserial=`$DIG $DIGOPTS +short soa inaczsk.example @10.53.0.3 | awk '$0 !~ /SOA/ {print $3}'`
191[ "$newserial" -eq 2 ] || ret=1
192if [ $ret != 0 ]; then echo "I:failed"; fi
193status=`expr $status + $ret`
194
195# Send rndc freeze command to ns1, ns2 and ns3, to force the dynamically
196# signed zones to be dumped to their zone files
197echo "I:dumping zone files"
198$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 freeze 2>&1 | sed 's/^/I:ns1 /'
199$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 thaw 2>&1 | sed 's/^/I:ns1 /'
200$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 freeze 2>&1 | sed 's/^/I:ns2 /'
201$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 thaw 2>&1 | sed 's/^/I:ns2 /'
202$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 freeze 2>&1 | sed 's/^/I:ns3 /'
203$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 thaw 2>&1 | sed 's/^/I:ns3 /'
204
205echo "I:checking expired signatures were updated ($n)"
206ret=0
207$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
208$DIG $DIGOPTS +noauth a.oldsigs.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
209$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
210grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
211n=`expr $n + 1`
212if [ $ret != 0 ]; then echo "I:failed"; fi
213status=`expr $status + $ret`
214
215echo "I:checking NSEC->NSEC3 conversion succeeded ($n)"
216ret=0
217$DIG $DIGOPTS nsec3.example. nsec3param @10.53.0.3 > dig.out.ns3.ok.test$n || ret=1
218grep "status: NOERROR" dig.out.ns3.ok.test$n > /dev/null || ret=1
219$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
220$DIG $DIGOPTS +noauth q.nsec3.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
221$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
222grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
223grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
224n=`expr $n + 1`
225if [ $ret != 0 ]; then echo "I:failed"; fi
226status=`expr $status + $ret`
227
228echo "I:checking NSEC->NSEC3 conversion failed with NSEC-only key ($n)"
229ret=0
230grep "failed: REFUSED" nsupdate.out > /dev/null || ret=1
231n=`expr $n + 1`
232if [ $ret != 0 ]; then echo "I:failed"; fi
233status=`expr $status + $ret`
234
235echo "I:checking NSEC3->NSEC conversion succeeded ($n)"
236ret=0
237# this command should result in an empty file:
238$DIG $DIGOPTS +noall +answer nsec3-to-nsec.example. nsec3param @10.53.0.3 > dig.out.ns3.nx.test$n || ret=1
239grep "NSEC3PARAM" dig.out.ns3.nx.test$n > /dev/null && ret=1
240$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
241$DIG $DIGOPTS +noauth q.nsec3-to-nsec.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
242$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
243grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
244grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
245n=`expr $n + 1`
246if [ $ret != 0 ]; then echo "I:failed"; fi
247status=`expr $status + $ret`
248
249echo "I:checking positive validation NSEC ($n)"
250ret=0
251$DIG $DIGOPTS +noauth a.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
252$DIG $DIGOPTS +noauth a.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
253$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
254grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
255n=`expr $n + 1`
256if [ $ret != 0 ]; then echo "I:failed"; fi
257status=`expr $status + $ret`
258
259echo "I:checking positive validation NSEC3 ($n)"
260ret=0
261$DIG $DIGOPTS +noauth a.nsec3.example. \
262	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
263$DIG $DIGOPTS +noauth a.nsec3.example. \
264	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
265$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
266grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
267n=`expr $n + 1`
268if [ $ret != 0 ]; then echo "I:failed"; fi
269status=`expr $status + $ret`
270
271echo "I:checking positive validation OPTOUT ($n)"
272ret=0
273$DIG $DIGOPTS +noauth a.optout.example. \
274	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
275$DIG $DIGOPTS +noauth a.optout.example. \
276	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
277$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
278grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
279n=`expr $n + 1`
280if [ $ret != 0 ]; then echo "I:failed"; fi
281status=`expr $status + $ret`
282
283echo "I:checking negative validation NXDOMAIN NSEC ($n)"
284ret=0
285$DIG $DIGOPTS +noauth q.example. @10.53.0.2 a > dig.out.ns2.test$n || ret=1
286$DIG $DIGOPTS +noauth q.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
287$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
288grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
289grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
290n=`expr $n + 1`
291if [ $ret != 0 ]; then echo "I:failed"; fi
292status=`expr $status + $ret`
293
294echo "I:checking negative validation NXDOMAIN NSEC3 ($n)"
295ret=0
296$DIG $DIGOPTS +noauth q.nsec3.example. \
297	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
298$DIG $DIGOPTS +noauth q.nsec3.example. \
299	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
300$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
301grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
302grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
303n=`expr $n + 1`
304if [ $ret != 0 ]; then echo "I:failed"; fi
305status=`expr $status + $ret`
306
307echo "I:checking negative validation NXDOMAIN OPTOUT ($n)"
308ret=0
309$DIG $DIGOPTS +noauth q.optout.example. \
310	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
311$DIG $DIGOPTS +noauth q.optout.example. \
312	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
313$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
314grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
315# Note - this is looking for failure, hence the &&
316grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
317n=`expr $n + 1`
318if [ $ret != 0 ]; then echo "I:failed"; fi
319status=`expr $status + $ret`
320
321echo "I:checking negative validation NODATA NSEC ($n)"
322ret=0
323$DIG $DIGOPTS +noauth a.example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
324$DIG $DIGOPTS +noauth a.example. @10.53.0.4 txt > dig.out.ns4.test$n || ret=1
325$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
326grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
327grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
328grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
329n=`expr $n + 1`
330if [ $ret != 0 ]; then echo "I:failed"; fi
331status=`expr $status + $ret`
332
333echo "I:checking negative validation NODATA NSEC3 ($n)"
334ret=0
335$DIG $DIGOPTS +noauth a.nsec3.example. \
336	@10.53.0.3 txt > dig.out.ns3.test$n || ret=1
337$DIG $DIGOPTS +noauth a.nsec3.example. \
338	@10.53.0.4 txt > dig.out.ns4.test$n || ret=1
339$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
340grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
341grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
342grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
343n=`expr $n + 1`
344if [ $ret != 0 ]; then echo "I:failed"; fi
345status=`expr $status + $ret`
346
347echo "I:checking negative validation NODATA OPTOUT ($n)"
348ret=0
349$DIG $DIGOPTS +noauth a.optout.example. \
350	@10.53.0.3 txt > dig.out.ns3.test$n || ret=1
351$DIG $DIGOPTS +noauth a.optout.example. \
352	@10.53.0.4 txt > dig.out.ns4.test$n || ret=1
353$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
354grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
355grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
356grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1
357n=`expr $n + 1`
358if [ $ret != 0 ]; then echo "I:failed"; fi
359status=`expr $status + $ret`
360
361# Check the insecure.example domain
362
363echo "I:checking 1-server insecurity proof NSEC ($n)"
364ret=0
365$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
366$DIG $DIGOPTS +noauth a.insecure.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
367$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
368grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
369# Note - this is looking for failure, hence the &&
370grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
371n=`expr $n + 1`
372if [ $ret != 0 ]; then echo "I:failed"; fi
373status=`expr $status + $ret`
374
375echo "I:checking 1-server negative insecurity proof NSEC ($n)"
376ret=0
377$DIG $DIGOPTS q.insecure.example. a @10.53.0.3 \
378	> dig.out.ns3.test$n || ret=1
379$DIG $DIGOPTS q.insecure.example. a @10.53.0.4 \
380	> dig.out.ns4.test$n || ret=1
381$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
382grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
383# Note - this is looking for failure, hence the &&
384grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
385n=`expr $n + 1`
386if [ $ret != 0 ]; then echo "I:failed"; fi
387status=`expr $status + $ret`
388
389# Check the secure.example domain
390
391echo "I:checking multi-stage positive validation NSEC/NSEC ($n)"
392ret=0
393$DIG $DIGOPTS +noauth a.secure.example. \
394	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
395$DIG $DIGOPTS +noauth a.secure.example. \
396	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
397$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
398grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
399grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
400n=`expr $n + 1`
401if [ $ret != 0 ]; then echo "I:failed"; fi
402status=`expr $status + $ret`
403
404echo "I:checking multi-stage positive validation NSEC/NSEC3 ($n)"
405ret=0
406$DIG $DIGOPTS +noauth a.nsec3.example. \
407	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
408$DIG $DIGOPTS +noauth a.nsec3.example. \
409	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
410$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
411grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
412grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
413n=`expr $n + 1`
414if [ $ret != 0 ]; then echo "I:failed"; fi
415status=`expr $status + $ret`
416
417echo "I:checking multi-stage positive validation NSEC/OPTOUT ($n)"
418ret=0
419$DIG $DIGOPTS +noauth a.optout.example. \
420	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
421$DIG $DIGOPTS +noauth a.optout.example. \
422	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
423$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
424grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
425grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
426n=`expr $n + 1`
427if [ $ret != 0 ]; then echo "I:failed"; fi
428status=`expr $status + $ret`
429
430echo "I:checking multi-stage positive validation NSEC3/NSEC ($n)"
431ret=0
432$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
433	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
434$DIG $DIGOPTS +noauth a.secure.nsec3.example. \
435	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
436$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
437grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
438grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
439n=`expr $n + 1`
440if [ $ret != 0 ]; then echo "I:failed"; fi
441status=`expr $status + $ret`
442
443echo "I:checking multi-stage positive validation NSEC3/NSEC3 ($n)"
444ret=0
445$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
446	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
447$DIG $DIGOPTS +noauth a.nsec3.nsec3.example. \
448	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
449$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
450grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
451grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
452n=`expr $n + 1`
453if [ $ret != 0 ]; then echo "I:failed"; fi
454status=`expr $status + $ret`
455
456echo "I:checking multi-stage positive validation NSEC3/OPTOUT ($n)"
457ret=0
458$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
459	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
460$DIG $DIGOPTS +noauth a.optout.nsec3.example. \
461	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
462$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
463grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
464grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
465n=`expr $n + 1`
466if [ $ret != 0 ]; then echo "I:failed"; fi
467status=`expr $status + $ret`
468
469echo "I:checking multi-stage positive validation OPTOUT/NSEC ($n)"
470ret=0
471$DIG $DIGOPTS +noauth a.secure.optout.example. \
472	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
473$DIG $DIGOPTS +noauth a.secure.optout.example. \
474	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
475$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
476grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
477grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
478n=`expr $n + 1`
479if [ $ret != 0 ]; then echo "I:failed"; fi
480status=`expr $status + $ret`
481
482echo "I:checking multi-stage positive validation OPTOUT/NSEC3 ($n)"
483ret=0
484$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
485	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
486$DIG $DIGOPTS +noauth a.nsec3.optout.example. \
487	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
488$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
489grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
490grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
491n=`expr $n + 1`
492if [ $ret != 0 ]; then echo "I:failed"; fi
493status=`expr $status + $ret`
494
495echo "I:checking multi-stage positive validation OPTOUT/OPTOUT ($n)"
496ret=0
497$DIG $DIGOPTS +noauth a.optout.optout.example. \
498	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
499$DIG $DIGOPTS +noauth a.optout.optout.example. \
500	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
501$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
502grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
503grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
504n=`expr $n + 1`
505if [ $ret != 0 ]; then echo "I:failed"; fi
506status=`expr $status + $ret`
507
508echo "I:checking empty NODATA OPTOUT ($n)"
509ret=0
510$DIG $DIGOPTS +noauth empty.optout.example. \
511	@10.53.0.3 a > dig.out.ns3.test$n || ret=1
512$DIG $DIGOPTS +noauth empty.optout.example. \
513	@10.53.0.4 a > dig.out.ns4.test$n || ret=1
514$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
515grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
516#grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
517n=`expr $n + 1`
518if [ $ret != 0 ]; then echo "I:failed"; fi
519status=`expr $status + $ret`
520
521# Check the insecure.secure.example domain (insecurity proof)
522
523echo "I:checking 2-server insecurity proof ($n)"
524ret=0
525$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.2 a \
526	> dig.out.ns2.test$n || ret=1
527$DIG $DIGOPTS +noauth a.insecure.secure.example. @10.53.0.4 a \
528	> dig.out.ns4.test$n || ret=1
529$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
530grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
531# Note - this is looking for failure, hence the &&
532grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
533n=`expr $n + 1`
534if [ $ret != 0 ]; then echo "I:failed"; fi
535status=`expr $status + $ret`
536
537# Check a negative response in insecure.secure.example
538
539echo "I:checking 2-server insecurity proof with a negative answer ($n)"
540ret=0
541$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.2 a > dig.out.ns2.test$n \
542	|| ret=1
543$DIG $DIGOPTS q.insecure.secure.example. @10.53.0.4 a > dig.out.ns4.test$n \
544	|| ret=1
545$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
546grep "status: NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
547# Note - this is looking for failure, hence the &&
548grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
549n=`expr $n + 1`
550if [ $ret != 0 ]; then echo "I:failed"; fi
551status=`expr $status + $ret`
552
553echo "I:checking security root query ($n)"
554ret=0
555$DIG $DIGOPTS . @10.53.0.4 key > dig.out.ns4.test$n || ret=1
556grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
557grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
558n=`expr $n + 1`
559if [ $ret != 0 ]; then echo "I:failed"; fi
560status=`expr $status + $ret`
561
562echo "I:checking positive validation RSASHA256 NSEC ($n)"
563ret=0
564$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
565$DIG $DIGOPTS +noauth a.rsasha256.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
566$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
567grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || ret=1
568n=`expr $n + 1`
569if [ $ret != 0 ]; then echo "I:failed"; fi
570status=`expr $status + $ret`
571
572echo "I:checking positive validation RSASHA512 NSEC ($n)"
573ret=0
574$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.3 a > dig.out.ns3.test$n || ret=1
575$DIG $DIGOPTS +noauth a.rsasha512.example. @10.53.0.4 a > dig.out.ns4.test$n || ret=1
576$PERL ../digcomp.pl dig.out.ns3.test$n dig.out.ns4.test$n || 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 that positive validation in a privately secure zone works ($n)"
583ret=0
584$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.2 \
585	> dig.out.ns2.test$n || ret=1
586$DIG $DIGOPTS +noauth a.private.secure.example. a @10.53.0.4 \
587	> dig.out.ns4.test$n || ret=1
588$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
589grep "NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
590# Note - this is looking for failure, hence the &&
591grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
592n=`expr $n + 1`
593if [ $ret != 0 ]; then echo "I:failed"; fi
594status=`expr $status + $ret`
595
596echo "I:checking that negative validation in a privately secure zone works ($n)"
597ret=0
598$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.2 \
599	> dig.out.ns2.test$n || ret=1
600$DIG $DIGOPTS +noauth q.private.secure.example. a @10.53.0.4 \
601	> dig.out.ns4.test$n || ret=1
602$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
603grep "NXDOMAIN" dig.out.ns4.test$n > /dev/null || ret=1
604# Note - this is looking for failure, hence the &&
605grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
606n=`expr $n + 1`
607if [ $ret != 0 ]; then echo "I:failed"; fi
608status=`expr $status + $ret`
609
610echo "I:checking privately secure to nxdomain works ($n)"
611ret=0
612$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.2 \
613	> dig.out.ns2.test$n || ret=1
614$DIG $DIGOPTS +noauth private2secure-nxdomain.private.secure.example. SOA @10.53.0.4 \
615	> dig.out.ns4.test$n || ret=1
616$PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
617# Note - this is looking for failure, hence the &&
618grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
619n=`expr $n + 1`
620if [ $ret != 0 ]; then echo "I:failed"; fi
621status=`expr $status + $ret`
622
623# Try validating with a revoked trusted key.
624# This should fail.
625
626echo "I:checking that validation returns insecure due to revoked trusted key ($n)"
627ret=0
628$DIG $DIGOPTS example. soa @10.53.0.5 > dig.out.ns5.test$n || ret=1
629grep "flags:.*; QUERY" dig.out.ns5.test$n > /dev/null || ret=1
630grep "flags:.* ad.*; QUERY" dig.out.ns5.test$n > /dev/null && ret=1
631n=`expr $n + 1`
632if [ $ret != 0 ]; then echo "I:failed"; fi
633status=`expr $status + $ret`
634
635echo "I:checking that revoked key is present ($n)"
636ret=0
637id=`cat rev.key`
638$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
639grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null || ret=1
640n=`expr $n + 1`
641if [ $ret != 0 ]; then echo "I:failed"; fi
642status=`expr $status + $ret`
643
644echo "I:checking that revoked key self-signs ($n)"
645ret=0
646id=`cat rev.key`
647$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
648grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
649n=`expr $n + 1`
650if [ $ret != 0 ]; then echo "I:failed"; fi
651status=`expr $status + $ret`
652
653echo "I:checking for unpublished key ($n)"
654ret=0
655id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < unpub.key`
656$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
657grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
658n=`expr $n + 1`
659if [ $ret != 0 ]; then echo "I:failed"; fi
660status=`expr $status + $ret`
661
662echo "I:checking that standby key does not sign records ($n)"
663ret=0
664id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < standby.key`
665$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
666grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
667n=`expr $n + 1`
668if [ $ret != 0 ]; then echo "I:failed"; fi
669status=`expr $status + $ret`
670
671echo "I:checking that deactivated key does not sign records  ($n)"
672ret=0
673id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < inact.key`
674$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
675grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
676n=`expr $n + 1`
677if [ $ret != 0 ]; then echo "I:failed"; fi
678status=`expr $status + $ret`
679
680echo "I:checking insertion of public-only key ($n)"
681ret=0
682id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < nopriv.key`
683file="ns1/`cat nopriv.key`.key"
684keydata=`grep DNSKEY $file`
685$NSUPDATE > /dev/null 2>&1 <<END	|| status=1
686server 10.53.0.1 5300
687zone .
688ttl 3600
689update add $keydata
690send
691END
692sleep 1
693$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
694grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
695n=`expr $n + 1`
696if [ $ret != 0 ]; then echo "I:failed"; fi
697status=`expr $status + $ret`
698
699echo "I:checking key deletion ($n)"
700ret=0
701id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < del.key`
702$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
703grep '; key id = '"$id"'$' dig.out.ns1.test$n > /dev/null && ret=1
704n=`expr $n + 1`
705if [ $ret != 0 ]; then echo "I:failed"; fi
706status=`expr $status + $ret`
707
708echo "I:checking secure-to-insecure transition, nsupdate ($n)"
709$NSUPDATE > /dev/null 2>&1 <<END	|| status=1
710server 10.53.0.3 5300
711zone secure-to-insecure.example
712update delete secure-to-insecure.example dnskey
713send
714END
715sleep 2
716$DIG $DIGOPTS axfr secure-to-insecure.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
717egrep 'RRSIG' dig.out.ns3.test$n > /dev/null && ret=1
718egrep '(DNSKEY|NSEC)' dig.out.ns3.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 secure-to-insecure transition, scheduled ($n)"
724file="ns3/`cat del1.key`.key"
725$SETTIME -I now -D now $file > /dev/null
726file="ns3/`cat del2.key`.key"
727$SETTIME -I now -D now $file > /dev/null
728$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 sign secure-to-insecure2.example. 2>&1 | sed 's/^/I:ns3 /'
729sleep 2
730$DIG $DIGOPTS axfr secure-to-insecure2.example @10.53.0.3 > dig.out.ns3.test$n || ret=1
731egrep 'RRSIG' dig.out.ns3.test$n > /dev/null && ret=1
732egrep '(DNSKEY|NSEC3)' dig.out.ns3.test$n > /dev/null && ret=1
733n=`expr $n + 1`
734if [ $ret != 0 ]; then echo "I:failed"; fi
735status=`expr $status + $ret`
736
737echo "I:checking that serial number and RRSIGs are both updated (rt21045) ($n)"
738ret=0
739oldserial=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '$0 !~ /SOA/ {print $3}'`
740oldinception=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u`
741
742$KEYGEN -3 -q -r $RANDFILE -K ns3 -P 0 -A +6d -I +38d -D +45d prepub.example > /dev/null
743
744$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 sign prepub.example 2>&1 | sed 's/^/I:ns1 /'
745newserial=$oldserial
746try=0
747while [ $oldserial -eq $newserial -a $try -lt 42 ]
748do
749	newserial=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 |
750		 awk '$0 !~ /SOA/ {print $3}'`
751	sleep 1
752	try=`expr $try + 1`
753done
754newinception=`$DIG $DIGOPTS +short soa prepub.example @10.53.0.3 | awk '/SOA/ {print $6}' | sort -u`
755#echo "$oldserial : $newserial"
756#echo "$oldinception : $newinception"
757
758[ "$oldserial" = "$newserial" ] && ret=1
759[ "$oldinception" = "$newinception" ] && ret=1
760if [ $ret != 0 ]; then echo "I:failed"; fi
761status=`expr $status + $ret`
762
763echo "I:preparing to test key change corner cases"
764echo "I:removing a private key file"
765file="ns1/`cat vanishing.key`.private"
766rm -f $file
767
768echo "I:preparing ZSK roll"
769starttime=`$PERL -e 'print time(), "\n";'`
770oldfile=`cat active.key`
771oldid=`sed 's/^K.+007+0*\([0-9]\)/\1/' < active.key`
772newfile=`cat standby.key`
773newid=`sed 's/^K.+007+0*\([0-9]\)/\1/' < standby.key`
774$SETTIME -K ns1 -I now+2s -D now+25 $oldfile > /dev/null
775$SETTIME -K ns1 -i 0 -S $oldfile $newfile > /dev/null
776
777# note previous zone serial number
778oldserial=`$DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}'`
779
780$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 loadkeys . 2>&1 | sed 's/^/I:ns1 /'
781sleep 4
782
783echo "I:revoking key to duplicated key ID"
784$SETTIME -R now -K ns2 Kbar.+005+30676.key > /dev/null
785
786$RNDC -c ../common/rndc.conf -s 10.53.0.2 -p 9953 loadkeys bar. 2>&1 | sed 's/^/I:ns2 /'
787
788echo "I:waiting for changes to take effect"
789sleep 5
790
791echo "I:checking former standby key is now active ($n)"
792ret=0
793$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
794grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
795n=`expr $n + 1`
796if [ $ret != 0 ]; then echo "I:failed"; fi
797status=`expr $status + $ret`
798
799echo "I:checking former standby key has only signed incrementally ($n)"
800ret=0
801$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
802grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null && ret=1
803grep 'RRSIG.*'" $oldid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
804n=`expr $n + 1`
805if [ $ret != 0 ]; then echo "I:failed"; fi
806status=`expr $status + $ret`
807
808echo "I:checking that signing records have been marked as complete ($n)"
809ret=0
810checkprivate . 10.53.0.1 || ret=1
811checkprivate bar 10.53.0.2 || ret=1
812checkprivate example 10.53.0.2 || ret=1
813checkprivate private.secure.example 10.53.0.3 || ret=1
814checkprivate nsec3.example 10.53.0.3 || ret=1
815checkprivate nsec3.nsec3.example 10.53.0.3 || ret=1
816checkprivate nsec3.optout.example 10.53.0.3 || ret=1
817checkprivate nsec3-to-nsec.example 10.53.0.3 || ret=1
818checkprivate nsec.example 10.53.0.3 || ret=1
819checkprivate oldsigs.example 10.53.0.3 || ret=1
820checkprivate optout.example 10.53.0.3 || ret=1
821checkprivate optout.nsec3.example 10.53.0.3 || ret=1
822checkprivate optout.optout.example 10.53.0.3 || ret=1
823checkprivate prepub.example 10.53.0.3 || ret=1
824checkprivate rsasha256.example 10.53.0.3 || ret=1
825checkprivate rsasha512.example 10.53.0.3 || ret=1
826checkprivate secure.example 10.53.0.3 || ret=1
827checkprivate secure.nsec3.example 10.53.0.3 || ret=1
828checkprivate secure.optout.example 10.53.0.3 || ret=1
829checkprivate secure-to-insecure2.example 10.53.0.3 || ret=1
830checkprivate secure-to-insecure.example 10.53.0.3 || ret=1
831checkprivate ttl1.example 10.53.0.3 || ret=1
832checkprivate ttl2.example 10.53.0.3 || ret=1
833checkprivate ttl3.example 10.53.0.3 || ret=1
834checkprivate ttl4.example 10.53.0.3 || ret=1
835n=`expr $n + 1`
836status=`expr $status + $ret`
837
838echo "I:forcing full sign"
839$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 sign . 2>&1 | sed 's/^/I:ns1 /'
840
841echo "I:waiting for change to take effect"
842sleep 5
843
844echo "I:checking former standby key has now signed fully ($n)"
845ret=0
846$DIG $DIGOPTS txt . @10.53.0.1 > dig.out.ns1.test$n || ret=1
847grep 'RRSIG.*'" $newid "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
848n=`expr $n + 1`
849if [ $ret != 0 ]; then echo "I:failed"; fi
850status=`expr $status + $ret`
851
852echo "I:checking SOA serial number has been incremented ($n)"
853ret=0
854newserial=`$DIG $DIGOPTS +short soa . @10.53.0.1 | awk '{print $3}'`
855[ "$newserial" != "$oldserial" ] || ret=1
856n=`expr $n + 1`
857if [ $ret != 0 ]; then echo "I:failed"; fi
858status=`expr $status + $ret`
859
860echo "I:checking delayed key publication/activation ($n)"
861ret=0
862zsk=`cat delayzsk.key`
863ksk=`cat delayksk.key`
864# publication and activation times should be unset
865$SETTIME -K ns3 -pA -pP $zsk | grep -v UNSET > /dev/null 2>&1 && ret=1
866$SETTIME -K ns3 -pA -pP $ksk | grep -v UNSET > /dev/null 2>&1 && ret=1
867$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
868# DNSKEY not expected:
869awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1
870n=`expr $n + 1`
871if [ $ret != 0 ]; then echo "I:failed"; fi
872status=`expr $status + $ret`
873
874echo "I:checking scheduled key publication, not activation ($n)"
875ret=0
876$SETTIME -K ns3 -P now+3s -A none $zsk > /dev/null 2>&1
877$SETTIME -K ns3 -P now+3s -A none $ksk > /dev/null 2>&1
878$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 loadkeys delay.example. 2>&1 | sed 's/^/I:ns2 /'
879
880echo "I:waiting for changes to take effect"
881sleep 5
882
883$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.test$n || ret=1
884# DNSKEY expected:
885awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.test$n || ret=1
886# RRSIG not expected:
887awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.test$n && ret=1
888n=`expr $n + 1`
889if [ $ret != 0 ]; then echo "I:failed"; fi
890status=`expr $status + $ret`
891
892echo "I:checking scheduled key activation ($n)"
893ret=0
894$SETTIME -K ns3 -A now+3s $zsk > /dev/null 2>&1
895$SETTIME -K ns3 -A now+3s $ksk > /dev/null 2>&1
896$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 loadkeys delay.example. 2>&1 | sed 's/^/I:ns2 /'
897
898echo "I:waiting for changes to take effect"
899sleep 5
900
901$DIG $DIGOPTS +noall +answer dnskey delay.example. @10.53.0.3 > dig.out.ns3.1.test$n || ret=1
902# DNSKEY expected:
903awk 'BEGIN {r=1} $4=="DNSKEY" {r=0} END {exit r}' dig.out.ns3.1.test$n || ret=1
904# RRSIG expected:
905awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.1.test$n || ret=1
906$DIG $DIGOPTS +noall +answer a a.delay.example. @10.53.0.3 > dig.out.ns3.2.test$n || ret=1
907# A expected:
908awk 'BEGIN {r=1} $4=="A" {r=0} END {exit r}' dig.out.ns3.2.test$n || ret=1
909# RRSIG expected:
910awk 'BEGIN {r=1} $4=="RRSIG" {r=0} END {exit r}' dig.out.ns3.2.test$n || ret=1
911n=`expr $n + 1`
912if [ $ret != 0 ]; then echo "I:failed"; fi
913status=`expr $status + $ret`
914
915echo "I:checking former active key was removed ($n)"
916#
917# Work out how long we need to sleep. Allow 4 seconds for the records
918# to be removed.
919#
920now=`$PERL -e 'print time(), "\n";'`
921sleep=`expr $starttime + 29 - $now`
922case $sleep in
923-*|0);;
924*) echo "I:waiting for timer to have activated"; sleep $sleep;;
925esac
926ret=0
927$DIG $DIGOPTS +multi dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
928grep '; key id = '"$oldid"'$' dig.out.ns1.test$n > /dev/null && ret=1
929n=`expr $n + 1`
930if [ $ret != 0 ]; then echo "I:failed"; fi
931status=`expr $status + $ret`
932
933echo "I:checking private key file removal caused no immediate harm ($n)"
934ret=0
935id=`sed 's/^K.+007+0*\([0-9]\)/\1/' < vanishing.key`
936$DIG $DIGOPTS dnskey . @10.53.0.1 > dig.out.ns1.test$n || ret=1
937grep 'RRSIG.*'" $id "'\. ' dig.out.ns1.test$n > /dev/null || ret=1
938n=`expr $n + 1`
939if [ $ret != 0 ]; then echo "I:failed"; fi
940status=`expr $status + $ret`
941
942echo "I:checking revoked key with duplicate key ID (failure expected) ($n)"
943lret=0
944id=30676
945$DIG $DIGOPTS +multi dnskey bar @10.53.0.2 > dig.out.ns2.test$n || lret=1
946grep '; key id = '"$id"'$' dig.out.ns2.test$n > /dev/null || lret=1
947$DIG $DIGOPTS dnskey bar @10.53.0.4 > dig.out.ns4.test$n || lret=1
948grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null || lret=1
949n=`expr $n + 1`
950if [ $lret != 0 ]; then echo "I:not yet implemented"; fi
951
952echo "I:checking key event timers are always set ($n)"
953# this is a regression test for a bug in which the next key event could
954# be scheduled for the present moment, and then never fire.  check for
955# visible evidence of this error in the logs:
956awk '/next key event/ {if ($1 == $8 && $2 == $9) exit 1}' */named.run || ret=1
957n=`expr $n + 1`
958if [ $ret != 0 ]; then echo "I:failed"; fi
959status=`expr $status + $ret`
960
961# this confirms that key events are never scheduled more than
962# a given number of seconds into the future, and that the last
963# event scheduled is within 10 seconds of expected interval.
964check_interval () {
965        awk '/next key event/ {print $2 ":" $9}' $1/named.run |
966	sed 's/\.//g' |
967            awk -F: '
968                     {
969                       x = ($6+ $5*60000 + $4*3600000) - ($3+ $2*60000 + $1*3600000);
970		       # abs(x) < 1000 ms treat as 'now'
971		       if (x < 1000 && x > -1000)
972                         x = 0;
973		       # convert to seconds
974		       x = x/1000;
975		       # handle end of day roll over
976		       if (x < 0)
977			 x = x + 24*3600;
978		       # handle log timestamp being a few milliseconds later
979                       if (x != int(x))
980                         x = int(x + 1);
981                       if (int(x) > int(interval))
982                         exit (1);
983                     }
984                     END { if (int(x) > int(interval) || int(x) < int(interval-10)) exit(1) }' interval=$2
985        return $?
986}
987
988echo "I:checking automatic key reloading interval ($n)"
989ret=0
990check_interval ns1 3600 || ret=1
991check_interval ns2 3600 || ret=1
992check_interval ns3 3600 || ret=1
993n=`expr $n + 1`
994if [ $ret != 0 ]; then echo "I:failed"; fi
995status=`expr $status + $ret`
996
997echo "I:forcing full sign with unreadable keys ($n)"
998ret=0
999chmod 0 ns1/K.+*+*.key ns1/K.+*+*.private || ret=1
1000$RNDC -c ../common/rndc.conf -s 10.53.0.1 -p 9953 sign . 2>&1 | sed 's/^/I:ns1 /'
1001$DIG $DIGOPTS . @10.53.0.1 dnskey > dig.out.ns1.test$n || ret=1
1002grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1
1003n=`expr $n + 1`
1004if [ $ret != 0 ]; then echo "I:failed"; fi
1005status=`expr $status + $ret`
1006
1007echo "I:test turning on auto-dnssec during reconfig ($n)"
1008ret=0
1009# first create a zone that doesn't have auto-dnssec
1010rm -f ns3/*.nzf
1011$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 /'
1012rekey_calls=`grep "zone reconf.example.*next key event" ns3/named.run | wc -l`
1013[ "$rekey_calls" -eq 0 ] || ret=1
1014# ...then we add auto-dnssec and reconfigure
1015nzf=`ls ns3/*.nzf`
1016echo 'zone reconf.example { type master; file "reconf.example.db"; allow-update { any; }; auto-dnssec maintain; };' > $nzf
1017$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reconfig 2>&1 | sed 's/^/I:ns3 /'
1018for i in 0 1 2 3 4 5 6 7 8 9; do
1019    lret=0
1020    rekey_calls=`grep "zone reconf.example.*next key event" ns3/named.run | wc -l`
1021    [ "$rekey_calls" -gt 0 ] || lret=1
1022    if [ "$lret" = 0 ]; then break; fi
1023    sleep 1
1024done
1025n=`expr $n + 1`
1026if [ "$lret" != 0 ]; then ret=$lret; fi
1027if [ $ret != 0 ]; then echo "I:failed"; fi
1028status=`expr $status + $ret`
1029
1030echo "I:exit status: $status"
1031
1032exit $status
1033