1#!/bin/sh
2
3# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
4#
5# SPDX-License-Identifier: MPL-2.0
6#
7# This Source Code Form is subject to the terms of the Mozilla Public
8# License, v. 2.0.  If a copy of the MPL was not distributed with this
9# file, you can obtain one at https://mozilla.org/MPL/2.0/.
10#
11# See the COPYRIGHT file distributed with this work for additional
12# information regarding copyright ownership.
13
14set -e
15
16SYSTEMTESTTOP=..
17export ALGORITHM_SET="ecc_default"
18#shellcheck source=conf.sh
19. "$SYSTEMTESTTOP/conf.sh"
20
21dig_with_opts() (
22	"$DIG" +tcp +noadd +nosea +nostat +nocmd +dnssec -p "${PORT}" "$@"
23)
24
25delv_with_opts() (
26	"$DELV" -a ns1/trusted.conf -p "${PORT}" "$@"
27)
28
29rndccmd() (
30	"$RNDC" -c "$SYSTEMTESTTOP/common/rndc.conf" -p "${CONTROLPORT}" -s "$@"
31)
32
33mkeys_reconfig_on() (
34	nsidx=$1
35	rndccmd "10.53.0.${nsidx}" reconfig . | sed "s/^/ns${nsidx} /" | cat_i
36)
37
38mkeys_reload_on() (
39	nsidx=$1
40	nextpart "ns${nsidx}"/named.run > /dev/null
41	rndc_reload "ns${nsidx}" "10.53.0.${nsidx}"
42	wait_for_log 20 "loaded serial" "ns${nsidx}"/named.run || return 1
43)
44
45mkeys_loadkeys_on() (
46	nsidx=$1
47	nextpart "ns${nsidx}"/named.run > /dev/null
48	rndccmd "10.53.0.${nsidx}" loadkeys . | sed "s/^/ns${nsidx} /" | cat_i
49	wait_for_log 20 "next key event" "ns${nsidx}"/named.run || return 1
50)
51
52mkeys_refresh_on() (
53	nsidx=$1
54	nextpart "ns${nsidx}"/named.run > /dev/null
55	rndccmd "10.53.0.${nsidx}" managed-keys refresh | sed "s/^/ns${nsidx} /" | cat_i
56	wait_for_log 20 "Returned from key fetch in keyfetch_done()" "ns${nsidx}"/named.run || return 1
57)
58
59mkeys_sync_on() (
60	# No race with mkeys_refresh_on() is possible as even if the latter
61	# returns immediately after the expected log message is written, the
62	# managed-keys zone is already locked and the command below calls
63	# dns_zone_flush(), which also attempts to take that zone's lock
64	nsidx=$1
65	nextpart "ns${nsidx}"/named.run > /dev/null
66	rndccmd "10.53.0.${nsidx}" managed-keys sync | sed "s/^/ns${nsidx} /" | cat_i
67	wait_for_log 20 "dump_done" "ns${nsidx}"/named.run || return 1
68)
69
70mkeys_status_on() (
71	# No race with mkeys_refresh_on() is possible as even if the latter
72	# returns immediately after the expected log message is written, the
73	# managed-keys zone is already locked and the command below calls
74	# mkey_status(), which in turn calls dns_zone_getrefreshkeytime(),
75	# which also attempts to take that zone's lock
76	nsidx=$1
77	rndccmd "10.53.0.${nsidx}" managed-keys status
78)
79
80mkeys_flush_on() (
81	nsidx=$1
82	rndccmd "10.53.0.${nsidx}" flush | sed "s/^/ns${nsidx} /" | cat_i
83)
84
85mkeys_secroots_on() (
86	nsidx=$1
87	rndccmd "10.53.0.${nsidx}" secroots | sed "s/^/ns${nsidx} /" | cat_i
88)
89
90original=$(cat ns1/managed.key)
91originalid=$(cat ns1/managed.key.id)
92
93status=0
94n=1
95
96rm -f dig.out.*
97
98echo_i "check for signed record ($n)"
99ret=0
100dig_with_opts +norec example.  @10.53.0.1 TXT > dig.out.ns1.test$n || ret=1
101grep "^example\.[[:space:]]*[0-9]*[[:space:]]*IN[[:space:]]*TXT[[:space:]]*\"This is a test\.\"" dig.out.ns1.test$n > /dev/null || ret=1
102grep "^example\.[[:space:]]*[0-9]*[[:space:]]*IN[[:space:]]*RRSIG[[:space:]]*TXT[[:space:]]" dig.out.ns1.test$n > /dev/null || ret=1
103if [ $ret != 0 ]; then echo_i "failed"; fi
104status=$((status+ret))
105
106n=$((n+1))
107echo_i "check positive validation with valid trust anchor ($n)"
108ret=0
109dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
110grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
111grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
112if [ $ret != 0 ]; then echo_i "failed"; fi
113status=$((status+ret))
114
115n=$((n+1))
116ret=0
117echo_i "check positive validation using delv ($n)"
118delv_with_opts @10.53.0.1 txt example > delv.out$n || ret=1
119grep "; fully validated" delv.out$n > /dev/null || ret=1	# redundant
120grep "example..*TXT.*This is a test" delv.out$n > /dev/null || ret=1
121grep "example..*.RRSIG..*TXT" delv.out$n > /dev/null || ret=1
122if [ $ret != 0 ]; then echo_i "failed"; fi
123status=$((status+ret))
124
125n=$((n+1))
126echo_i "check for failed validation due to wrong key in managed-keys ($n)"
127ret=0
128dig_with_opts +noauth example. @10.53.0.3 txt > dig.out.ns3.test$n || ret=1
129grep "flags:.*ad.*QUERY" dig.out.ns3.test$n > /dev/null && ret=1
130grep "example..*.RRSIG..*TXT" dig.out.ns3.test$n > /dev/null && ret=1
131grep "opcode: QUERY, status: SERVFAIL, id" dig.out.ns3.test$n > /dev/null || ret=1
132if [ $ret != 0 ]; then echo_i "failed"; fi
133status=$((status+ret))
134
135n=$((n+1))
136echo_i "check new trust anchor can be added ($n)"
137ret=0
138standby1=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .)
139mkeys_loadkeys_on 1 || ret=1
140mkeys_refresh_on 2 || ret=1
141mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
142# there should be two keys listed now
143count=$(grep -c "keyid: " rndc.out.$n) || true
144[ "$count" -eq 2 ] || ret=1
145# two lines indicating trust status
146count=$(grep -c "trust" rndc.out.$n) || true
147[ "$count" -eq 2 ] || ret=1
148# one indicates current trust
149count=$(grep -c "trusted since" rndc.out.$n) || true
150[ "$count" -eq 1 ] || ret=1
151# one indicates pending trust
152count=$(grep -c "trust pending" rndc.out.$n) || true
153[ "$count" -eq 1 ] || ret=1
154if [ $ret != 0 ]; then echo_i "failed"; fi
155status=$((status+ret))
156
157n=$((n+1))
158echo_i "check new trust anchor can't be added with bad initial key ($n)"
159ret=0
160mkeys_refresh_on 3 || ret=1
161mkeys_status_on 3 > rndc.out.$n 2>&1 || ret=1
162# there should be one key listed now
163count=$(grep -c "keyid: " rndc.out.$n) || true
164[ "$count" -eq 1 ] || ret=1
165# one line indicating trust status
166count=$(grep -c "trust" rndc.out.$n) || true
167[ "$count" -eq 1 ] || ret=1
168# ... and the key is not trusted
169count=$(grep -c "no trust" rndc.out.$n) || true
170[ "$count" -eq 1 ] || ret=1
171if [ $ret != 0 ]; then echo_i "failed"; fi
172status=$((status+ret))
173
174n=$((n+1))
175echo_i "remove untrusted standby key, check timer restarts ($n)"
176ret=0
177mkeys_sync_on 2 || ret=1
178t1=$(grep "trust pending" ns2/managed-keys.bind) || true
179$SETTIME -D now -K ns1 "$standby1" > /dev/null
180mkeys_loadkeys_on 1 || ret=1
181# Less than a second may have passed since the last time ns2 received a
182# ./DNSKEY response from ns1.  Ensure keys are refreshed at a different
183# timestamp to prevent false negatives caused by the acceptance timer getting
184# reset to the same timestamp.
185sleep 1
186mkeys_refresh_on 2 || ret=1
187mkeys_sync_on 2 || ret=1
188t2=$(grep "trust pending" ns2/managed-keys.bind) || true
189# trust pending date must be different
190[ -n "$t2" ] || ret=1
191[ "$t1" = "$t2" ] && ret=1
192if [ $ret != 0 ]; then echo_i "failed"; fi
193status=$((status+ret))
194
195n=$((n+1))
196ret=0
197echo_i "restore untrusted standby key, revoke original key ($n)"
198t1=$t2
199$SETTIME -D none -K ns1 "$standby1" > /dev/null
200$SETTIME -R now -K ns1 "$original" > /dev/null
201mkeys_loadkeys_on 1 || ret=1
202# Less than a second may have passed since the last time ns2 received a
203# ./DNSKEY response from ns1.  Ensure keys are refreshed at a different
204# timestamp to prevent false negatives caused by the acceptance timer getting
205# reset to the same timestamp.
206sleep 1
207mkeys_refresh_on 2 || ret=1
208mkeys_sync_on 2 || ret=1
209mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
210# two keys listed
211count=$(grep -c "keyid: " rndc.out.$n) || true
212[ "$count" -eq 2 ] || ret=1
213# two lines indicating trust status
214count=$(grep -c "trust" rndc.out.$n) || true
215[ "$count" -eq 2 ] || ret=1
216# trust is revoked
217count=$(grep -c "trust revoked" rndc.out.$n) || true
218[ "$count" -eq 1 ] || ret=1
219# removal scheduled
220count=$(grep -c "remove at" rndc.out.$n) || true
221[ "$count" -eq 1 ] || ret=1
222# trust is still pending on the standby key
223count=$(grep -c "trust pending" rndc.out.$n) || true
224[ "$count" -eq 1 ] || ret=1
225# pending date moved forward for the standby key
226t2=$(grep "trust pending" ns2/managed-keys.bind) || true
227[ -n "$t2" ] || ret=1
228[ "$t1" = "$t2" ] && ret=1
229if [ $ret != 0 ]; then echo_i "failed"; fi
230status=$((status+ret))
231
232n=$((n+1))
233ret=0
234echo_i "refresh managed-keys, ensure same result ($n)"
235t1=$t2
236# Less than a second may have passed since the last time ns2 received a
237# ./DNSKEY response from ns1.  Ensure keys are refreshed at a different
238# timestamp to prevent false negatives caused by the acceptance timer getting
239# reset to the same timestamp.
240sleep 1
241mkeys_refresh_on 2 || ret=1
242mkeys_sync_on 2 || ret=1
243mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
244# two keys listed
245count=$(grep -c "keyid: " rndc.out.$n) || true
246[ "$count" -eq 2 ] || ret=1
247# two lines indicating trust status
248count=$(grep -c "trust" rndc.out.$n) || true
249[ "$count" -eq 2 ] || ret=1
250# trust is revoked
251count=$(grep -c "trust revoked" rndc.out.$n) || true
252[ "$count" -eq 1 ] || ret=1
253# removal scheduled
254count=$(grep -c "remove at" rndc.out.$n) || true
255[ "$count" -eq 1 ] || ret=1
256# trust is still pending on the standby key
257count=$(grep -c "trust pending" rndc.out.$n) || true
258[ "$count" -eq 1 ] || ret=1
259# pending date moved forward for the standby key
260t2=$(grep "trust pending" ns2/managed-keys.bind) || true
261[ -n "$t2" ] || ret=1
262[ "$t1" = "$t2" ] && ret=1
263if [ $ret != 0 ]; then echo_i "failed"; fi
264status=$((status+ret))
265
266n=$((n+1))
267ret=0
268echo_i "restore revoked key, ensure same result ($n)"
269t1=$t2
270$SETTIME -R none -D now -K ns1 "$original" > /dev/null
271mkeys_loadkeys_on 1 || ret=1
272$SETTIME -D none -K ns1 "$original" > /dev/null
273mkeys_loadkeys_on 1 || ret=1
274# Less than a second may have passed since the last time ns2 received a
275# ./DNSKEY response from ns1.  Ensure keys are refreshed at a different
276# timestamp to prevent false negatives caused by the acceptance timer getting
277# reset to the same timestamp.
278sleep 1
279mkeys_refresh_on 2 || ret=1
280mkeys_sync_on 2 || ret=1
281mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
282# two keys listed
283count=$(grep -c "keyid: " rndc.out.$n) || true
284[ "$count" -eq 2 ] || ret=1
285# two lines indicating trust status
286count=$(grep -c "trust" rndc.out.$n) || true
287[ "$count" -eq 2 ] || ret=1
288# trust is revoked
289count=$(grep -c "trust revoked" rndc.out.$n) || true
290[ "$count" -eq 1 ] || ret=1
291# removal scheduled
292count=$(grep -c "remove at" rndc.out.$n) || true
293[ "$count" -eq 1 ] || ret=1
294# trust is still pending on the standby key
295count=$(grep -c "trust pending" rndc.out.$n) || true
296[ "$count" -eq 1 ] || ret=1
297# pending date moved forward for the standby key
298t2=$(grep "trust pending" ns2/managed-keys.bind) || true
299[ -n "$t2" ] || ret=1
300[ "$t1" = "$t2" ] && ret=1
301if [ $ret != 0 ]; then echo_i "failed"; fi
302status=$((status+ret))
303
304echo_i "reinitialize trust anchors, add second key to bind.keys"
305stop_server --use-rndc --port "${CONTROLPORT}" ns2
306rm -f ns2/managed-keys.bind*
307keyfile_to_initial_ds ns1/"$original" ns1/"$standby1" > ns2/managed.conf
308nextpart ns2/named.run > /dev/null
309start_server --noclean --restart --port "${PORT}" ns2
310
311n=$((n+1))
312echo_i "check that no key from bind.keys is marked as an initializing key ($n)"
313ret=0
314wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1
315mkeys_secroots_on 2 || ret=1
316grep '; initializing' ns2/named.secroots > /dev/null 2>&1 && ret=1
317if [ $ret != 0 ]; then echo_i "failed"; fi
318status=$((status+ret))
319
320echo_i "reinitialize trust anchors, revert to one key in bind.keys"
321stop_server --use-rndc --port "${CONTROLPORT}" ns2
322rm -f ns2/managed-keys.bind*
323mv ns2/managed1.conf ns2/managed.conf
324nextpart ns2/named.run > /dev/null
325start_server --noclean --restart --port "${PORT}" ns2
326
327n=$((n+1))
328echo_i "check that standby key is now trusted ($n)"
329ret=0
330wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1
331mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
332# two keys listed
333count=$(grep -c "keyid: " rndc.out.$n) || true
334[ "$count" -eq 2 ] || ret=1
335# two lines indicating trust status
336count=$(grep -c "trust" rndc.out.$n) || true
337[ "$count" -eq 2 ] || ret=1
338# both indicate current trust
339count=$(grep -c "trusted since" rndc.out.$n) || true
340[ "$count" -eq 2 ] || ret=1
341if [ $ret != 0 ]; then echo_i "failed"; fi
342status=$((status+ret))
343
344n=$((n+1))
345echo_i "revoke original key, add new standby ($n)"
346ret=0
347standby2=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .)
348$SETTIME -R now -K ns1 "$original" > /dev/null
349mkeys_loadkeys_on 1 || ret=1
350mkeys_refresh_on 2 || ret=1
351mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
352# three keys listed
353count=$(grep -c "keyid: " rndc.out.$n) || true
354[ "$count" -eq 3 ] || ret=1
355# one is revoked
356count=$(grep -c "REVOKE" rndc.out.$n) || true
357[ "$count" -eq 1 ] || ret=1
358# three lines indicating trust status
359count=$(grep -c "trust" rndc.out.$n) || true
360[ "$count" -eq 3 ] || ret=1
361# one indicates current trust
362count=$(grep -c "trusted since" rndc.out.$n) || true
363[ "$count" -eq 1 ] || ret=1
364# one indicates revoked trust
365count=$(grep -c "trust revoked" rndc.out.$n) || true
366[ "$count" -eq 1 ] || ret=1
367# one indicates trust pending
368count=$(grep -c "trust pending" rndc.out.$n) || true
369[ "$count" -eq 1 ] || ret=1
370# removal scheduled
371count=$(grep -c "remove at" rndc.out.$n) || true
372[ "$count" -eq 1 ] || ret=1
373if [ $ret != 0 ]; then echo_i "failed"; fi
374status=$((status+ret))
375
376n=$((n+1))
377echo_i "revoke standby before it is trusted ($n)"
378ret=0
379standby3=$($KEYGEN -a ${DEFAULT_ALGORITHM} -qfk -K ns1 .)
380mkeys_loadkeys_on 1 || ret=1
381mkeys_refresh_on 2 || ret=1
382mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
383# four keys listed
384count=$(grep -c "keyid: " rndc.out.1.$n) || true
385[ "$count" -eq 4 ] || { echo_i "keyid: count ($count) != 4"; ret=1; }
386# one revoked
387count=$(grep -c "trust revoked" rndc.out.1.$n) || true
388[ "$count" -eq 1 ] || { echo_i "trust revoked count ($count) != 1"; ret=1; }
389# two pending
390count=$(grep -c "trust pending" rndc.out.1.$n) || true
391[ "$count" -eq 2 ] || { echo_i "trust pending count ($count) != 2"; ret=1; }
392$SETTIME -R now -K ns1 "$standby3" > /dev/null
393mkeys_loadkeys_on 1 || ret=1
394mkeys_refresh_on 2 || ret=1
395mkeys_status_on 2 > rndc.out.2.$n 2>&1 || ret=1
396# now three keys listed
397count=$(grep -c "keyid: " rndc.out.2.$n) || true
398[ "$count" -eq 3 ] || { echo_i "keyid: count ($count) != 3"; ret=1; }
399# one revoked
400count=$(grep -c "trust revoked" rndc.out.2.$n) || true
401[ "$count" -eq 1 ] || { echo_i "trust revoked count ($count) != 1"; ret=1; }
402# one pending
403count=$(grep -c "trust pending" rndc.out.2.$n) || true
404[ "$count" -eq 1 ] || { echo_i "trust pending count ($count) != 1"; ret=1; }
405$SETTIME -D now -K ns1 "$standby3" > /dev/null
406mkeys_loadkeys_on 1 || ret=1
407if [ $ret != 0 ]; then echo_i "failed"; fi
408status=$((status+ret))
409
410n=$((n+1))
411echo_i "wait 20 seconds for key add/remove holddowns to expire ($n)"
412ret=0
413sleep 20
414mkeys_refresh_on 2 || ret=1
415mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
416# two keys listed
417count=$(grep -c "keyid: " rndc.out.$n) || true
418[ "$count" -eq 2 ] || ret=1
419# none revoked
420count=$(grep -c "REVOKE" rndc.out.$n) || true
421[ "$count" -eq 0 ] || ret=1
422# two lines indicating trust status
423count=$(grep -c "trust" rndc.out.$n) || true
424[ "$count" -eq 2 ] || ret=1
425# both indicate current trust
426count=$(grep -c "trusted since" rndc.out.$n) || true
427[ "$count" -eq 2 ] || ret=1
428if [ $ret != 0 ]; then echo_i "failed"; fi
429status=$((status+ret))
430
431n=$((n+1))
432echo_i "revoke all keys, confirm roll to insecure ($n)"
433ret=0
434$SETTIME -D now -K ns1 "$original" > /dev/null
435$SETTIME -R now -K ns1 "$standby1" > /dev/null
436$SETTIME -R now -K ns1 "$standby2" > /dev/null
437mkeys_loadkeys_on 1 || ret=1
438mkeys_refresh_on 2 || ret=1
439mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
440# two keys listed
441count=$(grep -c "keyid: " rndc.out.$n) || true
442[ "$count" -eq 2 ] || ret=1
443# both revoked
444count=$(grep -c "REVOKE" rndc.out.$n) || true
445[ "$count" -eq 2 ] || ret=1
446# two lines indicating trust status
447count=$(grep -c "trust" rndc.out.$n) || true
448[ "$count" -eq 2 ] || ret=1
449# both indicate trust revoked
450count=$(grep -c "trust revoked" rndc.out.$n) || true
451[ "$count" -eq 2 ] || ret=1
452# both have removal scheduled
453count=$(grep -c "remove at" rndc.out.$n) || true
454[ "$count" -eq 2 ] || ret=1
455if [ $ret != 0 ]; then echo_i "failed"; fi
456status=$((status+ret))
457
458n=$((n+1))
459echo_i "check for insecure response ($n)"
460ret=0
461mkeys_refresh_on 2 || ret=1
462dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
463grep "status: NOERROR" dig.out.ns2.test$n > /dev/null || ret=1
464grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null && ret=1
465grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
466if [ $ret != 0 ]; then echo_i "failed"; fi
467status=$((status+ret))
468
469n=$((n+1))
470echo_i "reset the root server ($n)"
471ret=0
472$SETTIME -D none -R none -K ns1 "$original" > /dev/null
473$SETTIME -D now -K ns1 "$standby1" > /dev/null
474$SETTIME -D now -K ns1 "$standby2" > /dev/null
475$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db > /dev/null 2>/dev/null
476copy_setports ns1/named2.conf.in ns1/named.conf
477rm -f ns1/root.db.signed.jnl
478mkeys_reconfig_on 1 || ret=1
479mkeys_reload_on 1 || ret=1
480if [ $ret != 0 ]; then echo_i "failed"; fi
481status=$((status+ret))
482
483echo_i "reinitialize trust anchors"
484stop_server --use-rndc --port "${CONTROLPORT}" ns2
485rm -f ns2/managed-keys.bind*
486nextpart ns2/named.run > /dev/null
487start_server --noclean --restart --port "${PORT}" ns2
488
489n=$((n+1))
490echo_i "check positive validation ($n)"
491ret=0
492wait_for_log 20 "Returned from key fetch in keyfetch_done()" ns2/named.run || ret=1
493dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
494grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
495grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
496if [ $ret != 0 ]; then echo_i "failed"; fi
497status=$((status+ret))
498
499n=$((n+1))
500echo_i "revoke key with bad signature, check revocation is ignored ($n)"
501ret=0
502revoked=$($REVOKE -K ns1 "$original")
503rkeyid=$(keyfile_to_key_id "$revoked")
504rm -f ns1/root.db.signed.jnl
505# We need to activate at least one valid DNSKEY to prevent dnssec-signzone from
506# failing.  Alternatively, we could use -P to disable post-sign verification,
507# but we actually do want post-sign verification to happen to ensure the zone
508# is correct before we break it on purpose.
509$SETTIME -R none -D none -K ns1 "$standby1" > /dev/null
510$SIGNER -Sg -K ns1 -N unixtime -O full -o . -f signer.out.$n ns1/root.db > /dev/null 2>/dev/null
511cp -f ns1/root.db.signed ns1/root.db.tmp
512BADSIG="SVn2tLDzpNX2rxR4xRceiCsiTqcWNKh7NQ0EQfCrVzp9WEmLw60sQ5kP xGk4FS/xSKfh89hO2O/H20Bzp0lMdtr2tKy8IMdU/mBZxQf2PXhUWRkg V2buVBKugTiOPTJSnaqYCN3rSfV1o7NtC1VNHKKK/D5g6bpDehdn5Gaq kpBhN+MSCCh9OZP2IT20luS1ARXxLlvuSVXJ3JYuuhTsQXUbX/SQpNoB Lo6ahCE55szJnmAxZEbb2KOVnSlZRA6ZBHDhdtO0S4OkvcmTutvcVV+7 w53CbKdaXhirvHIh0mZXmYk2PbPLDY7PU9wSH40UiWPOB9f00wwn6hUe uEQ1Qg=="
513# Less than a second may have passed since ns1 was started.  If we call
514# dnssec-signzone immediately, ns1/root.db.signed will not be reloaded by the
515# subsequent "rndc reload ." call on platforms which do not set the
516# "nanoseconds" field of isc_time_t, due to zone load time being seemingly
517# equal to master file modification time.
518sleep 1
519sed -e "/ $rkeyid \./s, \. .*$, . $BADSIG," signer.out.$n > ns1/root.db.signed
520mkeys_reload_on 1 || ret=1
521mkeys_refresh_on 2 || ret=1
522mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
523# one key listed
524count=$(grep -c "keyid: " rndc.out.$n) || true
525[ "$count" -eq 1 ] || { echo_i "'keyid:' count ($count) != 1"; ret=1; }
526# it's the original key id
527count=$(grep -c "keyid: $originalid" rndc.out.$n) || true
528[ "$count" -eq 1 ] || { echo_i "'keyid: $originalid' count ($count) != 1"; ret=1; }
529# not revoked
530count=$(grep -c "REVOKE" rndc.out.$n) || true
531[ "$count" -eq 0 ] || { echo_i "'REVOKE' count ($count) != 0"; ret=1; }
532# trust is still current
533count=$(grep -c "trust" rndc.out.$n) || true
534[ "$count" -eq 1 ] || { echo_i "'trust' count != 1"; ret=1; }
535count=$(grep -c "trusted since" rndc.out.$n) || true
536[ "$count" -eq 1 ] || { echo_i "'trusted since' count != 1"; ret=1; }
537if [ $ret != 0 ]; then echo_i "failed"; fi
538status=$((status+ret))
539
540n=$((n+1))
541echo_i "check validation fails with bad DNSKEY rrset ($n)"
542ret=0
543mkeys_flush_on 2 || ret=1
544dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
545grep "status: SERVFAIL" dig.out.ns2.test$n > /dev/null || ret=1
546if [ $ret != 0 ]; then echo_i "failed"; fi
547status=$((status+ret))
548
549n=$((n+1))
550echo_i "restore DNSKEY rrset, check validation succeeds again ($n)"
551ret=0
552rm -f "${revoked}".key "${revoked}".private
553rm -f ns1/root.db.signed.jnl
554$SETTIME -D none -R none -K ns1 "$original" > /dev/null
555$SETTIME -D now -K ns1 "$standby1" > /dev/null
556# Less than a second may have passed since ns1 was started.  If we call
557# dnssec-signzone immediately, ns1/root.db.signed will not be reloaded by the
558# subsequent "rndc reload ." call on platforms which do not set the
559# "nanoseconds" field of isc_time_t, due to zone load time being seemingly
560# equal to master file modification time.
561sleep 1
562$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db > /dev/null 2>/dev/null
563mkeys_reload_on 1 || ret=1
564mkeys_flush_on 2 || ret=1
565dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
566grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
567grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
568if [ $ret != 0 ]; then echo_i "failed"; fi
569status=$((status+ret))
570
571if [ ! "$CYGWIN" ]; then
572	n=$((n+1))
573	echo_i "reset the root server with no keys, check for minimal update ($n)"
574	ret=0
575	# Refresh keys first to prevent previous checks from influencing this one.
576	# Note that we might still get occasional false negatives on some really slow
577	# machines, when $t1 equals $t2 due to the time elapsed between "rndc
578	# managed-keys status" calls being equal to the normal active refresh period
579	# (as calculated per rules listed in RFC 5011 section 2.3) minus an "hour" (as
580	# set using -T mkeytimers).
581	mkeys_refresh_on 2 || ret=1
582	mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
583	t1=$(grep 'next refresh:' rndc.out.1.$n) || true
584	stop_server --use-rndc --port "${CONTROLPORT}" ns1
585	rm -f ns1/root.db.signed.jnl
586	cp ns1/root.db ns1/root.db.signed
587	nextpart ns1/named.run > /dev/null
588	start_server --noclean --restart --port "${PORT}" ns1
589	wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
590	mkeys_refresh_on 2 || ret=1
591	mkeys_status_on 2 > rndc.out.2.$n 2>&1 || ret=1
592	# one key listed
593	count=$(grep -c "keyid: " rndc.out.2.$n) || true
594	[ "$count" -eq 1 ] || ret=1
595	# it's the original key id
596	count=$(grep -c "keyid: $originalid" rndc.out.2.$n) || true
597	[ "$count" -eq 1 ] || ret=1
598	# not revoked
599	count=$(grep -c "REVOKE" rndc.out.2.$n) || true
600	[ "$count" -eq 0 ] || ret=1
601	# trust is still current
602	count=$(grep -c "trust" rndc.out.2.$n) || true
603	[ "$count" -eq 1 ] || ret=1
604	count=$(grep -c "trusted since" rndc.out.2.$n) || true
605	[ "$count" -eq 1 ] || ret=1
606	t2=$(grep 'next refresh:' rndc.out.2.$n) || true
607	[ "$t1" = "$t2" ] && ret=1
608	if [ $ret != 0 ]; then echo_i "failed"; fi
609	status=$((status+ret))
610fi
611
612n=$((n+1))
613echo_i "reset the root server with no signatures, check for minimal update ($n)"
614ret=0
615# Refresh keys first to prevent previous checks from influencing this one
616mkeys_refresh_on 2 || ret=1
617mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
618t1=$(grep 'next refresh:' rndc.out.1.$n) || true
619stop_server --use-rndc --port "${CONTROLPORT}" ns1
620rm -f ns1/root.db.signed.jnl
621cat ns1/K*.key >> ns1/root.db.signed
622nextpart ns1/named.run > /dev/null
623start_server --noclean --restart --port "${PORT}" ns1
624wait_for_log 20 "all zones loaded" ns1/named.run || ret=1
625# Less than a second may have passed since the last time ns2 received a
626# ./DNSKEY response from ns1.  Ensure keys are refreshed at a different
627# timestamp to prevent minimal update from resetting it to the same timestamp.
628sleep 1
629mkeys_refresh_on 2 || ret=1
630mkeys_status_on 2 > rndc.out.2.$n 2>&1 || ret=1
631# one key listed
632count=$(grep -c "keyid: " rndc.out.2.$n) || true
633[ "$count" -eq 1 ] || ret=1
634# it's the original key id
635count=$(grep -c "keyid: $originalid" rndc.out.2.$n) || true
636[ "$count" -eq 1 ] || ret=1
637# not revoked
638count=$(grep -c "REVOKE" rndc.out.2.$n) || true
639[ "$count" -eq 0 ] || ret=1
640# trust is still current
641count=$(grep -c "trust" rndc.out.2.$n) || true
642[ "$count" -eq 1 ] || ret=1
643count=$(grep -c "trusted since" rndc.out.2.$n) || true
644[ "$count" -eq 1 ] || ret=1
645t2=$(grep 'next refresh:' rndc.out.2.$n) || true
646[ "$t1" = "$t2" ] && ret=1
647if [ $ret != 0 ]; then echo_i "failed"; fi
648status=$((status+ret))
649
650n=$((n+1))
651echo_i "restore root server, check validation succeeds again ($n)"
652ret=0
653rm -f ns1/root.db.signed.jnl
654$SIGNER -Sg -K ns1 -N unixtime -o . ns1/root.db > /dev/null 2>/dev/null
655mkeys_reload_on 1 || ret=1
656mkeys_refresh_on 2 || ret=1
657mkeys_status_on 2 > rndc.out.$n 2>&1 || ret=1
658dig_with_opts +noauth example. @10.53.0.2 txt > dig.out.ns2.test$n || ret=1
659grep "flags:.*ad.*QUERY" dig.out.ns2.test$n > /dev/null || ret=1
660grep "example..*.RRSIG..*TXT" dig.out.ns2.test$n > /dev/null || ret=1
661if [ $ret != 0 ]; then echo_i "failed"; fi
662status=$((status+ret))
663
664n=$((n+1))
665echo_i "check that trust-anchor-telemetry queries are logged ($n)"
666ret=0
667grep "sending trust-anchor-telemetry query '_ta-[0-9a-f]*/NULL" ns2/named.run > /dev/null || ret=1
668if [ $ret != 0 ]; then echo_i "failed"; fi
669status=$((status+ret))
670
671n=$((n+1))
672echo_i "check that trust-anchor-telemetry queries are received ($n)"
673ret=0
674grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run > /dev/null || ret=1
675if [ $ret != 0 ]; then echo_i "failed"; fi
676status=$((status+ret))
677
678n=$((n+1))
679echo_i "check 'rndc-managed-keys destroy' ($n)"
680ret=0
681rndccmd 10.53.0.2 managed-keys destroy | sed 's/^/ns2 /' | cat_i
682mkeys_status_on 2 > rndc.out.1.$n 2>&1 || ret=1
683grep "no views with managed keys" rndc.out.1.$n > /dev/null || ret=1
684mkeys_reconfig_on 2 || ret=1
685check_root_trust_anchor_is_present_in_status() {
686	mkeys_status_on 2 > rndc.out.2.$n 2>&1 || return 1
687	grep "name: \." rndc.out.2.$n > /dev/null || return 1
688	return 0
689}
690retry_quiet 5 check_root_trust_anchor_is_present_in_status || ret=1
691if [ $ret != 0 ]; then echo_i "failed"; fi
692status=$((status+ret))
693
694n=$((n+1))
695echo_i "check that trust-anchor-telemetry queries contain the correct key ($n)"
696ret=0
697# convert the hexadecimal key from the TAT query into decimal and
698# compare against the known key.
699tathex=$(grep "query '_ta-[0-9a-f][0-9a-f]*/NULL/IN' approved" ns1/named.run | awk '{print $6; exit 0}' | sed -e 's/(_ta-\([0-9a-f][0-9a-f]*\)):/\1/') || true
700tatkey=$($PERL -e 'printf("%d\n", hex(@ARGV[0]));' "$tathex")
701realkey=$(rndccmd 10.53.0.2 secroots - | sed -n "s#.*${DEFAULT_ALGORITHM}/\([0-9][0-9]*\) ; .*managed.*#\1#p")
702[ "$tatkey" -eq "$realkey" ] || ret=1
703if [ $ret != 0 ]; then echo_i "failed"; fi
704status=$((status+ret))
705
706n=$((n+1))
707echo_i "check initialization fails if managed-keys can't be created ($n)"
708ret=0
709mkeys_secroots_on 4 || ret=1
710grep '; initializing managed' ns4/named.secroots > /dev/null 2>&1 || ret=1
711grep '; managed' ns4/named.secroots > /dev/null 2>&1 && ret=1
712grep '; trusted' ns4/named.secroots > /dev/null 2>&1 && ret=1
713if [ $ret != 0 ]; then echo_i "failed"; fi
714status=$((status+ret))
715
716n=$((n+1))
717echo_i "check failure to contact root servers does not prevent key refreshes after restart ($n)"
718ret=0
719# By the time we get here, ns5 should have attempted refreshing its managed
720# keys.  These attempts should fail as ns1 is configured to REFUSE all queries
721# from ns5.  Note that named1.args does not contain "-T mkeytimers"; this is to
722# ensure key refresh retry will be scheduled to one actual hour after the first
723# key refresh failure instead of just a few seconds, in order to prevent races
724# between the next scheduled key refresh time and startup time of restarted ns5.
725stop_server --use-rndc --port "${CONTROLPORT}" ns5
726nextpart ns5/named.run > /dev/null
727start_server --noclean --restart --port "${PORT}" ns5
728wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.':" ns5/named.run || ret=1
729wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld':" ns5/named.run || ret=1
730wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo':" ns5/named.run || ret=1
731# ns5/named.run will contain logs from both the old instance and the new
732# instance.  In order for the test to pass, both must attempt a fetch.
733count=$(grep -c "Creating key fetch" ns5/named.run) || true
734[ "$count" -lt 2 ] && ret=1
735if [ $ret != 0 ]; then echo_i "failed"; fi
736status=$((status+ret))
737
738n=$((n+1))
739echo_i "check 'rndc managed-keys' and islands of trust root unreachable ($n)"
740ret=0
741mkeys_sync_on 5
742mkeys_status_on 5 > rndc.out.$n 2>&1 || ret=1
743# there should be three keys listed now
744count=$(grep -c "keyid: " rndc.out.$n) || true
745[ "$count" -eq 3 ] || ret=1
746# three lines indicating trust status
747count=$(grep -c "trust" rndc.out.$n) || true
748[ "$count" -eq 3 ] || ret=1
749# one indicates current trust
750count=$(grep -c "trusted since" rndc.out.$n) || true
751[ "$count" -eq 1 ] || ret=1
752if [ $ret != 0 ]; then echo_i "failed"; fi
753status=$((status+ret))
754
755n=$((n+1))
756echo_i "check key refreshes are resumed after root servers become available ($n)"
757ret=0
758stop_server --use-rndc --port "${CONTROLPORT}" ns5
759# Prevent previous check from affecting this one
760rm -f ns5/managed-keys.bind*
761# named2.args adds "-T mkeytimers=2/20/40" to named1.args as we need to wait for
762# an "hour" until keys are refreshed again after initial failure
763cp ns5/named2.args ns5/named.args
764nextpart ns5/named.run > /dev/null
765start_server --noclean --restart --port "${PORT}" ns5
766wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.': failure" ns5/named.run || ret=1
767wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld': failure" ns5/named.run || ret=1
768wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo': success" ns5/named.run || ret=1
769mkeys_secroots_on 5 || ret=1
770grep '; initializing managed' ns5/named.secroots > /dev/null 2>&1 || ret=1
771# ns1 should still REFUSE queries from ns5, so resolving should be impossible
772dig_with_opts +noauth example. @10.53.0.5 txt > dig.out.ns5.a.test$n || ret=1
773grep "flags:.*ad.*QUERY" dig.out.ns5.a.test$n > /dev/null && ret=1
774grep "example..*.RRSIG..*TXT" dig.out.ns5.a.test$n > /dev/null && ret=1
775grep "status: SERVFAIL" dig.out.ns5.a.test$n > /dev/null || ret=1
776# Allow queries from ns5 to ns1
777copy_setports ns1/named3.conf.in ns1/named.conf
778rm -f ns1/root.db.signed.jnl
779nextpart ns5/named.run > /dev/null
780mkeys_reconfig_on 1 || ret=1
781wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for '.': success" ns5/named.run || ret=1
782wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.tld': success" ns5/named.run || ret=1
783wait_for_log_peek 20 "Returned from key fetch in keyfetch_done() for 'sub.foo': success" ns5/named.run || ret=1
784mkeys_secroots_on 5 || ret=1
785grep '; managed' ns5/named.secroots > /dev/null || ret=1
786# ns1 should not longer REFUSE queries from ns5, so managed keys should be
787# correctly refreshed and resolving should succeed
788dig_with_opts +noauth example. @10.53.0.5 txt > dig.out.ns5.b.test$n || ret=1
789grep "flags:.*ad.*QUERY" dig.out.ns5.b.test$n > /dev/null || ret=1
790grep "example..*.RRSIG..*TXT" dig.out.ns5.b.test$n > /dev/null || ret=1
791grep "status: NOERROR" dig.out.ns5.b.test$n > /dev/null || ret=1
792if [ $ret != 0 ]; then echo_i "failed"; fi
793status=$((status+ret))
794
795n=$((n+1))
796echo_i "reinitialize trust anchors, add unsupported algorithm ($n)"
797ret=0
798stop_server --use-rndc --port "${CONTROLPORT}" ns6
799rm -f ns6/managed-keys.bind*
800nextpart ns6/named.run > /dev/null
801start_server --noclean --restart --port "${PORT}" ns6
802# log when an unsupported algorithm is encountered during startup
803wait_for_log 20 "ignoring initial-key for 'unsupported.': algorithm is unsupported" ns6/named.run || ret=1
804if [ $ret != 0 ]; then echo_i "failed"; fi
805status=$((status+ret))
806
807n=$((n+1))
808echo_i "ignoring unsupported algorithm in managed-keys ($n)"
809ret=0
810mkeys_status_on 6 > rndc.out.$n 2>&1 || ret=1
811# there should still be only two keys listed (for . and island.)
812count=$(grep -c "keyid: " rndc.out.$n) || true
813[ "$count" -eq 2 ] || ret=1
814# two lines indicating trust status
815count=$(grep -c "trust" rndc.out.$n) || true
816[ "$count" -eq 2 ] || ret=1
817
818n=$((n+1))
819echo_i "introduce unsupported algorithm rollover in authoritative zone ($n)"
820ret=0
821cp ns1/root.db ns1/root.db.orig
822ksk=$(cat ns1/managed.key)
823zsk=$(cat ns1/zone.key)
824cat "ns1/${ksk}.key" "ns1/${zsk}.key" ns1/unsupported.key >> ns1/root.db
825grep "\.[[:space:]]*IN[[:space:]]*DNSKEY[[:space:]]*257 3 255" ns1/root.db > /dev/null || ret=1
826$SIGNER -K ns1 -N unixtime -o . ns1/root.db "$ksk" "$zsk" > /dev/null 2>/dev/null || ret=1
827grep "DNSKEY.*257 3 255" ns1/root.db.signed > /dev/null || ret=1
828cp ns1/root.db.orig ns1/root.db
829if [ $ret != 0 ]; then echo_i "failed"; fi
830status=$((status+ret))
831
832n=$((n+1))
833echo_i "ignoring unsupported algorithm in rollover ($n)"
834ret=0
835mkeys_reload_on 1 || ret=1
836mkeys_refresh_on 6 || ret=1
837mkeys_status_on 6 > rndc.out.$n 2>&1 || ret=1
838# there should still be only two keys listed (for . and island.)
839count=$(grep -c "keyid: " rndc.out.$n) || true
840[ "$count" -eq 2 ] || ret=1
841# two lines indicating trust status
842count=$(grep -c "trust" rndc.out.$n) || true
843[ "$count" -eq 2 ] || ret=1
844# log when an unsupported algorithm is encountered during rollover
845wait_for_log 20 "Cannot compute tag for key in zone .: algorithm is unsupported" ns6/named.run || ret=1
846if [ $ret != 0 ]; then echo_i "failed"; fi
847status=$((status+ret))
848
849n=$((n+1))
850echo_i "check 'rndc managed-keys' and views ($n)"
851ret=0
852rndccmd 10.53.0.7 managed-keys refresh in view1 > rndc.out.ns7.view1.test$n || ret=1
853grep "refreshing managed keys for 'view1'" rndc.out.ns7.view1.test$n > /dev/null || ret=1
854lines=$(wc -l < rndc.out.ns7.view1.test$n)
855[ "$lines" -eq 1 ] || ret=1
856rndccmd 10.53.0.7 managed-keys refresh > rndc.out.ns7.view2.test$n || ret=1
857lines=$(wc -l < rndc.out.ns7.view2.test$n)
858grep "refreshing managed keys for 'view1'" rndc.out.ns7.view2.test$n > /dev/null || ret=1
859grep "refreshing managed keys for 'view2'" rndc.out.ns7.view2.test$n > /dev/null || ret=1
860[ "$lines" -eq 2 ] || ret=1
861if [ $ret != 0 ]; then echo_i "failed"; fi
862status=$((status+ret))
863
864n=$((n+1))
865echo_i "check 'rndc managed-keys' and islands of trust now that root is reachable ($n)"
866ret=0
867mkeys_sync_on 5
868mkeys_status_on 5 > rndc.out.$n 2>&1 || ret=1
869# there should be three keys listed now
870count=$(grep -c "keyid: " rndc.out.$n) || true
871[ "$count" -eq 3 ] || ret=1
872# theee lines indicating trust status
873count=$(grep -c "trust" rndc.out.$n) || true
874[ "$count" -eq 3 ] || ret=1
875# three indicates current trust
876count=$(grep -c "trusted since" rndc.out.$n) || true
877[ "$count" -eq 3 ] || ret=1
878if [ $ret != 0 ]; then echo_i "failed"; fi
879status=$((status+ret))
880
881echo_i "exit status: $status"
882[ $status -eq 0 ] || exit 1
883