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
16. ../conf.sh
17
18# Test given condition.  If true, test again after a second.  Used for testing
19# filesystem-dependent conditions in order to prevent false negatives caused by
20# directory contents not being synchronized immediately after rename() returns.
21test_with_retry() {
22  if test "$@"; then
23    sleep 1
24    if test "$@"; then
25      return 0
26    fi
27  fi
28  return 1
29}
30
31status=0
32n=0
33
34# First run with a known good config.
35n=$((n + 1))
36echo_i "testing log file validity (only plain files allowed) ($n)"
37ret=0
38cat /dev/null >ns1/named_log
39copy_setports ns1/named.plainconf.in ns1/named.conf
40nextpart ns1/named.run >/dev/null
41rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
42wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
43if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
44status=$((status + ret))
45
46# Now try directory, expect failure
47n=$((n + 1))
48echo_i "testing directory as log file ($n)"
49ret=0
50nextpart ns1/named.run >/dev/null
51copy_setports ns1/named.dirconf.in ns1/named.conf
52rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
53wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
54if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
55status=$((status + ret))
56
57# Now try pipe file, expect failure
58n=$((n + 1))
59echo_i "testing pipe file as log file ($n)"
60ret=0
61nextpart ns1/named.run >/dev/null
62rm -f ns1/named_pipe
63if mkfifo ns1/named_pipe >/dev/null 2>&1; then
64  copy_setports ns1/named.pipeconf.in ns1/named.conf
65  rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
66  wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
67  if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
68  status=$((status + ret))
69else
70  echo_i "skipping pipe test (unable to create pipe)"
71fi
72
73# Now try symlink file to plain file, expect success
74n=$((n + 1))
75echo_i "testing symlink to plain file as log file ($n)"
76ret=0
77rm -f ns1/named_log ns1/named_sym
78touch ns1/named_log
79if ln -s $(pwd)/ns1/named_log $(pwd)/ns1/named_sym >/dev/null 2>&1; then
80  nextpart ns1/named.run >/dev/null
81  copy_setports ns1/named.symconf.in ns1/named.conf
82  rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
83  wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
84  if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
85  status=$((status + ret))
86else
87  echo_i "skipping symlink test (unable to create symlink)"
88fi
89
90echo_i "repeat previous tests without named -g"
91copy_setports ns1/named.plain.in ns1/named.conf
92stop_server --use-rndc --port ${CONTROLPORT} ns1
93cp named1.args ns1/named.args
94start_server --noclean --restart --port ${PORT} ns1
95
96n=$((n + 1))
97echo_i "testing log file validity (only plain files allowed) ($n)"
98ret=0
99cat /dev/null >ns1/named_log
100copy_setports ns1/named.plainconf.in ns1/named.conf
101nextpart ns1/named.run >/dev/null
102rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
103wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
104if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
105status=$((status + ret))
106
107# Now try directory, expect failure
108n=$((n + 1))
109echo_i "testing directory as log file ($n)"
110ret=0
111nextpart ns1/named.run >/dev/null
112copy_setports ns1/named.dirconf.in ns1/named.conf
113rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
114wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
115if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
116status=$((status + ret))
117
118# Now try pipe file, expect failure
119n=$((n + 1))
120echo_i "testing pipe file as log file ($n)"
121ret=0
122nextpart ns1/named.run >/dev/null
123rm -f ns1/named_pipe
124if mkfifo ns1/named_pipe >/dev/null 2>&1; then
125  copy_setports ns1/named.pipeconf.in ns1/named.conf
126  rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
127  wait_for_log 5 "reloading configuration failed: invalid file" ns1/named.run || ret=1
128  if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
129  status=$((status + ret))
130else
131  echo_i "skipping pipe test (unable to create pipe)"
132fi
133
134# Now try symlink file to plain file, expect success
135n=$((n + 1))
136echo_i "testing symlink to plain file as log file ($n)"
137ret=0
138rm -f ns1/named_log ns1/named_sym
139touch ns1/named_log
140if ln -s $(pwd)/ns1/named_log $(pwd)/ns1/named_sym >/dev/null 2>&1; then
141  nextpart ns1/named.run >/dev/null
142  copy_setports ns1/named.symconf.in ns1/named.conf
143  rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
144  wait_for_log 5 "reloading configuration succeeded" ns1/named.run || ret=1
145  if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
146  status=$((status + ret))
147else
148  echo_i "skipping symlink test (unable to create symlink)"
149fi
150
151echo_i "testing logging functionality"
152n=$((n + 1))
153ret=0
154echo_i "testing iso8601 timestamp ($n)"
155copy_setports ns1/named.iso8601.in ns1/named.conf
156rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
157grep '^....-..-..T..:..:..\.... ' ns1/named_iso8601 >/dev/null || ret=1
158if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
159status=$((status + ret))
160
161n=$((n + 1))
162echo_i "testing iso8601-utc timestamp ($n)"
163ret=0
164copy_setports ns1/named.iso8601-utc.in ns1/named.conf
165rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
166grep '^....-..-..T..:..:..\....Z' ns1/named_iso8601_utc >/dev/null || ret=1
167if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
168status=$((status + ret))
169
170n=$((n + 1))
171echo_i "testing explicit versions ($n)"
172ret=0
173copy_setports ns1/named.versconf.in ns1/named.conf
174# a seconds since epoch version number
175touch ns1/named_vers.1480039317
176rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
177$DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n
178grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
179# we are configured to retain five logfiles (a current file
180# and 4 backups). so files with version number 5 or higher
181# should be removed.
182test_with_retry -f ns1/named_vers.1480039317 && ret=1
183test_with_retry -f ns1/named_vers.5 && ret=1
184test_with_retry -f ns1/named_vers.4 || ret=1
185if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
186status=$((status + ret))
187
188n=$((n + 1))
189echo_i "testing timestamped versions ($n)"
190ret=0
191copy_setports ns1/named.tsconf.in ns1/named.conf
192# a seconds since epoch version number
193touch ns1/named_ts.1480039317
194# a timestamp version number
195touch ns1/named_ts.20150101120000120
196rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
197_found2() (
198  $DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n
199  grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
200
201  # we are configured to keep three versions, so the oldest
202  # timestamped versions should be gone, and there should
203  # be two or three backup ones.
204  [ -f ns1/named_ts.1480039317 ] && return 1
205  [ -f ns1/named_ts.20150101120000120 ] && return 1
206  set -- ns1/named_ts.*
207  [ "$#" -eq 2 -o "$#" -eq 3 ] || return 1
208)
209retry_quiet 5 _found2 || ret=1
210if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
211status=$((status + ret))
212
213n=$((n + 1))
214echo_i "testing incremented versions ($n)"
215ret=0
216copy_setports ns1/named.incconf.in ns1/named.conf
217try=0
218while test $try -lt 12; do
219  touch ns1/named_inc.$try
220  try=$((try + 1))
221done
222rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
223_found2() (
224  $DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n
225  grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
226
227  try=1
228  while test $try -lt 12; do
229    [ -f ns1/named_inc.$try ] && return 1
230    try=$((try + 1))
231  done
232  set -- ns1/named_inc.*
233  [ "$#" -eq 1 ] || return 1
234)
235retry_quiet 5 _found2 || ret=1
236if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
237status=$((status + ret))
238
239n=$((n + 1))
240echo_i "testing absolute file path versions ($n)"
241ret=0
242copy_setports ns1/named.abspathconf.in ns1/named.conf
243try=0
244while test $try -lt 12; do
245  touch $TMPDIR/example.log.$try
246  try=$((try + 1))
247done
248rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
249_found2() (
250  $DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n
251  grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
252
253  try=1
254  while test $try -lt 12; do
255    [ -f $TMPDIR/example.log.$try ] && return 1
256    try=$((try + 1))
257  done
258  set -- $TMPDIR/example.log.*
259  [ "$#" -eq 1 ] || return 1
260)
261retry_quiet 5 _found2 || ret=1
262if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
263status=$((status + ret))
264
265n=$((n + 1))
266echo_i "testing unlimited versions ($n)"
267ret=0
268copy_setports ns1/named.unlimited.in ns1/named.conf
269# a seconds since epoch version number
270touch ns1/named_unlimited.1480039317
271rndc_reconfig ns1 10.53.0.1 >rndc.out.test$n
272$DIG version.bind txt ch @10.53.0.1 -p ${PORT} >dig.out.test$n
273grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
274test_with_retry -f ns1/named_unlimited.1480039317 || ret=1
275test_with_retry -f ns1/named_unlimited.4 || ret=1
276if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
277status=$((status + ret))
278
279n=$((n + 1))
280echo_i "testing default logfile using named -L file ($n)"
281ret=0
282stop_server ns1
283cp named2.args ns1/named.args
284test -f ns1/named.pid && ret=1
285rm -f ns1/named_deflog
286copy_setports ns1/named.plainconf.in ns1/named.conf
287start_server --noclean --restart --port ${PORT} ns1
288[ -f "ns1/named_deflog" ] || ret=1
289if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
290status=$((status + ret))
291
292echo_i "exit status: $status"
293[ $status -eq 0 ] || exit 1
294