xref: /netbsd-src/external/mpl/bind/dist/bin/tests/system/upforwd/tests.sh (revision 9689912e6b171cbda866ec33f15ae94a04e2c02d)
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
14# ns1 = stealth primary
15# ns2 = secondary with update forwarding disabled; not currently used
16# ns3 = secondary with update forwarding enabled
17
18set -e
19
20. ../conf.sh
21
22DIGOPTS="+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd -p ${PORT}"
23RNDCCMD="$RNDC -p ${CONTROLPORT} -c ../_common/rndc.conf"
24
25nextpart_thrice() {
26  nextpart ns1/named.run >/dev/null
27  nextpart ns2/named.run >/dev/null
28  nextpart ns3/named.run >/dev/null
29}
30
31wait_for_log_thrice() {
32  echo_i "waiting for servers to incorporate changes"
33  wait_for_log 10 "committing update transaction" ns1/named.run
34  wait_for_log 10 "zone transfer finished" ns2/named.run
35  wait_for_log 10 "zone transfer finished" ns3/named.run
36}
37
38status=0
39n=1
40capture_dnstap() {
41  retry_quiet 20 test -f ns3/dnstap.out && mv ns3/dnstap.out dnstap.out.$n
42  $RNDCCMD -s 10.53.0.3 dnstap -reopen
43}
44
45uq_equals_ur() {
46  zonename="$1"
47  "$DNSTAPREAD" dnstap.out.$n \
48    | awk '$9 ~ /^'$zonename'\// { print }' \
49    | awk '$3 == "UQ" { UQ+=1 } $3 == "UR" { UR += 1 } END { print UQ+0, UR+0 }' >dnstapread.out$n
50  read UQ UR <dnstapread.out$n
51  echo_i "UQ=$UQ UR=$UR"
52  test $UQ -eq $UR || return 1
53}
54
55echo_i "waiting for servers to be ready for testing ($n)"
56for i in 1 2 3 4 5 6 7 8 9 10; do
57  ret=0
58  $DIG +tcp -p ${PORT} example. @10.53.0.1 soa >dig.out.ns1.$n || ret=1
59  grep "status: NOERROR" dig.out.ns1.$n >/dev/null || ret=1
60  $DIG +tcp -p ${PORT} example. @10.53.0.2 soa >dig.out.ns2.$n || ret=1
61  grep "status: NOERROR" dig.out.ns2.$n >/dev/null || ret=1
62  $DIG +tcp -p ${PORT} example. @10.53.0.3 soa >dig.out.ns3.$n || ret=1
63  grep "status: NOERROR" dig.out.ns3.$n >/dev/null || ret=1
64  test $ret = 0 && break
65  sleep 1
66done
67if [ $ret != 0 ]; then
68  echo_i "failed"
69  status=$((status + ret))
70fi
71n=$((n + 1))
72
73echo_i "fetching primary copy of zone before update ($n)"
74ret=0
75$DIG $DIGOPTS example. @10.53.0.1 axfr >dig.out.ns1.example.before || ret=1
76if [ $ret != 0 ]; then
77  echo_i "failed"
78  status=$((status + ret))
79fi
80n=$((n + 1))
81
82echo_i "fetching secondary 1 copy of zone before update ($n)"
83$DIG $DIGOPTS example. @10.53.0.2 axfr >dig.out.ns2.example.before || ret=1
84if [ $ret != 0 ]; then
85  echo_i "failed"
86  status=$((status + ret))
87fi
88n=$((n + 1))
89
90echo_i "fetching secondary 2 copy of zone before update ($n)"
91ret=0
92$DIG $DIGOPTS example. @10.53.0.3 axfr >dig.out.ns3.example.before || ret=1
93if [ $ret != 0 ]; then
94  echo_i "failed"
95  status=$((status + ret))
96fi
97n=$((n + 1))
98
99echo_i "comparing pre-update copies to known good data ($n)"
100ret=0
101digcomp knowngood.before dig.out.ns1.example.before || ret=1
102digcomp knowngood.before dig.out.ns2.example.before || ret=1
103digcomp knowngood.before dig.out.ns3.example.before || ret=1
104if [ $ret != 0 ]; then
105  echo_i "failed"
106  status=$((status + ret))
107fi
108
109echo_i "checking update forwarding of a zone (signed) (Do53 -> DoT) ($n)"
110nextpart_thrice
111ret=0
112$NSUPDATE -y "${DEFAULT_HMAC}:update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K" -- - <<EOF || ret=1
113local 10.53.0.1
114server 10.53.0.3 ${PORT}
115update add updated.example. 600 A 10.10.10.1
116update add updated.example. 600 TXT Foo
117send
118EOF
119if [ $ret != 0 ]; then
120  echo_i "failed"
121  status=$((status + ret))
122fi
123n=$((n + 1))
124wait_for_log_thrice
125
126echo_i "fetching primary copy of zone after update ($n)"
127ret=0
128$DIG $DIGOPTS example. @10.53.0.1 axfr >dig.out.ns1.example.after1 || ret=1
129if [ $ret != 0 ]; then
130  echo_i "failed"
131  status=$((status + ret))
132fi
133n=$((n + 1))
134
135echo_i "fetching secondary 1 copy of zone after update ($n)"
136ret=0
137$DIG $DIGOPTS example. @10.53.0.2 axfr >dig.out.ns2.example.after1 || ret=1
138if [ $ret != 0 ]; then
139  echo_i "failed"
140  status=$((status + ret))
141fi
142
143echo_i "fetching secondary 2 copy of zone after update ($n)"
144ret=0
145$DIG $DIGOPTS example. @10.53.0.3 axfr >dig.out.ns3.example.after1 || ret=1
146if [ $ret != 0 ]; then
147  echo_i "failed"
148  status=$((status + ret))
149fi
150n=$((n + 1))
151
152echo_i "comparing post-update copies to known good data ($n)"
153ret=0
154digcomp knowngood.after1 dig.out.ns1.example.after1 || ret=1
155digcomp knowngood.after1 dig.out.ns2.example.after1 || ret=1
156digcomp knowngood.after1 dig.out.ns3.example.after1 || ret=1
157if [ $ret != 0 ]; then
158  echo_i "failed"
159  status=$((status + ret))
160fi
161
162echo_i "checking update forwarding of a zone (signed) (DoT -> DoT) ($n)"
163nextpart_thrice
164ret=0
165$NSUPDATE -y "${DEFAULT_HMAC}:update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K" -S -O -- - <<EOF || ret=1
166local 10.53.0.1
167server 10.53.0.3 ${TLSPORT}
168update add updated-dot.example. 600 A 10.10.10.1
169update add updated-dot.example. 600 TXT Foo
170send
171EOF
172if [ $ret != 0 ]; then
173  echo_i "failed"
174  status=$((status + ret))
175fi
176n=$((n + 1))
177wait_for_log_thrice
178
179echo_i "fetching primary copy of zone after update ($n)"
180ret=0
181$DIG $DIGOPTS example. @10.53.0.1 axfr >dig.out.ns1.example.after2 || ret=1
182if [ $ret != 0 ]; then
183  echo_i "failed"
184  status=$((status + ret))
185fi
186n=$((n + 1))
187
188echo_i "fetching secondary 1 copy of zone after update ($n)"
189ret=0
190$DIG $DIGOPTS example. @10.53.0.2 axfr >dig.out.ns2.example.after2 || ret=1
191if [ $ret != 0 ]; then
192  echo_i "failed"
193  status=$((status + ret))
194fi
195
196echo_i "fetching secondary 2 copy of zone after update ($n)"
197ret=0
198$DIG $DIGOPTS example. @10.53.0.3 axfr >dig.out.ns3.example.after2 || ret=1
199if [ $ret != 0 ]; then
200  echo_i "failed"
201  status=$((status + ret))
202fi
203n=$((n + 1))
204
205echo_i "comparing post-update copies to known good data ($n)"
206ret=0
207digcomp knowngood.after2 dig.out.ns1.example.after2 || ret=1
208digcomp knowngood.after2 dig.out.ns2.example.after2 || ret=1
209digcomp knowngood.after2 dig.out.ns3.example.after2 || ret=1
210if [ $ret != 0 ]; then
211  echo_i "failed"
212  status=$((status + ret))
213fi
214
215echo_i "checking 'forwarding update for zone' is logged twice ($n)"
216ret=0
217cnt=$(grep -F "forwarding update for zone 'example/IN'" ns3/named.run | wc -l || ret=1)
218test "${cnt}" -eq 2 || ret=1
219if [ $ret != 0 ]; then
220  echo_i "failed"
221  status=$((status + ret))
222fi
223n=$((n + 1))
224
225if $FEATURETEST --enable-dnstap; then
226  echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
227  ret=0
228  capture_dnstap
229  uq_equals_ur example || ret=1
230  if [ $ret != 0 ]; then echo_i "failed"; fi
231  status=$((status + ret))
232  n=$((n + 1))
233fi
234
235echo_i "updating zone (unsigned) ($n)"
236nextpart_thrice
237ret=0
238$NSUPDATE -- - <<EOF || ret=1
239local 10.53.0.1
240server 10.53.0.3 ${PORT}
241update add unsigned.example. 600 A 10.10.10.1
242update add unsigned.example. 600 TXT Foo
243send
244EOF
245if [ $ret != 0 ]; then
246  echo_i "failed"
247  status=$((status + ret))
248fi
249n=$((n + 1))
250wait_for_log_thrice
251
252echo_i "fetching primary copy of zone after update ($n)"
253ret=0
254$DIG $DIGOPTS example. @10.53.0.1 axfr >dig.out.ns1.example.after3 || ret=1
255if [ $ret != 0 ]; then
256  echo_i "failed"
257  status=$((status + ret))
258fi
259
260echo_i "fetching secondary 1 copy of zone after update ($n)"
261ret=0
262$DIG $DIGOPTS example. @10.53.0.2 axfr >dig.out.ns2.example.after3 || ret=1
263if [ $ret != 0 ]; then
264  echo_i "failed"
265  status=$((status + ret))
266fi
267n=$((n + 1))
268
269echo_i "fetching secondary 2 copy of zone after update ($n)"
270ret=0
271$DIG $DIGOPTS example. @10.53.0.3 axfr >dig.out.ns3.example.after3 || ret=1
272if [ $ret != 0 ]; then
273  echo_i "failed"
274  status=$((status + ret))
275fi
276
277echo_i "comparing post-update copies to known good data ($n)"
278ret=0
279digcomp knowngood.after3 dig.out.ns1.example.after3 || ret=1
280digcomp knowngood.after3 dig.out.ns2.example.after3 || ret=1
281digcomp knowngood.after3 dig.out.ns3.example.after3 || ret=1
282if [ $ret != 0 ]; then
283  echo_i "failed"
284  status=$((status + ret))
285fi
286
287echo_i "fetching primary copy of zone before update, first primary fails ($n)"
288ret=0
289$DIG $DIGOPTS example3. @10.53.0.1 axfr >dig.out.ns1.example3.before || ret=1
290if [ $ret != 0 ]; then
291  echo_i "failed"
292  status=$((status + ret))
293fi
294n=$((n + 1))
295
296echo_i "fetching secondary 1 copy of zone before update, first primary fails ($n)"
297$DIG $DIGOPTS example3. @10.53.0.2 axfr >dig.out.ns2.example3.before || ret=1
298if [ $ret != 0 ]; then
299  echo_i "failed"
300  status=$((status + ret))
301fi
302n=$((n + 1))
303
304echo_i "fetching secondary 2 copy of zone before update, first primary fails ($n)"
305ret=0
306$DIG $DIGOPTS example3. @10.53.0.3 axfr >dig.out.ns3.example3.before || ret=1
307if [ $ret != 0 ]; then
308  echo_i "failed"
309  status=$((status + ret))
310fi
311n=$((n + 1))
312
313echo_i "comparing pre-update copies to known good data, first primary fails ($n)"
314ret=0
315digcomp knowngood.before.example3 dig.out.ns1.example3.before || ret=1
316digcomp knowngood.before.example3 dig.out.ns2.example3.before || ret=1
317digcomp knowngood.before.example3 dig.out.ns3.example3.before || ret=1
318if [ $ret != 0 ]; then
319  echo_i "failed"
320  status=$((status + ret))
321fi
322
323echo_i "checking update forwarding of a zone (signed) (Do53 -> DoT) ($n)"
324nextpart_thrice
325ret=0
326$NSUPDATE -y "${DEFAULT_HMAC}:update.example:c3Ryb25nIGVub3VnaCBmb3IgYSBtYW4gYnV0IG1hZGUgZm9yIGEgd29tYW4K" -- - <<EOF || ret=1
327local 10.53.0.1
328server 10.53.0.3 ${PORT}
329update add updated.example3. 600 A 10.10.10.1
330update add updated.example3. 600 TXT Foo
331send
332EOF
333if [ $ret != 0 ]; then
334  echo_i "failed"
335  status=$((status + ret))
336fi
337n=$((n + 1))
338wait_for_log_thrice
339
340echo_i "fetching primary copy of zone after update, first primary fails ($n)"
341ret=0
342$DIG $DIGOPTS example3. @10.53.0.1 axfr >dig.out.ns1.example3.after1 || ret=1
343if [ $ret != 0 ]; then
344  echo_i "failed"
345  status=$((status + ret))
346fi
347n=$((n + 1))
348
349echo_i "fetching secondary 1 copy of zone after update, first primary fails ($n)"
350ret=0
351$DIG $DIGOPTS example3. @10.53.0.2 axfr >dig.out.ns2.example3.after1 || ret=1
352if [ $ret != 0 ]; then
353  echo_i "failed"
354  status=$((status + ret))
355fi
356
357echo_i "fetching secondary 2 copy of zone after update, first primary fails ($n)"
358ret=0
359$DIG $DIGOPTS example3. @10.53.0.3 axfr >dig.out.ns3.example3.after1 || ret=1
360if [ $ret != 0 ]; then
361  echo_i "failed"
362  status=$((status + ret))
363fi
364n=$((n + 1))
365
366echo_i "comparing post-update copies to known good data, first primary fails ($n)"
367ret=0
368digcomp knowngood.after1.example3 dig.out.ns1.example3.after1 || ret=1
369digcomp knowngood.after1.example3 dig.out.ns2.example3.after1 || ret=1
370digcomp knowngood.after1.example3 dig.out.ns3.example3.after1 || ret=1
371if [ $ret != 0 ]; then
372  echo_i "failed"
373  status=$((status + ret))
374fi
375
376if $FEATURETEST --enable-dnstap; then
377  echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
378  ret=0
379  capture_dnstap
380  uq_equals_ur example3 || ret=1
381  if [ $ret != 0 ]; then echo_i "failed"; fi
382  status=$((status + ret))
383  n=$((n + 1))
384fi
385n=$((n + 1))
386
387if test -f keyname; then
388  echo_i "checking update forwarding with sig0 (Do53 -> Do53) ($n)"
389  nextpart_thrice
390  ret=0
391  keyname=$(cat keyname)
392  $NSUPDATE -k $keyname.private -- - <<EOF >nsupdate.out.test$n 2>&1 || ret=1
393	local 10.53.0.1
394	server 10.53.0.3 ${PORT}
395	zone example2
396	update add unsigned.example2. 600 A 10.10.10.1
397	update add unsigned.example2. 600 TXT Foo
398	send
399EOF
400  if [ $ret != 0 ]; then
401    echo_i "failed"
402    status=$((status + ret))
403  fi
404  n=$((n + 1))
405  wait_for_log_thrice
406
407  $DIG -p ${PORT} unsigned.example2 A @10.53.0.1 >dig.out.ns1.test$n || ret=1
408  grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1
409  if [ $ret != 0 ]; then echo_i "failed"; fi
410  status=$((status + ret))
411  n=$((n + 1))
412
413  if $FEATURETEST --enable-dnstap; then
414    echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
415    ret=0
416    capture_dnstap
417    uq_equals_ur example2 || ret=1
418    if [ $ret != 0 ]; then echo_i "failed"; fi
419    status=$((status + ret))
420    n=$((n + 1))
421  fi
422
423  echo_i "checking update forwarding with sig0 (DoT -> Do53) ($n)"
424  nextpart_thrice
425  ret=0
426  keyname=$(cat keyname)
427  $NSUPDATE -k $keyname.private -S -O -- - <<EOF >nsupdate.out.test$n 2>&1 || ret=1
428        local 10.53.0.1
429	server 10.53.0.3 ${TLSPORT}
430	zone example2
431	update add unsigned-dot.example2. 600 A 10.10.10.1
432	update add unsigned-dot.example2. 600 TXT Foo
433	send
434EOF
435  if [ $ret != 0 ]; then
436    echo_i "failed"
437    status=$((status + ret))
438  fi
439  n=$((n + 1))
440  wait_for_log_thrice
441
442  $DIG -p ${PORT} unsigned-dot.example2 A @10.53.0.1 >dig.out.ns1.test$n || ret=1
443  grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1
444  if [ $ret != 0 ]; then echo_i "failed"; fi
445  status=$((status + ret))
446  n=$((n + 1))
447
448  if $FEATURETEST --enable-dnstap; then
449    echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
450    ret=0
451    capture_dnstap
452    uq_equals_ur example2 || ret=1
453    if [ $ret != 0 ]; then echo_i "failed"; fi
454    status=$((status + ret))
455    n=$((n + 1))
456  fi
457
458  echo_i "checking update forwarding with sig0 with too many keys ($n)"
459  nextpart_thrice
460  ret=0
461  good=0
462  bad=0
463  for i in 1 2 3; do
464    keyname=$(cat keyname$i)
465    $NSUPDATE -d -D -k $keyname.private -- - <<EOF >nsupdate.out.test$n.$i 2>&1 && good=$((good + 1)) || bad=$((bad + 1))
466	local 10.53.0.1
467	server 10.53.0.3 ${PORT}
468	zone example2-toomanykeys
469	update add toomanykeys$i.example2-toomanykeys. 600 A 10.10.10.1
470	send
471EOF
472  done
473  # There are three keys in the zone but named checks the signature using
474  # maximum two keys, so one of these updates should have been failed.
475  [ $good = 2 ] && [ $bad = 1 ] || ret=1
476  if [ $ret != 0 ]; then echo_i "failed"; fi
477  status=$((status + ret))
478  n=$((n + 1))
479fi
480
481echo_i "attempting an update that should be rejected by ACL ($n)"
482ret=0
483{
484  $NSUPDATE -- - <<EOF
485        local 10.53.0.2
486        server 10.53.0.3 ${PORT}
487        update add another.unsigned.example. 600 A 10.10.10.2
488        update add another.unsigned.example. 600 TXT Bar
489        send
490EOF
491} >nsupdate.out.$n 2>&1 && ret=1
492grep REFUSED nsupdate.out.$n >/dev/null || ret=1
493if [ $ret != 0 ]; then
494  echo_i "failed"
495  status=$((status + ret))
496fi
497n=$((n + 1))
498
499echo_i "checking update forwarding to dead primary ($n)"
500count=0
501ret=0
502while [ $count -lt 5 -a $ret -eq 0 ]; do
503  (
504    $NSUPDATE -- - <<EOF
505local 10.53.0.1
506server 10.53.0.3 ${PORT}
507zone noprimary
508update add unsigned.noprimary. 600 A 10.10.10.1
509update add unsigned.noprimary. 600 TXT Foo
510send
511EOF
512  ) >/dev/null 2>&1 &
513  $DIG -p ${PORT} +noadd +notcp +noauth noprimary. @10.53.0.3 soa >dig.out.ns3.test$n.$count || ret=1
514  grep "status: NOERROR" dig.out.ns3.test$n.$count >/dev/null || ret=1
515  count=$((count + 1))
516done
517if [ $ret != 0 ]; then
518  echo_i "failed"
519  status=$((status + ret))
520fi
521n=$((n + 1))
522
523echo_i "waiting for nsupdate to finish ($n)"
524wait
525n=$((n + 1))
526
527if $FEATURETEST --enable-dnstap; then
528  echo_i "checking DNSTAP logging of UPDATE forwarded update replies ($n)"
529  ret=0
530  capture_dnstap
531  uq_equals_ur noprimary && ret=1
532  if [ $ret != 0 ]; then echo_i "failed"; fi
533  status=$((status + ret))
534  n=$((n + 1))
535fi
536
537n=$((n + 1))
538ret=0
539echo_i "attempting updates that should exceed quota ($n)"
540# lower the update quota to 1.
541copy_setports ns3/named2.conf.in ns3/named.conf
542rndc_reconfig ns3 10.53.0.3
543nextpart ns3/named.run >/dev/null
544for loop in 1 2 3 4 5 6 7 8 9 10; do
545  {
546    $NSUPDATE -- - >/dev/null 2>&1 <<END
547  local 10.53.0.1
548  server 10.53.0.3 ${PORT}
549  update add txt-$loop.unsigned.example 300 IN TXT Whatever
550  send
551END
552  } &
553done
554wait_for_log 10 "too many DNS UPDATEs queued" ns3/named.run || ret=1
555[ $ret = 0 ] || {
556  echo_i "failed"
557  status=1
558}
559
560echo_i "exit status: $status"
561[ $status -eq 0 ] || exit 1
562