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# touch dnsrps-off to not test with DNSRPS 15# touch dnsrps-only to not test with classic RPZ 16 17SYSTEMTESTTOP=.. 18. $SYSTEMTESTTOP/conf.sh 19 20status=0 21 22t=0 23 24DEBUG= 25ARGS= 26 27USAGE="$0: [-xS]" 28while getopts "xS:" c; do 29 case $c in 30 x) set -x; DEBUG=-x; ARGS="$ARGS -x";; 31 S) SAVE_RESULTS=-S; ARGS="$ARGS -S";; 32 *) echo "$USAGE" 1>&2; exit 1;; 33 esac 34done 35shift `expr $OPTIND - 1 || true` 36if test "$#" -ne 0; then 37 echo "$USAGE" 1>&2 38 exit 1 39fi 40# really quit on control-C 41trap 'exit 1' 1 2 15 42 43DNSRPSCMD=../rpz/dnsrps 44RNDCCMD="$RNDC -c $SYSTEMTESTTOP/common/rndc.conf -p ${CONTROLPORT} -s" 45 46# $1 = test name (such as 1a, 1b, etc. for which named.$1.conf exists) 47run_server() { 48 TESTNAME=$1 49 50 echo_i "stopping resolver" 51 stop_server --use-rndc --port ${CONTROLPORT} ns2 52 53 sleep 1 54 55 echo_i "starting resolver using named.$TESTNAME.conf" 56 cp -f ns2/named.$TESTNAME.conf ns2/named.conf 57 start_server --noclean --restart --port ${PORT} ns2 58 sleep 3 59} 60 61run_query() { 62 TESTNAME=$1 63 LINE=$2 64 65 NAME=`sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1` 66 $DIG $DIGOPTS $NAME a @10.53.0.2 -p ${PORT} -b 127.0.0.1 > dig.out.${t} 67 grep "status: SERVFAIL" dig.out.${t} > /dev/null 2>&1 && return 1 68 return 0 69} 70 71# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists) 72# $2 = line number in query file to test (the name to query is taken from this line) 73expect_norecurse() { 74 TESTNAME=$1 75 LINE=$2 76 77 NAME=`sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1` 78 t=`expr $t + 1` 79 echo_i "testing $NAME doesn't recurse (${t})" 80 add_test_marker 10.53.0.2 81 run_query $TESTNAME $LINE || { 82 echo_i "test ${t} failed" 83 status=1 84 } 85} 86 87# $1 = test name (such as 1a, 1b, etc. for which $1.queries exists) 88# $2 = line number in query file to test (the name to query is taken from this line) 89expect_recurse() { 90 TESTNAME=$1 91 LINE=$2 92 93 NAME=`sed -n -e "$LINE,"'$p' ns2/$TESTNAME.queries | head -n 1` 94 t=`expr $t + 1` 95 echo_i "testing $NAME recurses (${t})" 96 add_test_marker 10.53.0.2 97 run_query $TESTNAME $LINE && { 98 echo_i "test ${t} failed" 99 status=1 100 } 101} 102 103add_test_marker() { 104 for ns in $@ 105 do 106 $RNDCCMD $ns null ---- test ${t} ---- 107 done 108} 109 110for mode in native dnsrps; do 111 status=0 112 case $mode in 113 native) 114 if [ -e dnsrps-only ] ; then 115 echo_i "'dnsrps-only' found: skipping native RPZ sub-test" 116 continue 117 else 118 echo_i "running native RPZ sub-test" 119 fi 120 ;; 121 dnsrps) 122 if [ -e dnsrps-off ] ; then 123 echo_i "'dnsrps-off' found: skipping DNSRPS sub-test" 124 continue 125 fi 126 echo_i "attempting to configure servers with DNSRPS..." 127 stop_server --use-rndc --port ${CONTROLPORT} 128 $SHELL ./setup.sh -N -D $DEBUG 129 sed -n 's/^## //p' dnsrps.conf | cat_i 130 if grep '^#fail' dnsrps.conf >/dev/null; then 131 echo_i "exit status: 1" 132 exit 1 133 fi 134 if grep '^#skip' dnsrps.conf > /dev/null; then 135 echo_i "DNSRPS sub-test skipped" 136 continue 137 else 138 echo_i "running DNSRPS sub-test" 139 start_server --noclean --restart --port ${PORT} 140 sleep 3 141 fi 142 ;; 143 esac 144 145 # show whether and why DNSRPS is enabled or disabled 146 sed -n 's/^## //p' dnsrps.conf | cat_i 147 148 t=`expr $t + 1` 149 echo_i "testing that l1.l0 exists without RPZ (${t})" 150 add_test_marker 10.53.0.2 151 $DIG $DIGOPTS l1.l0 ns @10.53.0.2 -p ${PORT} > dig.out.${t} 152 grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || { 153 echo_i "test ${t} failed" 154 status=1 155 } 156 157 t=`expr $t + 1` 158 echo_i "testing that l2.l1.l0 returns SERVFAIL without RPZ (${t})" 159 add_test_marker 10.53.0.2 160 $DIG $DIGOPTS l2.l1.l0 ns @10.53.0.2 -p ${PORT} > dig.out.${t} 161 grep "status: SERVFAIL" dig.out.${t} > /dev/null 2>&1 || { 162 echo_i "test ${t} failed" 163 status=1 164 } 165 166 # Group 1 167 run_server 1a 168 expect_norecurse 1a 1 169 run_server 1b 170 expect_norecurse 1b 1 171 expect_recurse 1b 2 172 run_server 1c 173 expect_norecurse 1c 1 174 175 # Group 2 176 run_server 2a 177 for n in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \ 178 21 22 23 24 25 26 27 28 29 30 31 32 179 do 180 expect_norecurse 2a $n 181 done 182 expect_recurse 2a 33 183 184 # Group 3 185 run_server 3a 186 expect_recurse 3a 1 187 run_server 3b 188 expect_recurse 3b 1 189 run_server 3c 190 expect_recurse 3c 1 191 run_server 3d 192 expect_norecurse 3d 1 193 expect_recurse 3d 2 194 run_server 3e 195 expect_norecurse 3e 1 196 expect_recurse 3e 2 197 run_server 3f 198 expect_norecurse 3f 1 199 expect_recurse 3f 2 200 201 # Group 4 202 testlist="aa ap bf" 203 values="1 16 32" 204 # Uncomment the following to test every skip value instead of 205 # only a sample of values 206 # 207 #testlist="aa ab ac ad ae af ag ah ai aj ak al am an ao ap \ 208 # aq ar as at au av aw ax ay az ba bb bc bd be bf" 209 #values="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \ 210 # 21 22 23 24 25 26 27 28 29 30 31 32" 211 set -- $values 212 for n in $testlist; do 213 run_server 4$n 214 ni=$1 215 t=`expr $t + 1` 216 echo_i "testing that ${ni} of 33 queries skip recursion (${t})" 217 add_test_marker 10.53.0.2 218 c=0 219 for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \ 220 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 221 do 222 run_query 4$n $i 223 c=`expr $c + $?` 224 done 225 skipped=`expr 33 - $c` 226 if [ $skipped != $ni ]; then 227 echo_i "test $t failed (actual=$skipped, expected=$ni)" 228 status=1 229 fi 230 shift 231 done 232 233 # Group 5 234 run_server 5a 235 expect_norecurse 5a 1 236 expect_norecurse 5a 2 237 expect_recurse 5a 3 238 expect_recurse 5a 4 239 expect_recurse 5a 5 240 expect_recurse 5a 6 241 242 if [ ! "$CYGWIN" -o -n "$PSSUSPEND" ] 243 then 244 # Group 6 245 echo_i "check recursive behavior consistency during policy update races" 246 run_server 6a 247 sleep 1 248 t=`expr $t + 1` 249 echo_i "running dig to cache CNAME record (${t})" 250 add_test_marker 10.53.0.1 10.53.0.2 251 $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME > dig.out.${t} 252 sleep 1 253 echo_i "suspending authority server" 254 PID=`cat ns1/named.pid` 255 if [ "$CYGWIN" ] 256 then 257 $PSSUSPEND $PID 258 else 259 $KILL -STOP $PID 260 fi 261 echo_i "adding an NSDNAME policy" 262 cp ns2/db.6a.00.policy.local ns2/saved.policy.local 263 cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local 264 $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i 265 test -f dnsrpzd.pid && $KILL -USR1 `cat dnsrpzd.pid` 266 sleep 1 267 t=`expr $t + 1` 268 echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})" 269 add_test_marker 10.53.0.2 270 $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 > dig.out.${t} & 271 sleep 1 272 echo_i "removing the NSDNAME policy" 273 cp ns2/db.6c.00.policy.local ns2/db.6a.00.policy.local 274 $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i 275 test -f dnsrpzd.pid && $KILL -USR1 `cat dnsrpzd.pid` 276 sleep 1 277 echo_i "resuming authority server" 278 PID=`cat ns1/named.pid` 279 if [ "$CYGWIN" ] 280 then 281 $PSSUSPEND -r $PID 282 else 283 $KILL -CONT $PID 284 fi 285 add_test_marker 10.53.0.1 286 for n in 1 2 3 4 5 6 7 8 9 287 do 288 sleep 1 289 [ -s dig.out.${t} ] || continue 290 grep "status: .*," dig.out.${t} > /dev/null 2>&1 && break 291 done 292 grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || { 293 echo_i "test ${t} failed" 294 status=1 295 } 296 297 echo_i "check recursive behavior consistency during policy removal races" 298 cp ns2/saved.policy.local ns2/db.6a.00.policy.local 299 run_server 6a 300 sleep 1 301 t=`expr $t + 1` 302 echo_i "running dig to cache CNAME record (${t})" 303 add_test_marker 10.53.0.1 10.53.0.2 304 $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org CNAME > dig.out.${t} 305 sleep 1 306 echo_i "suspending authority server" 307 PID=`cat ns1/named.pid` 308 if [ "$CYGWIN" ] 309 then 310 $PSSUSPEND $PID 311 else 312 $KILL -STOP $PID 313 fi 314 echo_i "adding an NSDNAME policy" 315 cp ns2/db.6b.00.policy.local ns2/db.6a.00.policy.local 316 $RNDC -c ../common/rndc.conf -s 10.53.0.2 -p ${CONTROLPORT} reload 6a.00.policy.local 2>&1 | sed 's/^/ns2 /' | cat_i 317 test -f dnsrpzd.pid && $KILL -USR1 `cat dnsrpzd.pid` 318 sleep 1 319 t=`expr $t + 1` 320 echo_i "running dig to follow CNAME (blocks, so runs in the background) (${t})" 321 add_test_marker 10.53.0.2 322 $DIG $DIGOPTS @10.53.0.2 -p ${PORT} www.test.example.org A +time=5 > dig.out.${t} & 323 sleep 1 324 echo_i "removing the policy zone" 325 cp ns2/named.default.conf ns2/named.conf 326 rndc_reconfig ns2 10.53.0.2 327 test -f dnsrpzd.pid && $KILL -USR1 `cat dnsrpzd.pid` 328 sleep 1 329 echo_i "resuming authority server" 330 PID=`cat ns1/named.pid` 331 if [ "$CYGWIN" ] 332 then 333 $PSSUSPEND -r $PID 334 else 335 $KILL -CONT $PID 336 fi 337 add_test_marker 10.53.0.1 338 for n in 1 2 3 4 5 6 7 8 9; do 339 sleep 1 340 [ -s dig.out.${t} ] || continue 341 grep "status: .*," dig.out.${t} > /dev/null 2>&1 && break 342 done 343 grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || { 344 echo_i "test ${t} failed" 345 status=1 346 } 347 fi 348 349 # Check maximum number of RPZ zones (64) 350 t=`expr $t + 1` 351 echo_i "testing maximum number of RPZ zones (${t})" 352 add_test_marker 10.53.0.2 353 run_server max 354 i=1 355 while test $i -le 64 356 do 357 $DIG $DIGOPTS name$i a @10.53.0.2 -p ${PORT} -b 10.53.0.1 > dig.out.${t}.${i} 358 grep "^name$i.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.$i" dig.out.${t}.${i} > /dev/null 2>&1 || { 359 echo_i "test $t failed: didn't get expected answer from policy zone $i" 360 status=1 361 } 362 i=`expr $i + 1` 363 done 364 365 # Check CLIENT-IP behavior 366 t=`expr $t + 1` 367 echo_i "testing CLIENT-IP behavior (${t})" 368 add_test_marker 10.53.0.2 369 run_server clientip 370 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 > dig.out.${t} 371 grep "status: NOERROR" dig.out.${t} > /dev/null 2>&1 || { 372 echo_i "test $t failed: query failed" 373 status=1 374 } 375 grep "^l2.l1.l0.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.2" dig.out.${t} > /dev/null 2>&1 || { 376 echo_i "test $t failed: didn't get expected answer" 377 status=1 378 } 379 380 # Check CLIENT-IP behavior #2 381 t=`expr $t + 1` 382 echo_i "testing CLIENT-IP behavior #2 (${t})" 383 add_test_marker 10.53.0.2 384 run_server clientip2 385 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.1 > dig.out.${t}.1 386 grep "status: SERVFAIL" dig.out.${t}.1 > /dev/null 2>&1 || { 387 echo_i "test $t failed: query failed" 388 status=1 389 } 390 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 > dig.out.${t}.2 391 grep "status: NXDOMAIN" dig.out.${t}.2 > /dev/null 2>&1 || { 392 echo_i "test $t failed: query failed" 393 status=1 394 } 395 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 > dig.out.${t}.3 396 grep "status: NOERROR" dig.out.${t}.3 > /dev/null 2>&1 || { 397 echo_i "test $t failed: query failed" 398 status=1 399 } 400 grep "^l2.l1.l0.[ ]*[0-9]*[ ]*IN[ ]*A[ ]*10.53.0.1" dig.out.${t}.3 > /dev/null 2>&1 || { 401 echo_i "test $t failed: didn't get expected answer" 402 status=1 403 } 404 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 > dig.out.${t}.4 405 grep "status: SERVFAIL" dig.out.${t}.4 > /dev/null 2>&1 || { 406 echo_i "test $t failed: query failed" 407 status=1 408 } 409 410 # Check RPZ log clause 411 t=`expr $t + 1` 412 echo_i "testing RPZ log clause (${t})" 413 add_test_marker 10.53.0.2 414 run_server log 415 cur=`awk 'BEGIN {l=0} /^/ {l++} END { print l }' ns2/named.run` 416 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.4 > dig.out.${t} 417 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.3 >> dig.out.${t} 418 $DIG $DIGOPTS l2.l1.l0 a @10.53.0.2 -p ${PORT} -b 10.53.0.2 >> dig.out.${t} 419 sed -n "$cur,"'$p' < ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.4.0.53.10.rpz-client-ip.log1" > /dev/null && { 420 echo_ic "failed: unexpected rewrite message for policy zone log1 was logged" 421 status=1 422 } 423 sed -n "$cur,"'$p' < ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.3.0.53.10.rpz-client-ip.log2" > /dev/null || { 424 echo_ic "failed: expected rewrite message for policy zone log2 was not logged" 425 status=1 426 } 427 sed -n "$cur,"'$p' < ns2/named.run | grep "view recursive: rpz CLIENT-IP Local-Data rewrite l2.l1.l0/A/IN via 32.2.0.53.10.rpz-client-ip.log3" > /dev/null || { 428 echo_ic "failed: expected rewrite message for policy zone log3 was not logged" 429 status=1 430 } 431 432 # Check wildcard behavior 433 434 t=`expr $t + 1` 435 echo_i "testing wildcard behavior with 1 RPZ zone (${t})" 436 add_test_marker 10.53.0.2 437 run_server wildcard1 438 $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.1 439 grep "status: NXDOMAIN" dig.out.${t}.1 > /dev/null || { 440 echo_i "test ${t} failed" 441 status=1 442 } 443 $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.2 444 grep "status: NXDOMAIN" dig.out.${t}.2 > /dev/null || { 445 echo_i "test ${t} failed" 446 status=1 447 } 448 449 t=`expr $t + 1` 450 echo_i "testing wildcard behavior with 2 RPZ zones (${t})" 451 add_test_marker 10.53.0.2 452 run_server wildcard2 453 $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.1 454 grep "status: NXDOMAIN" dig.out.${t}.1 > /dev/null || { 455 echo_i "test ${t} failed" 456 status=1 457 } 458 $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.2 459 grep "status: NXDOMAIN" dig.out.${t}.2 > /dev/null || { 460 echo_i "test ${t} failed" 461 status=1 462 } 463 464 t=`expr $t + 1` 465 echo_i "testing wildcard behavior with 1 RPZ zone and no non-wildcard triggers (${t})" 466 add_test_marker 10.53.0.2 467 run_server wildcard3 468 $DIG $DIGOPTS www.test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.1 469 grep "status: NXDOMAIN" dig.out.${t}.1 > /dev/null || { 470 echo_i "test ${t} failed" 471 status=1 472 } 473 $DIG $DIGOPTS test1.example.net a @10.53.0.2 -p ${PORT} > dig.out.${t}.2 474 grep "status: NOERROR" dig.out.${t}.2 > /dev/null || { 475 echo_i "test ${t} failed" 476 status=1 477 } 478 479 # Check for invalid prefix length error 480 t=`expr $t + 1` 481 echo_i "testing for invalid prefix length error (${t})" 482 add_test_marker 10.53.0.2 483 run_server invalidprefixlength 484 grep "invalid rpz IP address \"1000.4.0.53.10.rpz-client-ip.invalidprefixlength\"; invalid prefix length of 1000$" ns2/named.run > /dev/null || { 485 echo_ic "failed: expected that invalid prefix length error would be logged" 486 status=1 487 } 488 489 t=`expr $t + 1` 490 echo_i "testing wildcard passthru before explicit drop (${t})" 491 add_test_marker 10.53.0.2 492 run_server wildcard4 493 $DIG $DIGOPTS example.com a @10.53.0.2 -p ${PORT} > dig.out.${t}.1 494 grep "status: NOERROR" dig.out.${t}.1 > /dev/null || { 495 echo_i "test ${t} failed" 496 status=1 497 } 498 $DIG $DIGOPTS www.example.com a @10.53.0.2 -p ${PORT} > dig.out.${t}.2 499 grep "status: NOERROR" dig.out.${t}.2 > /dev/null || { 500 echo_i "test ${t} failed" 501 status=1 502 } 503 504 t=`expr $t + 1` 505 echo_i "checking 'nsip-wait-recurse no' is faster than 'nsip-wait-recurse yes' ($t)" 506 add_test_marker 10.53.0.2 10.53.0.3 507 echo_i "timing 'nsip-wait-recurse yes' (default)" 508 ret=0 509 t1=`$PERL -e 'print time()."\n";'` 510 $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.yes.$t 511 t2=`$PERL -e 'print time()."\n";'` 512 p1=`expr $t2 - $t1` 513 echo_i "elasped time $p1 seconds" 514 515 $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} flush 516 copy_setports ns3/named2.conf.in ns3/named.conf 517 nextpart ns3/named.run > /dev/null 518 $RNDC -c ../common/rndc.conf -s 10.53.0.3 -p ${CONTROLPORT} reload > /dev/null 519 wait_for_log 20 "rpz: policy: reload done" ns3/named.run || ret=1 520 521 echo_i "timing 'nsip-wait-recurse no'" 522 t3=`$PERL -e 'print time()."\n";'` 523 $DIG -p ${PORT} @10.53.0.3 foo.child.example.tld a > dig.out.no.$t 524 t4=`$PERL -e 'print time()."\n";'` 525 p2=`expr $t4 - $t3` 526 echo_i "elasped time $p2 seconds" 527 528 if test $p1 -le $p2; then ret=1; fi 529 if test $ret != 0; then echo_i "failed"; fi 530 status=`expr $status + $ret` 531 532 [ $status -ne 0 ] && pf=fail || pf=pass 533 case $mode in 534 native) 535 native=$status 536 echo_i "status (native RPZ sub-test): $status ($pf)";; 537 dnsrps) 538 dnsrps=$status 539 echo_i "status (DNSRPS sub-test): $status ($pf)";; 540 *) echo_i "invalid test mode";; 541 esac 542done 543status=`expr ${native:-0} + ${dnsrps:-0}` 544 545[ $status -eq 0 ] || exit 1 546