1#!/bin/sh
2#
3# Copyright (C) 2010-2012, 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
17# Id: tests.sh,v 1.21 2012/02/09 23:47:18 tbox Exp
18
19SYSTEMTESTTOP=..
20. $SYSTEMTESTTOP/conf.sh
21
22status=0
23
24pzone=parent.nil
25pfile=parent.db
26
27czone=child.parent.nil
28cfile=child.db
29
30echo "I:generating child's keys"
31# active zsk
32czsk1=`$KEYGEN -q -r $RANDFILE -L 30 $czone`
33
34# not yet published or active
35czsk2=`$KEYGEN -q -r $RANDFILE -P none -A none $czone`
36
37# published but not active
38czsk3=`$KEYGEN -q -r $RANDFILE -A none $czone`
39
40# inactive
41czsk4=`$KEYGEN -q -r $RANDFILE -P now-24h -A now-24h -I now $czone`
42
43# active in 12 hours, inactive 12 hours after that...
44czsk5=`$KEYGEN -q -r $RANDFILE -P now+12h -A now+12h -I now+24h $czone`
45
46# explicit successor to czk5
47# (suppressing warning about lack of removal date)
48czsk6=`$KEYGEN -q -r $RANDFILE -S $czsk5 -i 6h 2>&-`
49
50# active ksk
51cksk1=`$KEYGEN -q -r $RANDFILE -fk -L 30 $czone`
52
53# published but not YET active; will be active in 20 seconds
54cksk2=`$KEYGEN -q -r $RANDFILE -fk $czone`
55# $SETTIME moved after other $KEYGENs
56
57echo I:revoking key
58# revoking key changes its ID
59cksk3=`$KEYGEN -q -r $RANDFILE -fk $czone`
60cksk4=`$REVOKE $cksk3`
61
62echo I:generating parent keys
63pzsk=`$KEYGEN -q -r $RANDFILE $pzone`
64pksk=`$KEYGEN -q -r $RANDFILE -fk $pzone`
65
66echo "I:setting child's activation time"
67# using now+30s to fix RT 24561
68$SETTIME -A now+30s $cksk2 > /dev/null
69
70echo I:signing child zone
71czoneout=`$SIGNER -Sg -e now+1d -X now+2d -r $RANDFILE -o $czone $cfile 2>&1`
72
73echo I:signing parent zone
74pzoneout=`$SIGNER -Sg -r $RANDFILE -o $pzone $pfile 2>&1`
75
76czactive=`echo $czsk1 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
77czgenerated=`echo $czsk2 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
78czpublished=`echo $czsk3 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
79czinactive=`echo $czsk4 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
80czpredecessor=`echo $czsk5 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
81czsuccessor=`echo $czsk6 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
82ckactive=`echo $cksk1 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
83ckpublished=`echo $cksk2 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
84ckprerevoke=`echo $cksk3 | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
85ckrevoked=`echo $cksk4 | sed 's/.*+005+0*\([0-9]*\)$/\1/'`
86
87pzid=`echo $pzsk | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
88pkid=`echo $pksk | sed 's/^K.*+005+0*\([0-9]\)/\1/'`
89
90echo "I:checking dnssec-signzone output matches expectations"
91ret=0
92echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1
93echo "$pzoneout" | grep 'ZSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1
94echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' > /dev/null || ret=1
95echo "$czoneout" | grep 'ZSKs: 1 active, 2 stand-by, 0 revoked' > /dev/null || ret=1
96if [ $ret != 0 ]; then
97	echo "I: parent $pzoneout"
98	echo "I: child $czoneout"
99	echo "I:failed";
100fi
101status=`expr $status + $ret`
102
103echo "I:rechecking dnssec-signzone output with -x"
104ret=0
105# use an alternate output file so -x doesn't interfere with later checks
106pzoneout=`$SIGNER -Sxg -r $RANDFILE -o $pzone -f ${pfile}2.signed $pfile 2>&1`
107czoneout=`$SIGNER -Sxg -e now+1d -X now+2d -r $RANDFILE -o $czone -f ${cfile}2.signed $cfile 2>&1`
108echo "$pzoneout" | grep 'KSKs: 1 active, 0 stand-by, 0 revoked' > /dev/null || ret=1
109echo "$pzoneout" | grep 'ZSKs: 1 active, 0 present, 0 revoked' > /dev/null || ret=1
110echo "$czoneout" | grep 'KSKs: 1 active, 1 stand-by, 1 revoked' > /dev/null || ret=1
111echo "$czoneout" | grep 'ZSKs: 1 active, 2 present, 0 revoked' > /dev/null || ret=1
112if [ $ret != 0 ]; then
113	echo "I: parent $pzoneout"
114	echo "I: child $czoneout"
115	echo "I:failed";
116fi
117status=`expr $status + $ret`
118
119echo "I:checking parent zone DNSKEY set"
120ret=0
121grep "key id = $pzid" $pfile.signed > /dev/null || {
122	ret=1
123	echo "I: missing expected parent ZSK id = $pzid"
124}
125grep "key id = $pkid" $pfile.signed > /dev/null || {
126	ret=1
127	echo "I: missing expected parent KSK id = $pkid"
128}
129if [ $ret != 0 ]; then echo "I:failed"; fi
130status=`expr $status + $ret`
131
132echo "I:checking parent zone DS records"
133ret=0
134awk '$2 == "DS" {print $3}' $pfile.signed > dsset.out
135grep -w "$ckactive" dsset.out > /dev/null || ret=1
136grep -w "$ckpublished" dsset.out > /dev/null || ret=1
137# revoked key should not be there, hence the &&
138grep -w "$ckprerevoke" dsset.out > /dev/null && ret=1
139grep -w "$ckrevoked" dsset.out > /dev/null && ret=1
140if [ $ret != 0 ]; then echo "I:failed"; fi
141status=`expr $status + $ret`
142
143echo "I:checking child zone DNSKEY set"
144ret=0
145grep "key id = $ckactive" $cfile.signed > /dev/null || {
146	ret=1
147	echo "I: missing expected child KSK id = $ckactive"
148}
149grep "key id = $ckpublished" $cfile.signed > /dev/null || {
150	ret=1
151	echo "I: missing expected child prepublished KSK id = $ckpublished"
152}
153grep "key id = $ckrevoked" $cfile.signed > /dev/null || {
154	ret=1
155	echo "I: missing expected child revoked KSK id = $ckrevoked"
156}
157grep "key id = $czactive" $cfile.signed > /dev/null || {
158	ret=1
159	echo "I: missing expected child ZSK id = $czactive"
160}
161grep "key id = $czpublished" $cfile.signed > /dev/null || {
162	ret=1
163	echo "I: missing expected child prepublished ZSK id = $czpublished"
164}
165grep "key id = $czinactive" $cfile.signed > /dev/null || {
166	ret=1
167	echo "I: missing expected child inactive ZSK id = $czinactive"
168}
169# should not be there, hence the &&
170grep "key id = $ckprerevoke" $cfile.signed > /dev/null && {
171	ret=1
172	echo "I: found unexpect child pre-revoke ZSK id = $ckprerevoke"
173}
174grep "key id = $czgenerated" $cfile.signed > /dev/null && {
175	ret=1
176	echo "I: found unexpected child generated ZSK id = $czgenerated"
177}
178grep "key id = $czpredecessor" $cfile.signed > /dev/null && {
179	echo "I: found unexpected ZSK predecessor id = $czpredecessor (ignored)"
180}
181grep "key id = $czsuccessor" $cfile.signed > /dev/null && {
182	echo "I: found unexpected ZSK successor id = $czsuccessor (ignored)"
183}
184#grep "key id = $czpredecessor" $cfile.signed > /dev/null && ret=1
185#grep "key id = $czsuccessor" $cfile.signed > /dev/null && ret=1
186if [ $ret != 0 ]; then echo "I:failed"; fi
187status=`expr $status + $ret`
188
189echo "I:checking key TTLs are correct"
190grep "${czone}. 30 IN" ${czsk1}.key > /dev/null 2>&1 || ret=1
191grep "${czone}. 30 IN" ${cksk1}.key > /dev/null 2>&1 || ret=1
192grep "${czone}. IN" ${czsk2}.key > /dev/null 2>&1 || ret=1
193$SETTIME -L 45 ${czsk2} > /dev/null
194grep "${czone}. 45 IN" ${czsk2}.key > /dev/null 2>&1 || ret=1
195$SETTIME -L 0 ${czsk2} > /dev/null
196grep "${czone}. IN" ${czsk2}.key > /dev/null 2>&1 || ret=1
197if [ $ret != 0 ]; then echo "I:failed"; fi
198status=`expr $status + $ret`
199
200echo "I:checking key TTLs were imported correctly"
201awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 30 {r = 1} END {exit r}' \
202        ${cfile}.signed || ret=1
203if [ $ret != 0 ]; then echo "I:failed"; fi
204status=`expr $status + $ret`
205
206echo "I:re-signing and checking imported TTLs again"
207$SETTIME -L 15 ${czsk2} > /dev/null
208czoneout=`$SIGNER -Sg -e now+1d -X now+2d -r $RANDFILE -o $czone $cfile 2>&1`
209awk 'BEGIN {r = 0} $2 == "DNSKEY" && $1 != 15 {r = 1} END {exit r}' \
210        ${cfile}.signed || ret=1
211if [ $ret != 0 ]; then echo "I:failed"; fi
212status=`expr $status + $ret`
213
214# There is some weirdness in Solaris 10 (Generic_120011-14), which
215# is why the next section has all those echo $ret > /dev/null;sync
216# commands
217echo "I:checking child zone signatures"
218ret=0
219# check DNSKEY signatures first
220awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed > dnskey.sigs
221sub=0
222grep -w "$ckactive" dnskey.sigs > /dev/null || sub=1
223if [ $sub != 0 ]; then echo "I:missing ckactive $ckactive (dnskey)"; ret=1; fi
224echo $ret > /dev/null
225sync
226sub=0
227grep -w "$ckrevoked" dnskey.sigs > /dev/null || sub=1
228if [ $sub != 0 ]; then echo "I:missing ckrevoke $ckrevoke (dnskey)"; ret=1; fi
229echo $ret > /dev/null
230sync
231sub=0
232grep -w "$czactive" dnskey.sigs > /dev/null || sub=1
233if [ $sub != 0 ]; then echo "I:missing czactive $czactive (dnskey)"; ret=1; fi
234# should not be there:
235echo $ret > /dev/null
236sync
237sub=0
238grep -w "$ckprerevoke" dnskey.sigs > /dev/null && sub=1
239if [ $sub != 0 ]; then echo "I:found ckprerevoke $ckprerevoke (dnskey)"; ret=1; fi
240echo $ret > /dev/null
241sync
242sub=0
243grep -w "$ckpublished" dnskey.sigs > /dev/null && sub=1
244if [ $sub != 0 ]; then echo "I:found ckpublished $ckpublished (dnskey)"; ret=1; fi
245echo $ret > /dev/null
246sync
247sub=0
248grep -w "$czpublished" dnskey.sigs > /dev/null && sub=1
249if [ $sub != 0 ]; then echo "I:found czpublished $czpublished (dnskey)"; ret=1; fi
250echo $ret > /dev/null
251sync
252sub=0
253grep -w "$czinactive" dnskey.sigs > /dev/null && sub=1
254if [ $sub != 0 ]; then echo "I:found czinactive $czinactive (dnskey)"; ret=1; fi
255echo $ret > /dev/null
256sync
257sub=0
258grep -w "$czgenerated" dnskey.sigs > /dev/null && sub=1
259if [ $sub != 0 ]; then echo "I:found czgenerated $czgenerated (dnskey)"; ret=1; fi
260# now check other signatures first
261awk '$2 == "RRSIG" && $3 != "DNSKEY" { getline; print $3 }' $cfile.signed | sort -un > other.sigs
262# should not be there:
263echo $ret > /dev/null
264sync
265sub=0
266grep -w "$ckactive" other.sigs > /dev/null && sub=1
267if [ $sub != 0 ]; then echo "I:found ckactive $ckactive (other)"; ret=1; fi
268echo $ret > /dev/null
269sync
270sub=0
271grep -w "$ckpublished" other.sigs > /dev/null && sub=1
272if [ $sub != 0 ]; then echo "I:found ckpublished $ckpublished (other)"; ret=1; fi
273echo $ret > /dev/null
274sync
275sub=0
276grep -w "$ckprerevoke" other.sigs > /dev/null && sub=1
277if [ $sub != 0 ]; then echo "I:found ckprerevoke $ckprerevoke (other)"; ret=1; fi
278echo $ret > /dev/null
279sync
280sub=0
281grep -w "$ckrevoked" other.sigs > /dev/null && sub=1
282if [ $sub != 0 ]; then echo "I:found ckrevoked $ckrevoked (other)"; ret=1; fi
283echo $ret > /dev/null
284sync
285sub=0
286grep -w "$czpublished" other.sigs > /dev/null && sub=1
287if [ $sub != 0 ]; then echo "I:found czpublished $czpublished (other)"; ret=1; fi
288echo $ret > /dev/null
289sync
290sub=0
291grep -w "$czinactive" other.sigs > /dev/null && sub=1
292if [ $sub != 0 ]; then echo "I:found czinactive $czinactive (other)"; ret=1; fi
293echo $ret > /dev/null
294sync
295sub=0
296grep -w "$czgenerated" other.sigs > /dev/null && sub=1
297if [ $sub != 0 ]; then echo "I:found czgenerated $czgenerated (other)"; ret=1; fi
298echo $ret > /dev/null
299sync
300sub=0
301grep -w "$czpredecessor" other.sigs > /dev/null && sub=1
302if [ $sub != 0 ]; then echo "I:found czpredecessor $czpredecessor (other)"; ret=1; fi
303echo $ret > /dev/null
304sync
305sub=0
306grep -w "$czsuccessor" other.sigs > /dev/null && sub=1
307if [ $sub != 0 ]; then echo "I:found czsuccessor $czsuccessor (other)"; ret=1; fi
308if [ $ret != 0 ]; then
309    sed 's/^/I:dnskey sigs: /' < dnskey.sigs
310    sed 's/^/I:other sigs: /' < other.sigs
311    echo "I:failed";
312fi
313status=`expr $status + $ret`
314
315echo "I:checking RRSIG expiry date correctness"
316dnskey_expiry=`$CHECKZONE -o - $czone $cfile.signed 2> /dev/null |
317              awk '$4 == "RRSIG" && $5 == "DNSKEY" {print $9; exit}' |
318              cut -c1-10`
319soa_expiry=`$CHECKZONE -o - $czone $cfile.signed 2> /dev/null |
320           awk '$4 == "RRSIG" && $5 == "SOA" {print $9; exit}' |
321           cut -c1-10`
322[ $dnskey_expiry -gt $soa_expiry ] || ret=1
323if [ $ret != 0 ]; then echo "I:failed"; fi
324status=`expr $status + $ret`
325
326echo "I:waiting 30 seconds for key activation"
327sleep 30
328echo "I:re-signing child zone"
329czoneout2=`$SIGNER -Sg -r $RANDFILE -o $czone -f $cfile.new $cfile.signed 2>&1`
330mv $cfile.new $cfile.signed
331
332echo "I:checking dnssec-signzone output matches expectations"
333ret=0
334echo "$czoneout2" | grep 'KSKs: 2 active, 0 stand-by, 1 revoked' > /dev/null || ret=1
335if [ $ret != 0 ]; then echo "I:failed"; fi
336status=`expr $status + $ret`
337
338echo "I:checking child zone signatures again"
339ret=0
340awk '$2 == "RRSIG" && $3 == "DNSKEY" { getline; print $3 }' $cfile.signed > dnskey.sigs
341grep -w "$ckpublished" dnskey.sigs > /dev/null || ret=1
342if [ $ret != 0 ]; then echo "I:failed"; fi
343status=`expr $status + $ret`
344
345echo "I:exit status: $status"
346exit $status
347