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
14SYSTEMTESTTOP=..
15. $SYSTEMTESTTOP/conf.sh
16
17DIGOPTS="-p ${PORT}"
18RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s"
19
20#
21# Uncomment when creating credential cache files.
22#
23# KRB5_CONFIG=`pwd`/krb/krb5.conf
24#
25# Cd krb and run krb/setup.sh to create new keys.
26# Run nsupdate system test.
27# Kill the krb5kdc server started by krb/setup.sh.
28# Check the expiry date on the cached machine.ccache with klist is in 2038.
29# Comment out KRB5_CONFIG.
30# Re-run nsupdate system test to confirm everything still works.
31# git add and commit the resulting ns*/machine.ccache and ns*/dns.keytab files.
32# Clean up krb.
33#
34
35status=0
36n=0
37
38nextpartreset ns3/named.run
39
40# wait for zone transfer to complete
41tries=0
42while true; do
43    if [ $tries -eq 10 ]
44    then
45        exit 1
46    fi
47
48    if grep "example.nil/IN.*Transfer status" ns2/named.run > /dev/null
49    then
50        break
51    else
52        echo_i "zones are not fully loaded, waiting..."
53        tries=`expr $tries + 1`
54        sleep 1
55    fi
56done
57
58has_positive_response() {
59	zone=$1
60	type=$2
61	ns=$3
62	$DIG $DIGOPTS +tcp +norec $zone $type @$ns > dig.out.post.test$n || return 1
63	grep "status: NOERROR" dig.out.post.test$n > /dev/null || return 1
64	grep "ANSWER: 0," dig.out.post.test$n > /dev/null && return 1
65	return 0
66}
67
68ret=0
69echo_i "fetching first copy of zone before update"
70$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
71	@10.53.0.1 axfr > dig.out.ns1 || ret=1
72[ $ret = 0 ] || { echo_i "failed"; status=1; }
73
74ret=0
75echo_i "fetching second copy of zone before update"
76$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
77	@10.53.0.2 axfr > dig.out.ns2 || ret=1
78[ $ret = 0 ] || { echo_i "failed"; status=1; }
79
80ret=0
81echo_i "comparing pre-update copies to known good data"
82digcomp knowngood.ns1.before dig.out.ns1 || ret=1
83digcomp knowngood.ns1.before dig.out.ns2 || ret=1
84[ $ret = 0 ] || { echo_i "failed"; status=1; }
85
86ret=0
87echo_i "updating zone"
88# nsupdate will print a ">" prompt to stdout as it gets each input line.
89$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
90server 10.53.0.1 ${PORT}
91update add updated.example.nil. 600 A 10.10.10.1
92add updated.example.nil. 600 TXT Foo
93delete t.example.nil.
94
95END
96[ $ret = 0 ] || { echo_i "failed"; status=1; }
97
98echo_i "sleeping 5 seconds for server to incorporate changes"
99sleep 5
100
101ret=0
102echo_i "fetching first copy of zone after update"
103$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
104	@10.53.0.1 axfr > dig.out.ns1 || ret=1
105[ $ret = 0 ] || { echo_i "failed"; status=1; }
106
107ret=0
108echo_i "fetching second copy of zone after update"
109$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
110	@10.53.0.2 axfr > dig.out.ns2 || ret=1
111[ $ret = 0 ] || { echo_i "failed"; status=1; }
112
113ret=0
114echo_i "comparing post-update copies to known good data"
115digcomp knowngood.ns1.after dig.out.ns1 || ret=1
116digcomp knowngood.ns1.after dig.out.ns2 || ret=1
117[ $ret = 0 ] || { echo_i "failed"; status=1; }
118
119ret=0
120echo_i "testing local update policy"
121pre=`$DIG $DIGOPTS +short new.other.nil. @10.53.0.1 a` || ret=1
122[ -z "$pre" ] || ret=1
123[ $ret = 0 ] || { echo_i "failed"; status=1; }
124
125ret=0
126echo_i "updating zone"
127# nsupdate will print a ">" prompt to stdout as it gets each input line.
128$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > /dev/null <<END || ret=1
129zone other.nil.
130update add new.other.nil. 600 IN A 10.10.10.1
131send
132END
133[ $ret = 0 ] || { echo_i "failed"; status=1; }
134
135echo_i "sleeping 5 seconds for server to incorporate changes"
136sleep 5
137
138ret=0
139echo_i "checking result of update"
140post=`$DIG $DIGOPTS +short new.other.nil. @10.53.0.1 a` || ret=1
141[ "$post" = "10.10.10.1" ] || ret=1
142[ $ret = 0 ] || { echo_i "failed"; status=1; }
143
144ret=0
145echo_i "comparing post-update copy to known good data"
146digcomp knowngood.ns1.after dig.out.ns1 || ret=1
147[ $ret = 0 ] || { echo_i "failed"; status=1; }
148
149ret=0
150echo_i "testing zone consistency checks"
151# inserting an NS record without a corresponding A or AAAA record should fail
152$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END && ret=1
153update add other.nil. 600 in ns ns3.other.nil.
154send
155END
156grep REFUSED nsupdate.out > /dev/null 2>&1 || ret=1
157# ...but should work if an A record is inserted first:
158$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
159update add ns4.other.nil 600 in a 10.53.0.1
160send
161update add other.nil. 600 in ns ns4.other.nil.
162send
163END
164grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
165# ...or if an AAAA record does:
166$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
167update add ns5.other.nil 600 in aaaa 2001:db8::1
168send
169update add other.nil. 600 in ns ns5.other.nil.
170send
171END
172grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
173# ...or if the NS and A/AAAA are inserted together:
174$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
175update add other.nil. 600 in ns ns6.other.nil.
176update add ns6.other.nil 600 in a 10.53.0.1
177send
178END
179grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
180[ $ret = 0 ] || { echo_i "failed"; status=1; }
181
182echo_i "sleeping 5 seconds for server to incorporate changes"
183sleep 5
184
185ret=0
186echo_i "checking result of update"
187$DIG $DIGOPTS +short @10.53.0.1 ns other.nil > dig.out.ns1 || ret=1
188grep ns3.other.nil dig.out.ns1 > /dev/null 2>&1 && ret=1
189grep ns4.other.nil dig.out.ns1 > /dev/null 2>&1 || ret=1
190grep ns5.other.nil dig.out.ns1 > /dev/null 2>&1 || ret=1
191grep ns6.other.nil dig.out.ns1 > /dev/null 2>&1 || ret=1
192[ $ret = 0 ] || { echo_i "failed"; status=1; }
193
194ret=0
195echo_i "ensure 'check-mx ignore' allows adding MX records containing an address without a warning"
196$NSUPDATE -k ns1/ddns.key > nsupdate.out 2>&1 << END || ret=1
197server 10.53.0.1 ${PORT}
198update add mx03.example.nil 600 IN MX 10 10.53.0.1
199send
200END
201grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
202grep "mx03.example.nil/MX:.*MX is an address" ns1/named.run > /dev/null 2>&1 && ret=1
203[ $ret = 0 ] || { echo_i "failed"; status=1; }
204
205ret=0
206echo_i "ensure 'check-mx warn' allows adding MX records containing an address with a warning"
207$NSUPDATE -4 -l -p ${PORT} -k ns1/session.key > nsupdate.out 2>&1 << END || ret=1
208update add mx03.other.nil 600 IN MX 10 10.53.0.1
209send
210END
211grep REFUSED nsupdate.out > /dev/null 2>&1 && ret=1
212grep "mx03.other.nil/MX:.*MX is an address" ns1/named.run > /dev/null 2>&1 || ret=1
213[ $ret = 0 ] || { echo_i "failed"; status=1; }
214
215ret=0
216echo_i "ensure 'check-mx fail' prevents adding MX records containing an address with a warning"
217$NSUPDATE > nsupdate.out 2>&1 << END && ret=1
218server 10.53.0.1 ${PORT}
219update add mx03.update.nil 600 IN MX 10 10.53.0.1
220send
221END
222grep REFUSED nsupdate.out > /dev/null 2>&1 || ret=1
223grep "mx03.update.nil/MX:.*MX is an address" ns1/named.run > /dev/null 2>&1 || ret=1
224[ $ret = 0 ] || { echo_i "failed"; status=1; }
225
226ret=0
227echo_i "check SIG(0) key is accepted"
228key=`$KEYGEN -q -a NSEC3RSASHA1 -b 1024 -T KEY -n ENTITY xxx`
229echo "" | $NSUPDATE -k ${key}.private > /dev/null 2>&1 || ret=1
230[ $ret = 0 ] || { echo_i "failed"; status=1; }
231
232n=`expr $n + 1`
233ret=0
234echo_i "check TYPE=0 update is rejected by nsupdate ($n)"
235$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
236    server 10.53.0.1 ${PORT}
237    ttl 300
238    update add example.nil. in type0 ""
239    send
240END
241grep "unknown class/type" nsupdate.out > /dev/null 2>&1 || ret=1
242[ $ret = 0 ] || { echo_i "failed"; status=1; }
243
244n=`expr $n + 1`
245ret=0
246echo_i "check TYPE=0 prerequisite is handled ($n)"
247$NSUPDATE -k ns1/ddns.key <<END > nsupdate.out 2>&1 || ret=1
248    server 10.53.0.1 ${PORT}
249    prereq nxrrset example.nil. type0
250    send
251END
252$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
253grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
254[ $ret = 0 ] || { echo_i "failed"; status=1; }
255
256n=`expr $n + 1`
257ret=0
258echo_i "check that TYPE=0 update is handled ($n)"
259echo "a0e4280000010000000100000000060001c00c000000fe000000000000" |
260$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp > /dev/null || ret=1
261$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
262grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
263[ $ret = 0 ] || { echo_i "failed"; status=1; }
264
265n=`expr $n + 1`
266ret=0
267echo_i "check that TYPE=0 additional data is handled ($n)"
268echo "a0e4280000010000000000010000060001c00c000000fe000000000000" |
269$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp > /dev/null || ret=1
270$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
271grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
272[ $ret = 0 ] || { echo_i "failed"; status=1; }
273
274n=`expr $n + 1`
275ret=0
276echo_i "check that update to undefined class is handled ($n)"
277echo "a0e4280000010001000000000000060101c00c000000fe000000000000" |
278$PERL ../packet.pl -a 10.53.0.1 -p ${PORT} -t tcp > /dev/null || ret=1
279$DIG $DIGOPTS +tcp version.bind txt ch @10.53.0.1 > dig.out.ns1.$n
280grep "status: NOERROR" dig.out.ns1.$n > /dev/null || ret=1
281[ $ret = 0 ] || { echo_i "failed"; status=1; }
282
283n=`expr $n + 1`
284ret=0
285echo_i "check that address family mismatch is handled ($n)"
286$NSUPDATE <<END > /dev/null 2>&1 && ret=1
287server ::1
288local 127.0.0.1
289update add 600 txt.example.nil in txt "test"
290send
291END
292[ $ret = 0 ] || { echo_i "failed"; status=1; }
293
294
295n=`expr $n + 1`
296ret=0
297echo_i "check that unixtime serial number is correctly generated ($n)"
298$DIG $DIGOPTS +short unixtime.nil. soa @10.53.0.1 > dig.out.old.test$n || ret=1
299oldserial=`awk '{print $3}' dig.out.old.test$n` || ret=1
300start=`$PERL -e 'print time()."\n";'`
301$NSUPDATE <<END > /dev/null 2>&1 || ret=1
302    server 10.53.0.1 ${PORT}
303    ttl 600
304    update add new.unixtime.nil in a 1.2.3.4
305    send
306END
307now=`$PERL -e 'print time()."\n";'`
308sleep 1
309$DIG $DIGOPTS +short unixtime.nil. soa @10.53.0.1 > dig.out.new.test$n || ret=1
310serial=`awk '{print $3}' dig.out.new.test$n` || ret=1
311[ "$oldserial" = "$serial" ] && { echo_i "oldserial == serial"; ret=1; }
312if [ "$serial" -lt "$start" ]; then
313    echo_i "out-of-range serial=$serial < start=$start"; ret=1;
314elif [ "$serial" -gt "$now" ]; then
315    echo_i "out-of-range serial=$serial > now=$now"; ret=1;
316fi
317[ $ret = 0 ] || { echo_i "failed"; status=1; }
318
319if $PERL -e 'use Net::DNS;' 2>/dev/null
320then
321    n=`expr $n + 1`
322    ret=0
323    echo_i "running update.pl test ($n)"
324    $PERL update_test.pl -s 10.53.0.1 -p ${PORT} update.nil. > perl.update_test.out || ret=1
325    [ $ret -eq 1 ] && { echo_i "failed"; status=1; }
326
327    if $PERL -e 'use Net::DNS; die "Net::DNS too old ($Net::DNS::VERSION < 1.01)" if ($Net::DNS::VERSION < 1.01)' > /dev/null
328    then
329	n=`expr $n + 1`
330	ret=0
331	echo_i "check for too many NSEC3 iterations log ($n)"
332	grep "updating zone 'update.nil/IN': too many NSEC3 iterations (151)" ns1/named.run > /dev/null || ret=1
333	[ $ret -eq 1 ] && { echo_i "failed"; status=1; }
334    fi
335else
336    echo_i "The second part of this test requires the Net::DNS library." >&2
337fi
338
339n=`expr $n + 1`
340ret=0
341echo_i "fetching first copy of test zone ($n)"
342$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
343	@10.53.0.1 axfr > dig.out.ns1 || ret=1
344[ $ret = 0 ] || { echo_i "failed"; status=1; }
345
346n=`expr $n + 1`
347ret=0
348echo_i "fetching second copy of test zone ($n)"
349$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
350	@10.53.0.2 axfr > dig.out.ns2 || ret=1
351[ $ret = 0 ] || { echo_i "failed"; status=1; }
352
353n=`expr $n + 1`
354ret=0
355echo_i "comparing zones ($n)"
356digcomp dig.out.ns1 dig.out.ns2 || ret=1
357[ $ret = 0 ] || { echo_i "failed"; status=1; }
358
359echo_i "SIGKILL and restart server ns1"
360cd ns1
361$KILL -KILL `cat named.pid`
362rm named.pid
363cd ..
364sleep 10
365if
366	$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} nsupdate ns1
367then
368	echo_i "restarted server ns1"
369else
370	echo_i "could not restart server ns1"
371	exit 1
372fi
373sleep 10
374
375n=`expr $n + 1`
376ret=0
377echo_i "fetching ns1 after hard restart ($n)"
378$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd example.nil.\
379	@10.53.0.1 axfr > dig.out.ns1.after || ret=1
380[ $ret = 0 ] || { echo_i "failed"; status=1; }
381
382n=`expr $n + 1`
383ret=0
384echo_i "comparing zones ($n)"
385digcomp dig.out.ns1 dig.out.ns1.after || ret=1
386[ $ret = 0 ] || { echo_i "failed"; status=1; }
387
388echo_i "begin RT #482 regression test"
389
390n=`expr $n + 1`
391ret=0
392echo_i "update primary ($n)"
393$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
394server 10.53.0.1 ${PORT}
395update add updated2.example.nil. 600 A 10.10.10.2
396update add updated2.example.nil. 600 TXT Bar
397update delete c.example.nil.
398send
399END
400[ $ret = 0 ] || { echo_i "failed"; status=1; }
401
402sleep 5
403
404if [ ! "$CYGWIN" ]; then
405    echo_i "SIGHUP secondary"
406    $KILL -HUP `cat ns2/named.pid`
407else
408    echo_i "reload secondary"
409    rndc_reload ns2 10.53.0.2
410fi
411
412sleep 5
413
414n=`expr $n + 1`
415ret=0
416echo_i "update primary again ($n)"
417$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
418server 10.53.0.1 ${PORT}
419update add updated3.example.nil. 600 A 10.10.10.3
420update add updated3.example.nil. 600 TXT Zap
421del d.example.nil.
422send
423END
424[ $ret = 0 ] || { echo_i "failed"; status=1; }
425
426sleep 5
427
428if [ ! "$CYGWIN" ]; then
429    echo_i "SIGHUP secondary again"
430    $KILL -HUP `cat ns2/named.pid`
431else
432    echo_i "reload secondary again"
433    rndc_reload ns2 10.53.0.2
434fi
435
436sleep 5
437
438n=`expr $n + 1`
439echo_i "check to 'out of sync' message ($n)"
440if grep "out of sync" ns2/named.run
441then
442	echo_i "failed (found 'out of sync')"
443	status=1
444fi
445
446echo_i "end RT #482 regression test"
447
448n=`expr $n + 1`
449ret=0
450echo_i "start NSEC3PARAM changes via UPDATE on a unsigned zone test ($n)"
451$NSUPDATE << EOF
452server 10.53.0.3 ${PORT}
453update add example 3600 nsec3param 1 0 0 -
454send
455EOF
456
457# the zone is not signed.  The nsec3param records should be removed.
458# this also proves that the server is still running.
459$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocmd +norec example.\
460	@10.53.0.3 nsec3param > dig.out.ns3.$n || ret=1
461grep "ANSWER: 0," dig.out.ns3.$n > /dev/null || ret=1
462grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
463[ $ret = 0 ] || { echo_i "failed"; status=1; }
464
465n=`expr $n + 1`
466ret=0
467echo_i "change the NSEC3PARAM ttl via update ($n)"
468$NSUPDATE << EOF
469server 10.53.0.3 ${PORT}
470update add nsec3param.test 3600 NSEC3PARAM 1 0 1 -
471send
472EOF
473
474$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocmd +norec nsec3param.test.\
475        @10.53.0.3 nsec3param > dig.out.ns3.$n || ret=1
476grep "ANSWER: 1," dig.out.ns3.$n > /dev/null || ret=1
477grep "3600.*NSEC3PARAM" dig.out.ns3.$n > /dev/null || ret=1
478grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
479[ $ret = 0 ] || { echo_i "failed"; status=1; }
480
481n=`expr $n + 1`
482ret=0
483echo_i "add a new NSEC3PARAM via update ($n)"
484$NSUPDATE << EOF
485server 10.53.0.3 ${PORT}
486update add nsec3param.test 3600 NSEC3PARAM 1 0 4 -
487send
488EOF
489
490_ret=1
491for i in 0 1 2 3 4 5 6 7 8 9; do
492	$DIG $DIGOPTS +tcp +norec +time=1 +tries=1 @10.53.0.3 nsec3param.test. NSEC3PARAM > dig.out.ns3.$n || _ret=1
493	if grep "ANSWER: 2," dig.out.ns3.$n > /dev/null; then
494		_ret=0
495		break
496	fi
497	sleep 1
498done
499
500if [ $_ret -ne 0 ]; then ret=1; fi
501grep "NSEC3PARAM 1 0 4 -" dig.out.ns3.$n > /dev/null || ret=1
502grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
503if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $ret + $status`; fi
504
505n=`expr $n + 1`
506ret=0
507echo_i "add, delete and change the ttl of the NSEC3PARAM rrset via update ($n)"
508$NSUPDATE << EOF
509server 10.53.0.3 ${PORT}
510update delete nsec3param.test NSEC3PARAM
511update add nsec3param.test 7200 NSEC3PARAM 1 0 5 -
512send
513EOF
514
515_ret=1
516for i in 0 1 2 3 4 5 6 7 8 9; do
517	$DIG $DIGOPTS +tcp +norec +time=1 +tries=1 @10.53.0.3 nsec3param.test. NSEC3PARAM > dig.out.ns3.$n || _ret=1
518	if grep "ANSWER: 1," dig.out.ns3.$n > /dev/null; then
519		_ret=0
520		break
521	fi
522	sleep 1
523done
524
525if [ $_ret -ne 0 ]; then ret=1; fi
526grep "7200.*NSEC3PARAM 1 0 5 -" dig.out.ns3.$n > /dev/null || ret=1
527grep "flags:[^;]* aa[ ;]" dig.out.ns3.$n > /dev/null || ret=1
528$JOURNALPRINT ns3/nsec3param.test.db.signed.jnl > jp.out.ns3.$n
529# intermediate TTL changes.
530grep "add nsec3param.test.	7200	IN	NSEC3PARAM 1 0 4 -" jp.out.ns3.$n > /dev/null || ret=1
531grep "add nsec3param.test.	7200	IN	NSEC3PARAM 1 0 1 -" jp.out.ns3.$n > /dev/null || ret=1
532# delayed adds and deletes.
533grep "add nsec3param.test.	0	IN	TYPE65534 .# 6 000180000500" jp.out.ns3.$n > /dev/null || ret=1
534grep "add nsec3param.test.	0	IN	TYPE65534 .# 6 000140000100" jp.out.ns3.$n > /dev/null || ret=1
535grep "add nsec3param.test.	0	IN	TYPE65534 .# 6 000140000400" jp.out.ns3.$n > /dev/null || ret=1
536if [ $ret != 0 ] ; then echo_i "failed"; status=`expr $ret + $status`; fi
537
538
539ret=0
540echo_i "testing that rndc stop updates the file"
541$NSUPDATE -k ns1/ddns.key <<END > /dev/null || ret=1
542server 10.53.0.1 ${PORT}
543update add updated4.example.nil. 600 A 10.10.10.3
544send
545END
546sleep 3
547$PERL $SYSTEMTESTTOP/stop.pl --use-rndc --port ${CONTROLPORT} nsupdate ns1
548sleep 3
549# Removing the journal file and restarting the server means
550# that the data served by the new server process are exactly
551# those dumped to the file by "rndc stop".
552rm -f ns1/*jnl
553$PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} nsupdate ns1
554for try in 0 1 2 3 4 5 6 7 8 9; do
555    iret=0
556    $DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
557	updated4.example.nil. @10.53.0.1 a > dig.out.ns1 || iret=1
558    digcomp knowngood.ns1.afterstop dig.out.ns1 || iret=1
559    [ "$iret" -eq 0 ] && break
560    sleep 1
561done
562[ "$iret" -ne 0 ] && ret=1
563[ "$ret" -eq 0 ] || { echo_i "failed"; status=1; }
564
565ret=0
566echo_i "check that 'nsupdate -l' with a missing keyfile reports the missing file"
567$NSUPDATE -4 -p ${PORT} -l -k ns1/nonexistent.key 2> nsupdate.out < /dev/null
568grep ns1/nonexistent.key nsupdate.out > /dev/null || ret=1
569if test $ret -ne 0
570then
571echo_i "failed"; status=1
572fi
573
574n=`expr $n + 1`
575ret=0
576echo_i "check that 'update-policy local' works from localhost address ($n)"
577$NSUPDATE -k ns5/session.key > nsupdate.out.$n 2>&1 << END || ret=1
578server 10.53.0.5 ${PORT}
579local 127.0.0.1
580update add fromlocal.local.nil. 600 A 1.2.3.4
581send
582END
583grep REFUSED nsupdate.out.$n > /dev/null 2>&1 && ret=1
584$DIG $DIGOPTS @10.53.0.5 \
585        +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
586        fromlocal.local.nil. > dig.out.ns5.$n || ret=1
587grep fromlocal dig.out.ns5.$n > /dev/null 2>&1 || ret=1
588if test $ret -ne 0
589then
590echo_i "failed"; status=1
591fi
592
593n=`expr $n + 1`
594ret=0
595echo_i "check that 'update-policy local' fails from non-localhost address ($n)"
596grep 'match on session key not from localhost' ns5/named.run > /dev/null && ret=1
597$NSUPDATE -k ns5/session.key > nsupdate.out.$n 2>&1 << END && ret=1
598server 10.53.0.5 ${PORT}
599local 10.53.0.1
600update add nonlocal.local.nil. 600 A 4.3.2.1
601send
602END
603grep REFUSED nsupdate.out.$n > /dev/null 2>&1 || ret=1
604grep 'match on session key not from localhost' ns5/named.run > /dev/null || ret=1
605$DIG $DIGOPTS @10.53.0.5 \
606        +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
607        nonlocal.local.nil. > dig.out.ns5.$n || ret=1
608grep nonlocal dig.out.ns5.$n > /dev/null 2>&1 && ret=1
609if test $ret -ne 0
610then
611echo_i "failed"; status=1
612fi
613
614n=`expr $n + 1`
615ret=0
616echo_i "check that 'update-policy tcp-self' refuses update of records via UDP ($n)"
617$NSUPDATE > nsupdate.out.$n 2>&1 << END
618server 10.53.0.6 ${PORT}
619local 127.0.0.1
620update add 1.0.0.127.in-addr.arpa. 600 PTR localhost.
621send
622END
623grep REFUSED nsupdate.out.$n > /dev/null 2>&1 || ret=1
624$DIG $DIGOPTS @10.53.0.6 \
625        +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
626        -x 127.0.0.1 > dig.out.ns6.$n
627grep localhost. dig.out.ns6.$n > /dev/null 2>&1 && ret=1
628if test $ret -ne 0
629then
630echo_i "failed"; status=1
631fi
632
633n=`expr $n + 1`
634ret=0
635echo_i "check that 'update-policy tcp-self' permits update of records for the client's own address via TCP ($n)"
636$NSUPDATE -v > nsupdate.out.$n 2>&1 << END || ret=1
637server 10.53.0.6 ${PORT}
638local 127.0.0.1
639update add 1.0.0.127.in-addr.arpa. 600 PTR localhost.
640send
641END
642grep REFUSED nsupdate.out.$n > /dev/null 2>&1 && ret=1
643$DIG $DIGOPTS @10.53.0.6 \
644        +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
645        -x 127.0.0.1 > dig.out.ns6.$n || ret=1
646grep localhost. dig.out.ns6.$n > /dev/null 2>&1 || ret=1
647if test $ret -ne 0
648then
649echo_i "failed"; status=1
650fi
651
652n=`expr $n + 1`
653ret=0
654echo_i "check that 'update-policy tcp-self' refuses update of records for a different address from the client's own address via TCP ($n)"
655$NSUPDATE -v > nsupdate.out.$n 2>&1 << END
656server 10.53.0.6 ${PORT}
657local 127.0.0.1
658update add 1.0.168.192.in-addr.arpa. 600 PTR localhost.
659send
660END
661grep REFUSED nsupdate.out.$n > /dev/null 2>&1 || ret=1
662$DIG $DIGOPTS @10.53.0.6 \
663        +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
664        -x 192.168.0.1 > dig.out.ns6.$n
665grep localhost. dig.out.ns6.$n > /dev/null 2>&1 && ret=1
666if test $ret -ne 0
667then
668echo_i "failed"; status=1
669fi
670
671n=`expr $n + 1`
672ret=0
673echo_i "check that 'update-policy subdomain' is properly enforced ($n)"
674# "restricted.example.nil" matches "grant ... subdomain restricted.example.nil"
675# and thus this UPDATE should succeed.
676$NSUPDATE -d <<END > nsupdate.out1-$n 2>&1 || ret=1
677server 10.53.0.1 ${PORT}
678key restricted.example.nil 1234abcd8765
679update add restricted.example.nil 0 IN TXT everywhere.
680send
681END
682$DIG $DIGOPTS +tcp @10.53.0.1 restricted.example.nil TXT > dig.out.1.test$n || ret=1
683grep "TXT.*everywhere" dig.out.1.test$n > /dev/null || ret=1
684# "example.nil" does not match "grant ... subdomain restricted.example.nil" and
685# thus this UPDATE should fail.
686$NSUPDATE -d <<END > nsupdate.out2-$n 2>&1 && ret=1
687server 10.53.0.1 ${PORT}
688key restricted.example.nil 1234abcd8765
689update add example.nil 0 IN TXT everywhere.
690send
691END
692$DIG $DIGOPTS +tcp @10.53.0.1 example.nil TXT > dig.out.2.test$n || ret=1
693grep "TXT.*everywhere" dig.out.2.test$n > /dev/null && ret=1
694[ $ret = 0 ] || { echo_i "failed"; status=1; }
695
696n=`expr $n + 1`
697ret=0
698echo_i "check that 'update-policy zonesub' is properly enforced ($n)"
699# grant zonesub-key.example.nil zonesub TXT;
700# the A record update should be rejected as it is not in the type list
701$NSUPDATE -d <<END > nsupdate.out1-$n 2>&1 && ret=1
702server 10.53.0.1 ${PORT}
703key zonesub-key.example.nil 1234subk8765
704update add zonesub.example.nil 0 IN A 1.2.3.4
705send
706END
707$DIG $DIGOPTS +tcp @10.53.0.1 zonesub.example.nil A > dig.out.1.test$n || ret=1
708grep "status: REFUSED" nsupdate.out1-$n > /dev/null || ret=1
709grep "ANSWER: 0," dig.out.1.test$n > /dev/null || ret=1
710# the TXT record update should be accepted as it is in the type list
711$NSUPDATE -d <<END > nsupdate.out2-$n 2>&1 || ret=1
712server 10.53.0.1 ${PORT}
713key zonesub-key.example.nil 1234subk8765
714update add zonesub.example.nil 0 IN TXT everywhere.
715send
716END
717$DIG $DIGOPTS +tcp @10.53.0.1 zonesub.example.nil TXT > dig.out.2.test$n || ret=1
718grep "status: REFUSED" nsupdate.out2-$n > /dev/null && ret=1
719grep "ANSWER: 1," dig.out.2.test$n > /dev/null || ret=1
720grep "TXT.*everywhere" dig.out.2.test$n > /dev/null || ret=1
721[ $ret = 0 ] || { echo_i "failed"; status=1; }
722
723n=`expr $n + 1`
724ret=0
725echo_i "check 'grant' in deny name + grant subdomain ($n)"
726$NSUPDATE << EOF > nsupdate.out-$n 2>&1 || ret=1
727key hmac-sha256:subkey 1234abcd8765
728server 10.53.0.9 ${PORT}
729zone denyname.example
730update add foo.denyname.example 3600 IN TXT added
731send
732EOF
733$DIG $DIGOPTS +tcp @10.53.0.9 foo.denyname.example TXT > dig.out.ns9.test$n
734grep "added" dig.out.ns9.test$n > /dev/null || ret=1
735[ $ret = 0 ] || { echo_i "failed"; status=1; }
736
737n=`expr $n + 1`
738ret=0
739echo_i "check 'deny' in deny name + grant subdomain ($n)"
740$NSUPDATE << EOF > nsupdate.out-$n 2>&1 && ret=1
741key hmac-sha256:subkey 1234abcd8765
742server 10.53.0.9 ${PORT}
743zone denyname.example
744update add denyname.example 3600 IN TXT added
745send
746EOF
747$DIG $DIGOPTS +tcp @10.53.0.9 denyname.example TXT > dig.out.ns9.test$n
748grep "added" dig.out.ns9.test$n > /dev/null && ret=1
749[ $ret = 0 ] || { echo_i "failed"; status=1; }
750
751n=`expr $n + 1`
752ret=0
753echo_i "check that changes to the DNSKEY RRset TTL do not have side effects ($n)"
754$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \
755        @10.53.0.3 dnskey | \
756	awk -v port="${PORT}" 'BEGIN { print "server 10.53.0.3", port; }
757	$2 == 10 && $3 == "IN" && $4 == "DNSKEY" { $2 = 600; print "update add", $0 }
758	END { print "send" }' > update.in.$n
759$NSUPDATE update.in.$n
760
761$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \
762	@10.53.0.3 any > dig.out.ns3.$n
763
764grep "600.*DNSKEY" dig.out.ns3.$n > /dev/null || ret=1
765grep TYPE65534 dig.out.ns3.$n > /dev/null && ret=1
766if test $ret -ne 0
767then
768echo_i "failed"; status=1
769fi
770
771n=`expr $n + 1`
772ret=0
773echo_i "check notify with TSIG worked ($n)"
774# if the alternate view received a notify--meaning, the notify was
775# validly signed by "altkey"--then the zonefile update.alt.bk will
776# will have been created.
777[ -f ns2/update.alt.bk ] || ret=1
778if [ $ret -ne 0 ]; then
779    echo_i "failed"
780    status=1
781fi
782
783n=`expr $n + 1`
784ret=0
785echo_i "check type list options ($n)"
786$NSUPDATE -T > typelist.out.T.${n} || { ret=1; echo_i "nsupdate -T failed"; }
787$NSUPDATE -P > typelist.out.P.${n} || { ret=1; echo_i "nsupdate -P failed"; }
788$NSUPDATE -TP > typelist.out.TP.${n} || { ret=1; echo_i "nsupdate -TP failed"; }
789grep ANY typelist.out.T.${n} > /dev/null && { ret=1; echo_i "failed: ANY found (-T)"; }
790grep ANY typelist.out.P.${n} > /dev/null && { ret=1; echo_i "failed: ANY found (-P)"; }
791grep ANY typelist.out.TP.${n} > /dev/null && { ret=1; echo_i "failed: ANY found (-TP)"; }
792grep KEYDATA typelist.out.T.${n} > /dev/null && { ret=1; echo_i "failed: KEYDATA found (-T)"; }
793grep KEYDATA typelist.out.P.${n} > /dev/null && { ret=1; echo_i "failed: KEYDATA found (-P)"; }
794grep KEYDATA typelist.out.TP.${n} > /dev/null && { ret=1; echo_i "failed: KEYDATA found (-TP)"; }
795grep AAAA typelist.out.T.${n} > /dev/null || { ret=1; echo_i "failed: AAAA not found (-T)"; }
796grep AAAA typelist.out.P.${n} > /dev/null && { ret=1; echo_i "failed: AAAA found (-P)"; }
797grep AAAA typelist.out.TP.${n} > /dev/null || { ret=1; echo_i "failed: AAAA not found (-TP)"; }
798if [ $ret -ne 0 ]; then
799    echo_i "failed"
800    status=1
801fi
802
803n=`expr $n + 1`
804ret=0
805echo_i "check command list ($n)"
806(
807while read cmd
808do
809    echo "$cmd" | $NSUPDATE  > /dev/null 2>&1
810    if test $? -gt 1 ; then
811	echo_i "failed ($cmd)"
812	ret=1
813    fi
814    echo "$cmd " | $NSUPDATE  > /dev/null 2>&1
815    if test $? -gt 1 ; then
816	echo_i "failed ($cmd)"
817	ret=1
818    fi
819done
820exit $ret
821) < commandlist || ret=1
822if [ $ret -ne 0 ]; then
823    status=1
824fi
825
826n=`expr $n + 1`
827ret=0
828echo_i "check TSIG key algorithms (nsupdate -k) ($n)"
829for alg in md5 sha1 sha224 sha256 sha384 sha512; do
830    $NSUPDATE -k ns1/${alg}.key <<END > /dev/null || ret=1
831server 10.53.0.1 ${PORT}
832update add ${alg}.keytests.nil. 600 A 10.10.10.3
833send
834END
835done
836sleep 2
837for alg in md5 sha1 sha224 sha256 sha384 sha512; do
838    $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.3 > /dev/null 2>&1 || ret=1
839done
840if [ $ret -ne 0 ]; then
841    echo_i "failed"
842    status=1
843fi
844
845n=`expr $n + 1`
846ret=0
847echo_i "check TSIG key algorithms (nsupdate -y) ($n)"
848for alg in md5 sha1 sha224 sha256 sha384 sha512; do
849    secret=$(sed -n 's/.*secret "\(.*\)";.*/\1/p' ns1/${alg}.key)
850    $NSUPDATE -y "hmac-${alg}:${alg}-key:$secret" <<END > /dev/null || ret=1
851server 10.53.0.1 ${PORT}
852update add ${alg}.keytests.nil. 600 A 10.10.10.50
853send
854END
855done
856sleep 2
857for alg in md5 sha1 sha224 sha256 sha384 sha512; do
858    $DIG $DIGOPTS +short @10.53.0.1 ${alg}.keytests.nil | grep 10.10.10.50 > /dev/null 2>&1 || ret=1
859done
860if [ $ret -ne 0 ]; then
861    echo_i "failed"
862    status=1
863fi
864
865n=`expr $n + 1`
866ret=0
867echo_i "check that ttl is capped by max-ttl ($n)"
868$NSUPDATE <<END > /dev/null || ret=1
869server 10.53.0.1 ${PORT}
870update add cap.max-ttl.nil. 600 A 10.10.10.3
871update add nocap.max-ttl.nil. 150 A 10.10.10.3
872send
873END
874sleep 2
875$DIG $DIGOPTS @10.53.0.1  cap.max-ttl.nil | grep "^cap.max-ttl.nil.	300" > /dev/null 2>&1 || ret=1
876$DIG $DIGOPTS @10.53.0.1  nocap.max-ttl.nil | grep "^nocap.max-ttl.nil.	150" > /dev/null 2>&1 || ret=1
877if [ $ret -ne 0 ]; then
878    echo_i "failed"
879    status=1
880fi
881
882n=`expr $n + 1`
883ret=0
884echo_i "add a record which is truncated when logged. ($n)"
885$NSUPDATE verylarge || ret=1
886$DIG $DIGOPTS +tcp @10.53.0.1 txt txt.update.nil > dig.out.ns1.test$n
887grep "ANSWER: 1," dig.out.ns1.test$n > /dev/null || ret=1
888grep "adding an RR at 'txt.update.nil' TXT .* \[TRUNCATED\]"  ns1/named.run > /dev/null || ret=1
889if [ $ret -ne 0 ]; then
890    echo_i "failed"
891    status=1
892fi
893
894n=`expr $n + 1`
895ret=0
896echo_i "check that yyyymmddvv serial number is correctly generated ($n)"
897oldserial=`$DIG $DIGOPTS +short yyyymmddvv.nil. soa @10.53.0.1 | awk '{print $3}'` || ret=1
898$NSUPDATE <<END > /dev/null 2>&1 || ret=1
899    server 10.53.0.1 ${PORT}
900    ttl 600
901    update add new.yyyymmddvv.nil in a 1.2.3.4
902    send
903END
904now=`$PERL -e '@lt=localtime(); printf "%.4d%0.2d%0.2d00\n",$lt[5]+1900,$lt[4]+1,$lt[3];'`
905sleep 1
906serial=`$DIG $DIGOPTS +short yyyymmddvv.nil. soa @10.53.0.1 | awk '{print $3}'` || ret=1
907[ "$oldserial" -ne "$serial" ] || ret=1
908[ "$serial" -eq "$now" ] || ret=1
909[ $ret = 0 ] || { echo_i "failed"; status=1; }
910
911#
912#  Refactor to use perl to launch the parallel updates.
913#
914if false
915then
916n=`expr $n + 1`
917echo_i "send many simultaneous updates via a update forwarder ($n)"
918ret=0
919for i in 0 1 2 3 4 5 6 7
920do
921(
922    for j in 0 1 2 3 4 5 6 7
923    do
924    (
925	$NSUPDATE << EOF
926server 10.53.0.3 ${PORT}
927zone many.test
928update add $i-$j.many.test 0 IN A 1.2.3.4
929send
930EOF
931    ) &
932    done
933    wait
934) &
935done
936wait
937dig axfr many.test @10.53.0.1 > dig.out.test$n
938lines=`awk '$4 == "A" { l++ } END { print l }' dig.out.test$n`
939test ${lines:-0} -eq 64 || ret=1
940[ $ret = 0 ] || { echo_i "failed"; status=1; }
941fi
942
943n=`expr $n + 1`
944echo_i "check max-journal-size limits ($n)"
945ret=0
946rm -f nsupdate.out1-$n
947# add one record
948$NSUPDATE << EOF >> nsupdate.out1-$n 2>&1
949server 10.53.0.1 ${PORT}
950zone maxjournal.test
951update add z.maxjournal.test 300 IN A 10.20.30.40
952send
953EOF
954for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
955    # repeatedly add and remove the same set of records to fill up
956    # the journal file without changing the zone content
957    $NSUPDATE << EOF >> nsupdate.out1-$n 2>&1
958server 10.53.0.1 ${PORT}
959zone maxjournal.test
960update add a.maxjournal.test 300 IN A 1.2.3.4
961update add b.maxjournal.test 300 IN A 1.2.3.4
962update add c.maxjournal.test 300 IN A 1.2.3.4
963update add d.maxjournal.test 300 IN A 1.2.3.4
964send
965update del a.maxjournal.test
966update del b.maxjournal.test
967update del c.maxjournal.test
968update del d.maxjournal.test
969send
970EOF
971done
972# check that the journal is big enough to require truncation.
973size=`$PERL -e 'use File::stat; my $sb = stat(@ARGV[0]); printf("%s\n", $sb->size);' ns1/maxjournal.db.jnl`
974[ "$size" -gt 6000 ] || ret=1
975sleep 1
976$RNDCCMD 10.53.0.1 sync maxjournal.test
977check_size_lt_5000() (
978    size=`$PERL -e 'use File::stat; my $sb = stat(@ARGV[0]); printf("%s\n", $sb->size);' ns1/maxjournal.db.jnl`
979    [ "$size" -lt 5000 ]
980)
981retry_quiet 20 check_size_lt_5000 || ret=1
982[ $ret = 0 ] || { echo_i "failed"; status=1; }
983
984n=`expr $n + 1`
985echo_i "check check-names processing ($n)"
986ret=0
987$NSUPDATE << EOF > nsupdate.out1-$n 2>&1
988update add # 0 in a 1.2.3.4
989EOF
990grep "bad owner" nsupdate.out1-$n > /dev/null || ret=1
991
992$NSUPDATE << EOF > nsupdate.out2-$n 2>&1
993check-names off
994update add # 0 in a 1.2.3.4
995EOF
996grep "bad owner" nsupdate.out2-$n > /dev/null && ret=1
997
998$NSUPDATE << EOF > nsupdate.out3-$n 2>&1
999update add . 0 in mx 0 #
1000EOF
1001grep "bad name" nsupdate.out3-$n > /dev/null || ret=1
1002
1003$NSUPDATE << EOF > nsupdate.out4-$n 2>&1
1004check-names off
1005update add . 0 in mx 0 #
1006EOF
1007grep "bad name" nsupdate.out4-$n > /dev/null && ret=1
1008
1009[ $ret = 0 ] || { echo_i "failed"; status=1; }
1010
1011n=`expr $n + 1`
1012echo_i "check adding of delegating NS records processing ($n)"
1013ret=0
1014$NSUPDATE -v << EOF > nsupdate.out-$n 2>&1 || ret=1
1015server 10.53.0.3 ${PORT}
1016zone delegation.test.
1017update add child.delegation.test. 3600 NS foo.example.net.
1018update add child.delegation.test. 3600 NS bar.example.net.
1019send
1020EOF
1021$DIG $DIGOPTS +tcp @10.53.0.3 ns child.delegation.test > dig.out.ns1.test$n
1022grep "status: NOERROR" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
1023grep "AUTHORITY: 2" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
1024[ $ret = 0 ] || { echo_i "failed"; status=1; }
1025
1026n=`expr $n + 1`
1027echo_i "check deleting of delegating NS records processing ($n)"
1028ret=0
1029$NSUPDATE -v << EOF > nsupdate.out-$n 2>&1 || ret=1
1030server 10.53.0.3 ${PORT}
1031zone delegation.test.
1032update del child.delegation.test. 3600 NS foo.example.net.
1033update del child.delegation.test. 3600 NS bar.example.net.
1034send
1035EOF
1036$DIG $DIGOPTS +tcp @10.53.0.3 ns child.delegation.test > dig.out.ns1.test$n
1037grep "status: NXDOMAIN" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1
1038[ $ret = 0 ] || { echo_i "failed"; status=1; }
1039
1040n=`expr $n + 1`
1041echo_i "check that adding too many records is blocked ($n)"
1042ret=0
1043$NSUPDATE -v << EOF > nsupdate.out-$n 2>&1 && ret=1
1044server 10.53.0.3 ${PORT}
1045zone too-big.test.
1046update add r1.too-big.test 3600 IN TXT r1.too-big.test
1047send
1048EOF
1049grep "update failed: SERVFAIL" nsupdate.out-$n > /dev/null || ret=1
1050$DIG $DIGOPTS +tcp @10.53.0.3 r1.too-big.test TXT > dig.out.ns3.test$n
1051grep "status: NXDOMAIN" dig.out.ns3.test$n > /dev/null || ret=1
1052grep "records in zone (4) exceeds max-records (3)" ns3/named.run > /dev/null || ret=1
1053[ $ret = 0 ] || { echo_i "failed"; status=1; }
1054
1055n=`expr $n + 1`
1056ret=0
1057echo_i "check whether valid addresses are used for primary failover ($n)"
1058$NSUPDATE -t 1 <<END > nsupdate.out-$n 2>&1 && ret=1
1059server 10.53.0.4 ${PORT}
1060zone unreachable.
1061update add unreachable. 600 A 192.0.2.1
1062send
1063END
1064grep "; Communication with 10.53.0.4#${PORT} failed: timed out" nsupdate.out-$n > /dev/null 2>&1 || ret=1
1065grep "not implemented" nsupdate.out-$n > /dev/null 2>&1 && ret=1
1066[ $ret = 0 ] || { echo_i "failed"; status=1; }
1067
1068n=`expr $n + 1`
1069ret=0
1070echo_i "ensure bad owner name is fatal in non-interactive mode ($n)"
1071$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
1072    update add emptylabel..nil. 600 A 10.10.10.1
1073END
1074grep "invalid owner name: empty label" nsupdate.out > /dev/null || ret=1
1075grep "syntax error" nsupdate.out > /dev/null || ret=1
1076[ $ret = 0 ] || { echo_i "failed"; status=1; }
1077
1078n=`expr $n + 1`
1079ret=0
1080echo_i "ensure bad owner name is not fatal in interactive mode ($n)"
1081$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
1082    update add emptylabel..nil. 600 A 10.10.10.1
1083END
1084grep "invalid owner name: empty label" nsupdate.out > /dev/null || ret=1
1085[ $ret = 0 ] || { echo_i "failed"; status=1; }
1086
1087n=`expr $n + 1`
1088ret=0
1089echo_i "ensure invalid key type is fatal in non-interactive mode ($n)"
1090$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
1091    key badkeytype:example abcd12345678
1092END
1093grep "unknown key type 'badkeytype'" nsupdate.out > /dev/null || ret=1
1094grep "syntax error" nsupdate.out > /dev/null || ret=1
1095[ $ret = 0 ] || { echo_i "failed"; status=1; }
1096
1097n=`expr $n + 1`
1098ret=0
1099echo_i "ensure invalid key type is not fatal in interactive mode ($n)"
1100$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
1101    key badkeytype:example abcd12345678
1102END
1103grep "unknown key type 'badkeytype'" nsupdate.out > /dev/null || ret=1
1104[ $ret = 0 ] || { echo_i "failed"; status=1; }
1105
1106n=`expr $n + 1`
1107ret=0
1108echo_i "ensure unresolvable server name is fatal in non-interactive mode ($n)"
1109$NSUPDATE <<END > nsupdate.out 2>&1 && ret=1
1110    server unresolvable..
1111END
1112grep "couldn't get address for 'unresolvable..':" nsupdate.out > /dev/null || ret=1
1113grep "syntax error" nsupdate.out > /dev/null || ret=1
1114[ $ret = 0 ] || { echo_i "failed"; status=1; }
1115
1116n=`expr $n + 1`
1117ret=0
1118echo_i "ensure unresolvable server name is not fatal in interactive mode ($n)"
1119$NSUPDATE -i <<END > nsupdate.out 2>&1 || ret=1
1120    server unresolvable..
1121END
1122grep "couldn't get address for 'unresolvable..':" nsupdate.out > /dev/null || ret=1
1123grep "syntax error" nsupdate.out > /dev/null && ret=1
1124[ $ret = 0 ] || { echo_i "failed"; status=1; }
1125
1126n=`expr $n + 1`
1127ret=0
1128echo_i "check nsupdate -4 -6 ($n)"
1129$NSUPDATE -4 -6 <<END > nsupdate.out-$n 2>&1 && ret=1
1130server 10.53.0.3 ${PORT}
1131zone delegation.test.
1132update del child.delegation.test. 3600 NS foo.example.net.
1133update del child.delegation.test. 3600 NS bar.example.net.
1134send
1135END
1136grep "only one of -4 and -6 allowed" nsupdate.out-$n > /dev/null 2>&1 || ret=1
1137[ $ret = 0 ] || { echo_i "failed"; status=1; }
1138
1139n=`expr $n + 1`
1140ret=0
1141echo_i "check nsupdate -4 with an IPv6 server address ($n)"
1142$NSUPDATE -4 <<END > nsupdate.out-$n 2>&1 && ret=1
1143server fd92:7065:b8e:ffff::2 ${PORT}
1144zone delegation.test.
1145update del child.delegation.test. 3600 NS foo.example.net.
1146update del child.delegation.test. 3600 NS bar.example.net.
1147send
1148END
1149grep "address family not supported" nsupdate.out-$n > /dev/null 2>&1 || ret=1
1150[ $ret = 0 ] || { echo_i "failed"; status=1; }
1151
1152n=`expr $n + 1`
1153ret=0
1154echo_i "check that TKEY in a update is rejected ($n)"
1155$NSUPDATE -d <<END > nsupdate.out-$n 2>&1 && ret=1
1156server 10.53.0.3 ${PORT}
1157update add tkey.example 0 in tkey invalid.algorithm. 1516055980 1516140801 1 0 16 gRof8D2BFKvl/vrr9Lmnjw== 16 gRof8D2BFKvl/vrr9Lmnjw==
1158send
1159END
1160grep "UPDATE, status: NOERROR" nsupdate.out-$n > /dev/null 2>&1 || ret=1
1161grep "UPDATE, status: FORMERR" nsupdate.out-$n > /dev/null 2>&1 || ret=1
1162[ $ret = 0 ] || { echo_i "failed"; status=1; }
1163
1164
1165
1166n=`expr $n + 1`
1167ret=0
1168echo_i "check that DS to the zone apex is ignored ($n)"
1169$DIG $DIGOPTS +tcp +norec example DS @10.53.0.3 > dig.out.pre.test$n || ret=1
1170grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
1171grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
1172nextpart ns3/named.run > /dev/null
1173# specify zone to override the default of adding to parent zone
1174$NSUPDATE -d <<END > nsupdate.out-$n 2>&1 || ret=1
1175server 10.53.0.3 ${PORT}
1176zone example
1177update add example 0 in DS 14364 10 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
1178send
1179END
1180msg=": attempt to add a DS record at zone apex ignored"
1181nextpart ns3/named.run | grep "$msg" > /dev/null || ret=1
1182$DIG $DIGOPTS +tcp +norec example DS @10.53.0.3 > dig.out.post.test$n || ret=1
1183grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
1184grep "ANSWER: 0," dig.out.post.test$n > /dev/null || ret=1
1185[ $ret = 0 ] || { echo_i "failed"; status=1; }
1186
1187n=`expr $n + 1`
1188ret=0
1189echo_i "check that CDS with mismatched algorithm to DNSSEC multisigner zone is not allowed ($n)"
1190$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 > dig.out.pre.test$n || ret=1
1191grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
1192grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
1193$NSUPDATE -d <<END > nsupdate.out-$n 2>&1 && ret=1
1194server 10.53.0.3 ${PORT}
1195zone multisigner.test
1196update add multisigner.test 3600 IN CDS 14364 14 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
1197send
1198END
1199msg=": bad CDS RRset"
1200nextpart ns3/named.run | grep "$msg" > /dev/null || ret=1
1201$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 > dig.out.post.test$n || ret=1
1202grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
1203grep "ANSWER: 0," dig.out.post.test$n > /dev/null || ret=1
1204[ $ret = 0 ] || { echo_i "failed"; status=1; }
1205
1206n=`expr $n + 1`
1207ret=0
1208echo_i "check that CDNSKEY with mismatched algorithm to DNSSEC multisigner zone is not allowed ($n)"
1209$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 > dig.out.pre.test$n || ret=1
1210grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
1211grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
1212nextpart ns3/named.run > /dev/null
1213$NSUPDATE -d <<END > nsupdate.out-$n 2>&1 && ret=1
1214server 10.53.0.3 ${PORT}
1215zone multisigner.test
1216update add multisigner.test 3600 IN CDNSKEY 257 3 14 d0NQ5PKmDz6P0B1WPMH9/UKRux/toSFwV2nTJYPA1Cx8pB0sJGTXbVhG U+6gye7VCHDhGIn9CjVfb2RJPW7GnQ==
1217send
1218END
1219msg=": bad CDNSKEY RRset"
1220nextpart ns3/named.run | grep "$msg" > /dev/null || ret=1
1221$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 > dig.out.post.test$n || ret=1
1222grep "status: NOERROR" dig.out.post.test$n > /dev/null || ret=1
1223grep "ANSWER: 0," dig.out.post.test$n > /dev/null || ret=1
1224[ $ret = 0 ] || { echo_i "failed"; status=1; }
1225
1226n=`expr $n + 1`
1227ret=0
1228echo_i "check that CDS to DNSSEC multisigner zone is allowed ($n)"
1229$DIG $DIGOPTS +tcp +norec multisigner.test CDS @10.53.0.3 > dig.out.pre.test$n || ret=1
1230grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
1231grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
1232$NSUPDATE -d <<END > nsupdate.out-$n 2>&1 || ret=1
1233server 10.53.0.3 ${PORT}
1234zone multisigner.test
1235update add multisigner.test 3600 IN CDS 14364 13 2 FD03B2312C8F0FE72C1751EFA1007D743C94EC91594FF0047C23C37CE119BA0C
1236send
1237END
1238retry_quiet 5 has_positive_response multisigner.test CDS 10.53.0.3 || ret=1
1239[ $ret = 0 ] || { echo_i "failed"; status=1; }
1240
1241n=`expr $n + 1`
1242ret=0
1243echo_i "check that CDNSKEY to DNSSEC multisigner zone is allowed ($n)"
1244$DIG $DIGOPTS +tcp +norec multisigner.test CDNSKEY @10.53.0.3 > dig.out.pre.test$n || ret=1
1245grep "status: NOERROR" dig.out.pre.test$n > /dev/null || ret=1
1246grep "ANSWER: 0," dig.out.pre.test$n > /dev/null || ret=1
1247$NSUPDATE -d <<END > nsupdate.out-$n 2>&1 || ret=1
1248server 10.53.0.3 ${PORT}
1249zone multisigner.test
1250update add multisigner.test 3600 IN CDNSKEY 257 3 13 d0NQ5PKmDz6P0B1WPMH9/UKRux/toSFwV2nTJYPA1Cx8pB0sJGTXbVhG U+6gye7VCHDhGIn9CjVfb2RJPW7GnQ==
1251send
1252END
1253retry_quiet 5 has_positive_response multisigner.test CDNSKEY 10.53.0.3 || ret=1
1254[ $ret = 0 ] || { echo_i "failed"; status=1; }
1255
1256n=`expr $n + 1`
1257ret=0
1258echo_i "check that excessive NSEC3PARAM iterations are rejected by nsupdate ($n)"
1259$NSUPDATE -d <<END > nsupdate.out-$n 2>&1 && ret=1
1260server 10.53.0.3 ${PORT}
1261zone example
1262update add example 0 in NSEC3PARAM 1 0 151 -
1263END
1264grep "NSEC3PARAM has excessive iterations (> 150)" nsupdate.out-$n >/dev/null || ret=1
1265[ $ret = 0 ] || { echo_i "failed"; status=1; }
1266
1267if ! $FEATURETEST --gssapi ; then
1268  echo_i "SKIPPED: GSSAPI tests"
1269else
1270  n=`expr $n + 1`
1271  ret=0
1272  echo_i "check krb5-self match ($n)"
1273  KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
1274  export KRB5CCNAME
1275  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 || ret=1
1276  gsstsig
1277  realm EXAMPLE.COM
1278  server 10.53.0.7 ${PORT}
1279  zone example.com
1280  update add machine.example.com 3600 IN A 10.53.0.7
1281  send
1282EOF
1283  $DIG $DIGOPTS +tcp @10.53.0.7 machine.example.com A > dig.out.ns7.test$n
1284  grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
1285  grep "machine.example.com..*A.*10.53.0.7" dig.out.ns7.test$n > /dev/null || ret=1
1286  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1287
1288  n=`expr $n + 1`
1289  ret=0
1290  echo_i "check krb5-self no-match ($n)"
1291  KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
1292  export KRB5CCNAME
1293  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 && ret=1
1294  gsstsig
1295  realm EXAMPLE.COM
1296  server 10.53.0.7 ${PORT}
1297  zone example.com
1298  update add foo.example.com 3600 IN A 10.53.0.7
1299  send
1300EOF
1301  grep "update failed: REFUSED" nsupdate.out-$n > /dev/null || ret=1
1302  $DIG $DIGOPTS +tcp @10.53.0.7 foo.example.com A > dig.out.ns7.test$n
1303  grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
1304  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1305
1306  n=`expr $n + 1`
1307  ret=0
1308  echo_i "check krb5-subdomain match ($n)"
1309  KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
1310  export KRB5CCNAME
1311  $NSUPDATE -d << EOF > nsupdate.out-$n 2>&1 || ret=1
1312  gsstsig
1313  realm EXAMPLE.COM
1314  server 10.53.0.7 ${PORT}
1315  zone example.com
1316  update add _xxx._tcp.example.com 3600 IN SRV 0 0 0 machine.example.com
1317  send
1318EOF
1319  $DIG $DIGOPTS +tcp @10.53.0.7 _xxx._tcp.example.com SRV > dig.out.ns7.test$n
1320  grep "status: NOERROR" dig.out.ns7.test$n > /dev/null || ret=1
1321  grep "_xxx._tcp.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns7.test$n > /dev/null || ret=1
1322  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1323
1324  n=`expr $n + 1`
1325  ret=0
1326  echo_i "check krb5-subdomain no-match ($n)"
1327  KRB5CCNAME="FILE:"`pwd`/ns7/machine.ccache
1328  export KRB5CCNAME
1329  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 && ret=1
1330  gsstsig
1331  realm EXAMPLE.COM
1332  server 10.53.0.7 ${PORT}
1333  zone example.com
1334  update add _xxx._udp.example.com 3600 IN SRV 0 0 0 machine.example.com
1335  send
1336EOF
1337  grep "update failed: REFUSED" nsupdate.out-$n > /dev/null || ret=1
1338  $DIG $DIGOPTS +tcp @10.53.0.7 _xxx._udp.example.com SRV > dig.out.ns7.test$n
1339  grep "status: NXDOMAIN" dig.out.ns7.test$n > /dev/null || ret=1
1340  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1341
1342  n=`expr $n + 1`
1343  ret=0
1344  echo_i "check krb5-selfsub match ($n)"
1345  KRB5CCNAME="FILE:"`pwd`/ns8/machine.ccache
1346  export KRB5CCNAME
1347  $NSUPDATE -d << EOF > nsupdate.out-$n 2>&1 || ret=1
1348  gsstsig
1349  realm EXAMPLE.COM
1350  server 10.53.0.8 ${PORT}
1351  zone example.com
1352  update add xxx.machine.example.com 3600 IN A 10.53.0.8
1353  send
1354EOF
1355  $DIG $DIGOPTS +tcp @10.53.0.8 xxx.machine.example.com A > dig.out.ns8.test$n
1356  grep "status: NOERROR" dig.out.ns8.test$n > /dev/null || ret=1
1357  grep "xxx.machine.example.com..*A.*10.53.0.8" dig.out.ns8.test$n > /dev/null || ret=1
1358  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1359
1360  n=`expr $n + 1`
1361  ret=0
1362  echo_i "check krb5-selfsub no-match ($n)"
1363  KRB5CCNAME="FILE:"`pwd`/ns8/machine.ccache
1364  export KRB5CCNAME
1365  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 && ret=1
1366  gsstsig
1367  realm EXAMPLE.COM
1368  server 10.53.0.8 ${PORT}
1369  zone example.com
1370  update add foo.example.com 3600 IN A 10.53.0.8
1371  send
1372EOF
1373  grep "update failed: REFUSED" nsupdate.out-$n > /dev/null || ret=1
1374  $DIG $DIGOPTS +tcp @10.53.0.8 foo.example.com A > dig.out.ns8.test$n
1375  grep "status: NXDOMAIN" dig.out.ns8.test$n > /dev/null || ret=1
1376  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1377
1378  n=`expr $n + 1`
1379  ret=0
1380
1381  echo_i "check ms-self match ($n)"
1382  KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
1383  export KRB5CCNAME
1384  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 || ret=1
1385  gsstsig
1386  realm EXAMPLE.COM
1387  server 10.53.0.9 ${PORT}
1388  zone example.com
1389  update add machine.example.com 3600 IN A 10.53.0.9
1390  send
1391EOF
1392  $DIG $DIGOPTS +tcp @10.53.0.9 machine.example.com A > dig.out.ns9.test$n
1393  grep "status: NOERROR" dig.out.ns9.test$n > /dev/null || ret=1
1394  grep "machine.example.com..*A.*10.53.0.9" dig.out.ns9.test$n > /dev/null || ret=1
1395  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1396
1397  n=`expr $n + 1`
1398  ret=0
1399  echo_i "check ms-self no-match ($n)"
1400  KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
1401  export KRB5CCNAME
1402  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 && ret=1
1403  gsstsig
1404  realm EXAMPLE.COM
1405  server 10.53.0.9 ${PORT}
1406  zone example.com
1407  update add foo.example.com 3600 IN A 10.53.0.9
1408  send
1409EOF
1410  grep "update failed: REFUSED" nsupdate.out-$n > /dev/null || ret=1
1411  $DIG $DIGOPTS +tcp @10.53.0.9 foo.example.com A > dig.out.ns9.test$n
1412  grep "status: NXDOMAIN" dig.out.ns9.test$n > /dev/null || ret=1
1413  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1414
1415  n=`expr $n + 1`
1416  ret=0
1417  echo_i "check ms-subdomain match ($n)"
1418  KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
1419  export KRB5CCNAME
1420  $NSUPDATE -d << EOF > nsupdate.out-$n 2>&1 || ret=1
1421  gsstsig
1422  realm EXAMPLE.COM
1423  server 10.53.0.9 ${PORT}
1424  zone example.com
1425  update add _xxx._tcp.example.com 3600 IN SRV 0 0 0 machine.example.com
1426  send
1427EOF
1428  $DIG $DIGOPTS +tcp @10.53.0.9 _xxx._tcp.example.com SRV > dig.out.ns9.test$n
1429  grep "status: NOERROR" dig.out.ns9.test$n > /dev/null || ret=1
1430  grep "_xxx._tcp.example.com.*SRV.*0 0 0 machine.example.com" dig.out.ns9.test$n > /dev/null || ret=1
1431  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1432
1433  n=`expr $n + 1`
1434  ret=0
1435  echo_i "check ms-subdomain no-match ($n)"
1436  KRB5CCNAME="FILE:"`pwd`/ns9/machine.ccache
1437  export KRB5CCNAME
1438  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 && ret=1
1439  gsstsig
1440  realm EXAMPLE.COM
1441  server 10.53.0.9 ${PORT}
1442  zone example.com
1443  update add _xxx._udp.example.com 3600 IN SRV 0 0 0 machine.example.com
1444  send
1445EOF
1446  grep "update failed: REFUSED" nsupdate.out-$n > /dev/null || ret=1
1447  $DIG $DIGOPTS +tcp @10.53.0.9 _xxx._udp.example.com SRV > dig.out.ns9.test$n
1448  grep "status: NXDOMAIN" dig.out.ns9.test$n > /dev/null || ret=1
1449  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1450
1451  n=`expr $n + 1`
1452  ret=0
1453  echo_i "check ms-selfsub match ($n)"
1454  KRB5CCNAME="FILE:"`pwd`/ns10/machine.ccache
1455  export KRB5CCNAME
1456  $NSUPDATE -d << EOF > nsupdate.out-$n 2>&1 || ret=1
1457  gsstsig
1458  realm EXAMPLE.COM
1459  server 10.53.0.10 ${PORT}
1460  zone example.com
1461  update add xxx.machine.example.com 3600 IN A 10.53.0.10
1462  send
1463EOF
1464  $DIG $DIGOPTS +tcp @10.53.0.10 xxx.machine.example.com A > dig.out.ns10.test$n
1465  grep "status: NOERROR" dig.out.ns10.test$n > /dev/null || ret=1
1466  grep "xxx.machine.example.com..*A.*10.53.0.10" dig.out.ns10.test$n > /dev/null || ret=1
1467  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1468
1469  n=`expr $n + 1`
1470  ret=0
1471  echo_i "check ms-selfsub no-match ($n)"
1472  KRB5CCNAME="FILE:"`pwd`/ns10/machine.ccache
1473  export KRB5CCNAME
1474  $NSUPDATE << EOF > nsupdate.out-$n 2>&1 && ret=1
1475  gsstsig
1476  realm EXAMPLE.COM
1477  server 10.53.0.10 ${PORT}
1478  zone example.com
1479  update add foo.example.com 3600 IN A 10.53.0.10
1480  send
1481EOF
1482  grep "update failed: REFUSED" nsupdate.out-$n > /dev/null || ret=1
1483  $DIG $DIGOPTS +tcp @10.53.0.10 foo.example.com A > dig.out.ns10.test$n
1484  grep "status: NXDOMAIN" dig.out.ns10.test$n > /dev/null || ret=1
1485  [ $ret = 0 ] || { echo_i "failed"; status=1; }
1486
1487fi
1488
1489echo_i "exit status: $status"
1490[ $status -eq 0 ] || exit 1
1491