allow-update { any; };
};
-zone "corp" {
- type primary;
- file "corp.db";
-};
-
zone "hours-vs-days" {
type primary;
file "hours-vs-days.db.signed";
recursion yes;
minimal-responses no;
- nta-lifetime 12s;
- nta-recheck 9s;
- validate-except { corp; };
-
# Note: We only reference the bind.keys file here to confirm that it
# is *not* being used. It contains the real root key, and we're
# using a local toy root zone for the tests, so it wouldn't work.
type hint;
file "../../_common/root.hint";
};
-
-zone "corp" {
- type static-stub;
- server-addresses { 10.53.0.2; };
-};
recursion yes;
minimal-responses no;
- nta-lifetime 12s;
- nta-recheck 9s;
- validate-except { corp; };
-
dnssec-validation auto;
bindkeys-file "managed.conf";
};
type hint;
file "../../_common/root.hint";
};
-
-zone "corp" {
- type static-stub;
- server-addresses { 10.53.0.2; };
-};
recursion yes;
minimal-responses no;
- nta-lifetime 12s;
- nta-recheck 9s;
- validate-except { corp; };
-
dnssec-accept-expired yes;
servfail-ttl 0;
type hint;
file "../../_common/root.hint";
};
-
-zone "corp" {
- type static-stub;
- server-addresses { 10.53.0.2; };
-};
listen-on-v6 { none; };
minimal-responses no;
- nta-lifetime 12s;
- nta-recheck 9s;
-
disable-algorithms "digest-alg-unsupported.example." { ECDSAP384SHA384; };
disable-ds-digests "digest-alg-unsupported.example." { "SHA384"; "SHA-384"; };
disable-ds-digests "ds-unsupported.example." { "SHA256"; "SHA-256"; "SHA384"; "SHA-384"; };
file "../../_common/root.hint";
};
- zone "corp" {
- type static-stub;
- server-addresses { 10.53.0.2; };
- };
-
include "broken.conf";
{% else %}
zone "." {
linecount=$(grep -c "./$DEFAULT_ALGORITHM/$keyid ; static" named.secroots.test$n || true)
[ "$linecount" -eq 1 ] || ret=1
linecount=$(wc <named.secroots.test$n -l)
-[ "$linecount" -eq 10 ] || ret=1
+[ "$linecount" -eq 9 ] || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "checking validate-except in an insecure local domain ($n)"
-ret=0
-dig_with_opts ns www.corp @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking positive and negative validation with negative trust anchors ($n)"
-ret=0
-
-#
-# check correct initial behavior
-#
-dig_with_opts a.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.1 >/dev/null || ret=1
-dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null || ret=1
-dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null || ret=1
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - checking initial state"; fi
-status=$((status + ret))
-ret=0
-
-#
-# add negative trust anchors
-#
-rndccmd 10.53.0.4 nta -f -l 20s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
-rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
-# reconfig should maintain NTAs
-rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1
-lines=$(wc -l <rndc.out.ns4.test$n.1)
-[ "$lines" -eq 3 ] || ret=1
-rndccmd 10.53.0.4 nta secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
-rndccmd 10.53.0.4 nta fakenode.secure.example 2>&1 | sed 's/^/ns4 /' | cat_i
-# reload should maintain NTAs
-rndc_reload ns4 10.53.0.4
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.2
-lines=$(wc -l <rndc.out.ns4.test$n.2)
-[ "$lines" -eq 5 ] || ret=1
-# shellcheck disable=SC2016
-start=$($PERL -e 'print time()."\n";')
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - adding NTA's failed"; fi
-status=$((status + ret))
-ret=0
-
-#
-# check behavior with NTA's in place
-#
-dig_with_opts a.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.4 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.4 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 >/dev/null && ret=1
-dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.5 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.5 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.5 >/dev/null && ret=1
-dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.6 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.6 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.6 >/dev/null && ret=1
-dig_with_opts a.fakenode.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.7 || ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.7 >/dev/null && ret=1
-echo_i "dumping secroots"
-rndccmd 10.53.0.4 secroots | sed 's/^/ns4 /' | cat_i
-cp ns4/named.secroots named.secroots.test$n
-check_secroots_layout named.secroots.test$n || ret=1
-grep "bogus.example: expiry" named.secroots.test$n >/dev/null || ret=1
-grep "badds.example: expiry" named.secroots.test$n >/dev/null || ret=1
-grep "secure.example: expiry" named.secroots.test$n >/dev/null || ret=1
-grep "fakenode.secure.example: expiry" named.secroots.test$n >/dev/null || ret=1
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - with NTA's in place failed"; fi
-status=$((status + ret))
-ret=0
-
-echo_i "waiting for NTA rechecks/expirations"
-
-#
-# secure.example and badds.example used default nta-duration
-# (configured as 12s in ns4/named1.conf), but nta recheck interval
-# is configured to 9s, so at t=10 the NTAs for secure.example and
-# fakenode.secure.example should both be lifted, but badds.example
-# should still be going.
-#
-# shellcheck disable=SC2016
-$PERL -e 'my $delay = '"$start"' + 10 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
-dig_with_opts b.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.8 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.8 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.8 >/dev/null || ret=1
-dig_with_opts b.fakenode.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.9 || ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.9 >/dev/null || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n.9 >/dev/null || ret=1
-dig_with_opts badds.example. soa @10.53.0.4 >dig.out.ns4.test$n.10 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.10 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.10 >/dev/null && ret=1
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to recheck"; fi
-status=$((status + ret))
-ret=0
-
-#
-# bogus.example was set to expire in 20s, so at t=13
-# it should still be NTA'd, but badds.example used the default
-# lifetime of 12s, so it should revert to SERVFAIL now.
-#
-# shellcheck disable=SC2016
-$PERL -e 'my $delay = '"$start"' + 13 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
-# check nta table
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n._11
-lines=$(grep -c " expiry " rndc.out.ns4.test$n._11 || true)
-[ "$lines" -le 2 ] || ret=1
-grep "bogus.example/_default: expiry" rndc.out.ns4.test$n._11 >/dev/null || ret=1
-grep "badds.example/_default: expiry" rndc.out.ns4.test$n._11 >/dev/null && ret=1
-dig_with_opts b.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.11 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.11 >/dev/null && ret=1
-dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.12 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.12 >/dev/null || ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.12 >/dev/null && ret=1
-dig_with_opts c.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.13 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.13 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.13 >/dev/null || ret=1
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - checking that default nta's were lifted due to lifetime"; fi
-status=$((status + ret))
-ret=0
-
-#
-# at t=21, all the NTAs should have expired.
-#
-# shellcheck disable=SC2016
-$PERL -e 'my $delay = '"$start"' + 21 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
-# check correct behavior after bogus.example expiry
-dig_with_opts d.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.14 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.14 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.14 >/dev/null || ret=1
-dig_with_opts c.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.15 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.15 >/dev/null || ret=1
-# check nta table has been cleaned up now
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3
-lines=$(grep -c " expiry " rndc.out.ns4.test$n.3 || true)
-[ "$lines" -eq 0 ] || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed - checking that all nta's have been lifted"; fi
-status=$((status + ret))
-ret=0
-
-echo_i "testing NTA removals ($n)"
-rndccmd 10.53.0.4 nta badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1
-grep "badds.example/_default: expiry" rndc.out.ns4.test$n.1 >/dev/null || ret=1
-dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.1 >/dev/null && ret=1
-grep "^a.badds.example." dig.out.ns4.test$n.1 >/dev/null || ret=1
-rndccmd 10.53.0.4 nta -remove badds.example >rndc.out.ns4.test$n.2
-grep "Negative trust anchor removed: badds.example/_default" rndc.out.ns4.test$n.2 >/dev/null || ret=1
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3
-grep "badds.example/_default: expiry" rndc.out.ns4.test$n.3 >/dev/null && ret=1
-dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null || ret=1
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-ret=0
-
-echo_i "remove non-existent NTA three times"
-rndccmd 10.53.0.4 nta -r foo >rndc.out.ns4.test$n.4 2>&1
-rndccmd 10.53.0.4 nta -remove foo >rndc.out.ns4.test$n.5 2>&1
-rndccmd 10.53.0.4 nta -r foo >rndc.out.ns4.test$n.6 2>&1
-grep "not found" rndc.out.ns4.test$n.6 >/dev/null || ret=1
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-ret=0
-
-n=$((n + 1))
-echo_i "testing NTA with bogus lifetimes ($n)"
-echo_i "check with no nta lifetime specified"
-rndccmd 10.53.0.4 nta -l "" foo >rndc.out.ns4.test$n.1 2>&1 || true
-grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.1 >/dev/null || ret=1
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-ret=0
-
-echo_i "check with bad nta lifetime"
-rndccmd 10.53.0.4 nta -l garbage foo >rndc.out.ns4.test$n.2 2>&1 || true
-grep "'nta' failed: bad ttl" rndc.out.ns4.test$n.2 >/dev/null || ret=1
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-ret=0
-
-echo_i "check with too long nta lifetime"
-rndccmd 10.53.0.4 nta -l 7d1h foo >rndc.out.ns4.test$n.3 2>&1 || true
-grep "'nta' failed: out of range" rndc.out.ns4.test$n.3 >/dev/null || ret=1
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-ret=0
-
-#
-# check NTA persistence across restarts
-#
-n=$((n + 1))
-echo_i "testing NTA persistence across restarts ($n)"
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1
-lines=$(grep -c " expiry " rndc.out.ns4.test$n.1 || true)
-[ "$lines" -eq 0 ] || ret=1
-rndccmd 10.53.0.4 nta -f -l 30s bogus.example 2>&1 | sed 's/^/ns4 /' | cat_i
-rndccmd 10.53.0.4 nta -f -l 10s badds.example 2>&1 | sed 's/^/ns4 /' | cat_i
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.2
-lines=$(grep -c " expiry " rndc.out.ns4.test$n.2 || true)
-[ "$lines" -eq 2 ] || ret=1
-# shellcheck disable=SC2016
-start=$($PERL -e 'print time()."\n";')
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: adding NTA's failed"; fi
-status=$((status + ret))
-ret=0
-
-echo_i "killing ns4 with SIGTERM"
-kill -TERM "$(cat ns4/named.pid)"
-rm -f ns4/named.pid
-
-#
-# ns4 has now shutdown. wait until t=14 when badds.example's NTA
-# (lifetime=10s) would have expired, and then restart ns4.
-#
-echo_i "waiting till 14s have passed since NTAs were added before restarting ns4"
-# shellcheck disable=SC2016
-$PERL -e 'my $delay = '"$start"' + 14 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
-
-if
- start_server --noclean --restart --port "$PORT" ns4
-then
- echo_i "restarted server ns4"
-else
- echo_i "could not restart server ns4"
- exit 1
-fi
-
-echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
-sleep 4
-
-#
-# ns4 should be back up now. The NTA for bogus.example should still be
-# valid, whereas badds.example should not have been added during named
-# startup (as it had already expired), the fact that it's ignored should
-# be logged.
-#
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.3
-lines=$(wc -l <rndc.out.ns4.test$n.3)
-[ "$lines" -eq 2 ] || ret=1
-grep "bogus.example/_default: expiry" rndc.out.ns4.test$n.3 >/dev/null || ret=1
-dig_with_opts b.bogus.example. a @10.53.0.4 >dig.out.ns4.test$n.4 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.4 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.4 >/dev/null && ret=1
-dig_with_opts a.badds.example. a @10.53.0.4 >dig.out.ns4.test$n.5 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.5 >/dev/null || ret=1
-grep "ignoring expired NTA at badds.example" ns4/named.run >/dev/null || ret=1
-
-# cleanup
-rndccmd 10.53.0.4 nta -remove bogus.example >rndc.out.ns4.test$n.6
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: restoring NTA failed"; fi
-status=$((status + ret))
-ret=0
-
-#
-# check "regular" attribute in NTA file works as expected at named
-# startup.
-#
-n=$((n + 1))
-echo_i "testing loading regular attribute from NTA file ($n)"
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 2>/dev/null
-lines=$(wc -l <rndc.out.ns4.test$n.1)
-[ "$lines" -eq 1 ] || ret=1
-# initially, secure.example. validates with AD=1
-dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 >/dev/null || ret=1
-
-echo_i "killing ns4 with SIGTERM"
-kill -TERM "$(cat ns4/named.pid)"
-rm -f ns4/named.pid
-
-echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
-sleep 4
-
-#
-# ns4 has now shutdown. add NTA for secure.example. directly into the
-# _default.nta file with the regular attribute and some future timestamp.
-#
-future="$(($(date +%Y) + 20))0101010000"
-echo "secure.example. regular $future" >ns4/_default.nta
-# shellcheck disable=SC2016
-start=$($PERL -e 'print time()."\n";')
-
-if
- start_server --noclean --restart --port "$PORT" ns4
-then
- echo_i "restarted server ns4"
-else
- echo_i "could not restart server ns4"
- exit 1
-fi
-
-# nta-recheck is configured as 9s, so at t=12 the NTAs for
-# secure.example. should be lifted as it is not a forced NTA.
-echo_i "waiting till 12s have passed after ns4 was restarted"
-# shellcheck disable=SC2016
-$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
-
-# secure.example. should now return an AD=1 answer (still validates) as
-# the NTA has been lifted.
-dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null || ret=1
-
-# cleanup
-rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.4 2>/dev/null
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading regular NTAs failed"; fi
-status=$((status + ret))
-ret=0
-
-#
-# check "forced" attribute in NTA file works as expected at named
-# startup.
-#
-n=$((n + 1))
-echo_i "testing loading forced attribute from NTA file ($n)"
-rndccmd 10.53.0.4 nta -d >rndc.out.ns4.test$n.1 2>/dev/null
-lines=$(wc -l <rndc.out.ns4.test$n.1)
-[ "$lines" -eq 1 ] || ret=1
-# initially, secure.example. validates with AD=1
-dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.2 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.2 >/dev/null || ret=1
-
-echo_i "killing ns4 with SIGTERM"
-kill -TERM "$(cat ns4/named.pid)"
-rm -f named.pid
-
-echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
-sleep 4
-
-#
-# ns4 has now shutdown. add NTA for secure.example. directly into the
-# _default.nta file with the forced attribute and some future timestamp.
-#
-echo "secure.example. forced $future" >ns4/_default.nta
-start=$($PERL -e 'print time()."\n";')
-
-if
- start_server --noclean --restart --port "$PORT" ns4
-then
- echo_i "restarted server ns4"
-else
- echo_i "could not restart server ns4"
- exit 1
-fi
-
-# nta-recheck is configured as 9s, but even at t=12 the NTAs for
-# secure.example. should not be lifted as it is a forced NTA.
-echo_i "waiting till 12s have passed after ns4 was restarted"
-# shellcheck disable=SC2016
-$PERL -e 'my $delay = '"$start"' + 12 - time(); select(undef, undef, undef, $delay) if ($delay > 0);'
-
-# secure.example. should now return an AD=0 answer (non-authenticated)
-# as the NTA is still there.
-dig_with_opts a.secure.example. a @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n.3 >/dev/null && ret=1
-grep "flags:[^;]* ad[^;]*;" dig.out.ns4.test$n.3 >/dev/null && ret=1
-
-# cleanup
-rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.4 2>/dev/null
-
-if [ "$ret" -ne 0 ]; then echo_i "failed - NTA persistence: loading forced NTAs failed"; fi
-status=$((status + ret))
-ret=0
-
-#
-# check that NTA lifetime read from file is clamped to 1 week.
-#
-n=$((n + 1))
-echo_i "testing loading out of bounds lifetime from NTA file ($n)"
-
-echo_i "killing ns4 with SIGTERM"
-kill -TERM "$(cat ns4/named.pid)"
-rm -f ns4/named.pid
-
-echo_i "sleeping for an additional 4 seconds for ns4 to fully shutdown"
-sleep 4
-
-#
-# ns4 has now shutdown. add NTA for secure.example. directly into the
-# _default.nta file with a lifetime well into the future.
-#
-echo "secure.example. forced $future" >ns4/_default.nta
-added=$($PERL -e 'print time()."\n";')
-
-if
- start_server --noclean --restart --port "$PORT" ns4
-then
- echo_i "restarted server ns4"
-else
- echo_i "could not restart server ns4"
- exit 1
-fi
-
-echo_i "sleeping for an additional 4 seconds for ns4 to fully startup"
-sleep 4
-
-# dump the NTA to a file (omit validate-except entries)
-echo_i "testing 'rndc nta -d' with NTA"
-rndccmd 10.53.0.4 nta -d | grep -v ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null
-# "corp" is configured as a validate-except domain and thus should be
-# removed by the grep -v above. only "secure.example" should appear in
-# the dump.
-lines=$(wc -l <rndc.out.ns4.test$n.1)
-[ "$lines" -eq 1 ] || ret=1
-grep 'secure.example' rndc.out.ns4.test$n.1 >/dev/null || ret=1
-ts=$(awk '{print $3" "$4}' <rndc.out.ns4.test$n.1)
-# rndc nta outputs localtime, so append the timezone
-ts_with_zone="$ts $(date +%z)"
-echo "ts=$ts" >rndc.out.ns4.test$n.2
-echo "ts_with_zone=$ts_with_zone" >>rndc.out.ns4.test$n.2
-echo "added=$added" >>rndc.out.ns4.test$n.2
-if $PERL -e 'use Time::Piece; use Time::Seconds;' 2>/dev/null; then
- # ntadiff.pl computes $ts_with_zone - ($added + 1week)
- d=$($PERL ./ntadiff.pl "$ts_with_zone" "$added")
- echo "d=$d" >>rndc.out.ns4.test$n.2
- # diff from $added(now) + 1week to the clamped NTA lifetime should be
- # less than a few seconds (handle daylight saving changes by adding 3600).
- [ "$d" -lt 3610 ] || ret=1
-else
- echo_i "skipped ntadiff test; install PERL module Time::Piece"
-fi
-
-echo_i "testing 'rndc nta' lifetime clamping"
-rndccmd 10.53.0.4 nta -d | grep ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null
-# "corp" is configured as a validate-except domain and thus should be
-# the only entry in the dump.
-lines=$(wc -l <rndc.out.ns4.test$n.1)
-[ "$lines" -eq 1 ] || ret=1
-grep 'corp/_default' rndc.out.ns4.test$n.1 >/dev/null || ret=1
-
-# cleanup
-rndccmd 10.53.0.4 nta -remove secure.example >rndc.out.ns4.test$n.3 2>/dev/null
-
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "testing 'rndc nta -d' displays validate-except entries"
-rndccmd 10.53.0.4 nta -d | grep ": permanent" >rndc.out.ns4.test$n.1 2>/dev/null
-lines=$(wc -l <rndc.out.ns4.test$n.1)
-[ "$lines" -eq 1 ] || ret=1
-grep 'corp/_default' rndc.out.ns4.test$n.1 >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking that NTAs work with 'forward only;' to a validating resolver ($n)"
-ret=0
-# Sanity check behavior without an NTA in place.
-dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.1 || ret=1
-grep "SERVFAIL" dig.out.ns9.test$n.1 >/dev/null || ret=1
-grep "ANSWER: 0" dig.out.ns9.test$n.1 >/dev/null || ret=1
-grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.1 >/dev/null && ret=1
-# Add an NTA, expecting that to cause resolution to succeed.
-rndccmd 10.53.0.9 nta badds.example >rndc.out.ns9.test$n.1 2>&1 || ret=1
-dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.2 || ret=1
-grep "NOERROR" dig.out.ns9.test$n.2 >/dev/null || ret=1
-grep "ANSWER: 2" dig.out.ns9.test$n.2 >/dev/null || ret=1
-grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.2 >/dev/null && ret=1
-# Remove the NTA, expecting that to cause resolution to fail again.
-rndccmd 10.53.0.9 nta -remove badds.example >rndc.out.ns9.test$n.2 2>&1 || ret=1
-dig_with_opts @10.53.0.9 badds.example. SOA >dig.out.ns9.test$n.3 || ret=1
-grep "SERVFAIL" dig.out.ns9.test$n.3 >/dev/null || ret=1
-grep "ANSWER: 0" dig.out.ns9.test$n.3 >/dev/null || ret=1
-grep "flags:[^;]* ad[ ;].*QUERY" dig.out.ns9.test$n.3 >/dev/null && ret=1
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "completed NTA tests"
-
# Run a minimal update test if possible. This is really just
# a regression test for RT #2399; more tests should be added.
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS1
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation yes;
+ /* test that we can turn off trust-anchor-telemetry */
+ trust-anchor-telemetry no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+include "trusted.conf";
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns2.example.
+ns2.example. A 10.53.0.2
--- /dev/null
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+(cd ../ns2 && $SHELL sign.sh)
+
+cp "../ns2/dsset-example." .
+
+ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+
+cat "$infile" "$ksk.key" "$zsk.key" >"$zonefile"
+
+"$SIGNER" -g -o "$zone" "$zonefile" >/dev/null 2>&1
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds "$ksk" >trusted.conf
+cp trusted.conf ../ns4/trusted.conf
+cp trusted.conf ../ns9/trusted.conf
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns2
+ NS ns3
+ns2 A 10.53.0.2
+ns3 A 10.53.0.3
+
+; A secure subdomain
+secure NS ns3.secure
+ns3.secure A 10.53.0.3
+
+; A secure subdomain we're going to inject bogus data into
+bogus NS ns.bogus
+ns.bogus A 10.53.0.3
+
+; A subdomain with a corrupt DS
+badds NS ns.badds
+ns.badds A 10.53.0.3
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS2
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ notify yes;
+ notify-delay 1;
+ dnssec-validation no;
+ minimal-responses no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type primary;
+ file "example.db.signed";
+ allow-update { any; };
+};
+
+zone "corp" {
+ type primary;
+ file "corp.db";
+};
--- /dev/null
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+# Sign child zones (served by ns3).
+(cd ../ns3 && $SHELL sign.sh)
+
+# The "example." zone.
+zone=example.
+infile=example.db.in
+zonefile=example.db
+
+# Get the DS records for the "example." zone.
+for subdomain in bogus badds secure; do
+ cp "../ns3/dsset-$subdomain.example." .
+done
+
+# Sign the "example." zone.
+keyname1=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" -f KSK "$zone")
+keyname2=$("$KEYGEN" -q -a "$ALTERNATIVE_ALGORITHM" -b "$ALTERNATIVE_BITS" "$zone")
+
+cat "$infile" "$keyname1.key" "$keyname2.key" >"$zonefile"
+
+"$SIGNER" -g -o "$zone" -k "$keyname1" "$zonefile" "$keyname2" >/dev/null 2>&1
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+d A 10.0.0.4
+z A 10.0.0.26
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS3
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ allow-transfer { any; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+ minimal-responses no;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example" {
+ type secondary;
+ primaries { 10.53.0.2; };
+ file "example.bk";
+};
+
+zone "secure.example" {
+ type primary;
+ file "secure.example.db.signed";
+ allow-update { any; };
+};
+
+zone "bogus.example" {
+ type primary;
+ file "bogus.example.db.signed";
+ allow-update { any; };
+};
+
+zone "badds.example" {
+ type primary;
+ file "badds.example.db.signed";
+ allow-update { any; };
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300 ; 5 minutes
+@ IN SOA mname1. . (
+ 2000042407 ; serial
+ 20 ; refresh (20 seconds)
+ 20 ; retry (20 seconds)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns3
+ns3 A 10.53.0.3
+
+a A 10.0.0.1
+b A 10.0.0.2
+c A 10.0.0.3
+d A 10.0.0.4
+e A 10.0.0.5
+f A 10.0.0.6
+g A 10.0.0.7
+z A 10.0.0.26
--- /dev/null
+#!/bin/sh -e
+
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+# a validly signed zone
+zone=secure.example.
+infile=secure.example.db.in
+zonefile=secure.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+
+cat "$infile" "$keyname.key" >"$zonefile"
+
+"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null
+cat "$zonefile" "$zonefile".signed >"$zonefile".tmp
+mv "$zonefile".tmp "$zonefile".signed
+
+# a zone that we'll add bogus data to
+zone=bogus.example.
+infile=bogus.example.db.in
+zonefile=bogus.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+
+cat "$infile" "$keyname.key" >"$zonefile"
+
+"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null
+
+{
+ echo "a.bogus.example. A 10.0.0.22"
+ echo "b.bogus.example. A 10.0.0.23"
+ echo "c.bogus.example. A 10.0.0.23"
+} >>bogus.example.db.signed
+
+#
+# A zone with a bad DS in the parent
+# (sourced from bogus.example.db.in)
+#
+zone=badds.example.
+infile=bogus.example.db.in
+zonefile=badds.example.db
+
+keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" "$zone")
+
+cat "$infile" "$keyname.key" >"$zonefile"
+
+"$SIGNER" -P -o "$zone" "$zonefile" >/dev/null
+sed -e 's/bogus/badds/g' <dsset-bogus.example. >dsset-badds.example.
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS4
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ minimal-responses no;
+
+ nta-lifetime 12s;
+ nta-recheck 9s;
+ validate-except { corp; };
+
+ dnssec-validation yes;
+};
+
+include "trusted.conf";
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "../../_common/root.hint";
+};
+
+zone "corp" {
+ type static-stub;
+ server-addresses { 10.53.0.2; };
+};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+// NS9
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ forward only;
+ forwarders { 10.53.0.4; };
+ servfail-ttl 0;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+include "trusted.conf";
-#!/usr/bin/perl -w
+#!/bin/sh -e
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
-use strict;
-use Time::Piece;
-use Time::Seconds;
+# shellcheck source=conf.sh
+. ../conf.sh
-exit 1 if (scalar(@ARGV) != 2);
+set -e
-my $actual = Time::Piece->strptime($ARGV[0], '%d-%b-%Y %H:%M:%S.000 %z');
-my $expected = Time::Piece->strptime($ARGV[1], '%s') + ONE_WEEK;
-my $diff = abs($actual - $expected);
-
-print($diff . "\n");
+(
+ cd ns1
+ $SHELL sign.sh
+)
--- /dev/null
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+import re
+import time
+
+import pytest
+
+import isctest
+
+
+# helper functions
+def hasmatch(regex, blob):
+ return re.search(regex, blob, flags=re.MULTILINE)
+
+
+def active(blob):
+ return len([x for x in blob.splitlines() if " expiry" in x])
+
+
+# global start-time variable
+# pylint: disable=global-statement
+# pylint: disable=global-variable-not-assigned
+start = 0
+
+
+def test_initial():
+ m = isctest.query.create("a.bogus.example.", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ m = isctest.query.create("badds.example.", "SOA")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ m = isctest.query.create("a.secure.example.", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+
+def test_nta_validate_except(servers):
+ ns4 = servers["ns4"]
+ response = ns4.rndc("secroots -", log=False)
+ assert hasmatch("^corp: permanent", response)
+
+ # check insecure local domain works with validate-except
+ m = isctest.query.create("www.corp", "NS")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+
+def test_nta_bogus_lifetimes(servers):
+ ns4 = servers["ns4"]
+
+ # no nta lifetime specified:
+ response = ns4.rndc("nta -l '' foo", ignore_errors=True, log=False)
+ assert "'nta' failed: bad ttl" in response
+
+ # bad nta lifetime:
+ response = ns4.rndc("nta -l garbage foo", ignore_errors=True, log=False)
+ assert "'nta' failed: bad ttl" in response
+
+ # excessive nta lifetime:
+ response = ns4.rndc("nta -l 7d1h foo", ignore_errors=True, log=False)
+ assert "'nta' failed: out of range" in response
+
+
+def test_nta_install(servers):
+ global start
+
+ ns4 = servers["ns4"]
+ ns4.rndc("nta -f -l 20s bogus.example", log=False)
+ ns4.rndc("nta badds.example", log=False)
+
+ # NTAs should persist after reconfig
+ with ns4.watch_log_from_here() as watcher:
+ ns4.reconfigure(log=False)
+ watcher.wait_for_line("any newly configured zones are now loaded")
+
+ response = ns4.rndc("nta -d", log=False)
+ assert len(response.splitlines()) == 3
+
+ ns4.rndc("nta secure.example", log=False)
+ ns4.rndc("nta fakenode.secure.example", log=False)
+ with ns4.watch_log_from_here() as watcher:
+ ns4.rndc("reload", log=False)
+ watcher.wait_for_line("all zones loaded")
+
+ response = ns4.rndc("nta -d", log=False)
+ assert len(response.splitlines()) == 5
+
+ start = time.time()
+
+
+def test_nta_behavior(servers):
+ global start
+ assert start, "test_nta_behavior must be run as part of the full NTA test"
+
+ m = isctest.query.create("a.bogus.example.", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ m = isctest.query.create("badds.example.", "SOA")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ m = isctest.query.create("a.secure.example.", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ m = isctest.query.create("a.fakenode.secure.example.", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noadflag(res)
+
+ ns4 = servers["ns4"]
+ response = ns4.rndc("secroots -", log=False)
+ assert hasmatch("^bogus.example: expiry", response)
+ assert hasmatch("^badds.example: expiry", response)
+ assert hasmatch("^secure.example: expiry", response)
+ assert hasmatch("^fakenode.secure.example: expiry", response)
+
+ # secure.example and badds.example used the default nta-duration
+ # (configured as 12s in ns4/named1.conf), but the nta recheck interval
+ # is configured to 9s, so at t=10 the NTAs for secure.example and
+ # fakenode.secure.example should both be lifted, while badds.example
+ # should still be going.
+ delay = start + 10 - time.time()
+ if delay > 0:
+ time.sleep(delay)
+
+ m = isctest.query.create("b.secure.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ m = isctest.query.create("b.fakenode.secure.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.nxdomain(res)
+ isctest.check.adflag(res)
+
+ m = isctest.query.create("badds.example.", "SOA")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ # bogus.example was set to expire in 20s, so at t=13
+ # it should still be NTA'd, but badds.example used the default
+ # lifetime of 12s, so it should revert to SERVFAIL now.
+ delay = start + 13 - time.time()
+ if delay > 0:
+ time.sleep(delay)
+
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) <= 2
+
+ response = ns4.rndc("secroots -", log=False)
+ assert hasmatch("bogus.example: expiry", response)
+ assert not hasmatch("badds.example: expiry", response)
+
+ m = isctest.query.create("b.bogus.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+
+ m = isctest.query.create("a.badds.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.servfail(res)
+ isctest.check.noadflag(res)
+
+ m = isctest.query.create("c.secure.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ # at t=21, all the NTAs should have expired.
+ delay = start + 21 - time.time()
+ if delay > 0:
+ time.sleep(delay)
+
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 0
+
+ m = isctest.query.create("d.secure.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ m = isctest.query.create("c.bogus.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.servfail(res)
+ isctest.check.noadflag(res)
+
+
+def test_nta_removals(servers):
+ ns4 = servers["ns4"]
+ ns4.rndc("nta badds.example", log=False)
+
+ response = ns4.rndc("nta -d", log=False)
+ assert hasmatch("^badds.example/_default: expiry", response)
+
+ m = isctest.query.create("a.badds.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ response = ns4.rndc("nta -remove badds.example", log=False)
+ assert "Negative trust anchor removed: badds.example" in response
+
+ response = ns4.rndc("nta -d", log=False)
+ assert not hasmatch("^badds.example/_default: expiry", response)
+
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.servfail(res)
+ isctest.check.noadflag(res)
+
+ # remove non-existent NTA three times
+ ns4.rndc("nta -r foo", log=False)
+ ns4.rndc("nta -remove foo", log=False)
+ response = ns4.rndc("nta -r foo", log=False)
+ assert "not found" in response
+
+
+def test_nta_restarts(servers):
+ global start
+ assert start, "test_nta_restarts must be run as part of the full NTA test"
+
+ # test NTA persistence across restarts
+ ns4 = servers["ns4"]
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 0
+
+ start = time.time()
+ ns4.rndc("nta -f -l 30s bogus.example", log=False)
+ ns4.rndc("nta -f -l 10s badds.example", log=False)
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 2
+
+ # stop the server
+ ns4.stop()
+
+ # wait 14s before restarting. badds.example's NTA (lifetime=10s) should
+ # have expired, and bogus.example should still be running.
+ delay = start + 14 - time.time()
+ if delay > 0:
+ time.sleep(delay)
+ ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]])
+
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 1
+ assert hasmatch("^bogus.example/_default: expiry", response)
+
+ m = isctest.query.create("a.badds.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ m = isctest.query.create("a.bogus.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ ns4.rndc("nta -r bogus.example", log=False)
+
+
+def test_nta_regular(servers):
+ global start
+ assert start, "test_nta_regular must be run as part of the full NTA test"
+
+ # check "regular" attribute in NTA file
+ ns4 = servers["ns4"]
+
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 0
+
+ # secure.example validates with AD=1
+ m = isctest.query.create("a.secure.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ # stop the server, update _default.nta, restart
+ ns4.stop()
+ now = time.localtime()
+ future = str(now.tm_year + 20) + "0101010000"
+ with open("ns4/_default.nta", "w", encoding="utf-8") as f:
+ f.write(f"secure.example. regular {future}")
+
+ ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]])
+
+ # NTA active; secure.example. should now return an AD=0 answer.
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ # nta-recheck is configured as 9s, so at t=12 the NTA for
+ # secure.example. should be lifted as it is not a "forced" NTA.
+ start = time.mktime(now)
+ delay = start + 12 - time.time()
+ if delay > 0:
+ time.sleep(delay)
+
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 0
+
+ # NTA lifted; secure.example. flush the cache to trigger a new query,
+ # and it should now return an AD=1 answer.
+ ns4.rndc("flushtree secure.example", log=False)
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+
+def test_nta_forced(servers):
+ global start
+ assert start, "test_nta_regular must be run as part of the full NTA test"
+
+ # check "forced" attribute in NTA file
+ ns4 = servers["ns4"]
+
+ # just to be certain, clean up any existing NTA first
+ ns4.rndc("nta -r secure.example", log=False)
+
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 0
+
+ # secure.example validates with AD=1
+ m = isctest.query.create("a.secure.example", "A")
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ # stop the server, update _default.nta, restart
+ ns4.stop()
+ now = time.localtime()
+ future = str(now.tm_year + 20) + "0101010000"
+ with open("ns4/_default.nta", "w", encoding="utf-8") as f:
+ f.write(f"secure.example. forced {future}")
+
+ ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]])
+
+ # NTA active; secure.example. should now return an AD=0 answer
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+ # nta-recheck is configured as 9s. at t=12 the NTA for
+ # secure.example. should NOT be lifted as it is "forced".
+ start = time.mktime(now)
+ delay = start + 12 - time.time()
+ if delay > 0:
+ time.sleep(delay)
+
+ # NTA lifted; secure.example. should still return an AD=0 answer
+ ns4.rndc("flushtree secure.example", log=False)
+ res = isctest.query.tcp(m, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+
+
+def test_nta_clamping(servers):
+ ns4 = servers["ns4"]
+
+ # clean up any existing NTA
+ ns4.rndc("nta -r secure.example", log=False)
+
+ # stop the server, update _default.nta, restart
+ ns4.stop()
+ now = time.localtime()
+ future = str(now.tm_year + 20) + "0101010000"
+ with open("ns4/_default.nta", "w", encoding="utf-8") as f:
+ f.write(f"secure.example. forced {future}")
+
+ ns4.start(["--noclean", "--restart", "--port", os.environ["PORT"]])
+
+ # check that NTA lifetime read from file is clamped to 1 week.
+ response = ns4.rndc("nta -d", log=False)
+ assert active(response) == 1
+
+ nta = next((s for s in response.splitlines() if " expiry" in s), None)
+ assert nta is not None
+
+ nta = nta.split(" ")
+ expiry = f"{nta[2]} {nta[3]}"
+ then = time.mktime(time.strptime(expiry, "%d-%b-%Y %H:%M:%S.000"))
+ nextweek = time.mktime(now) + (86400 * 7)
+
+ # normally there's no more than a few seconds difference between the
+ # clamped expiration date and the calculated date for next week,
+ # but add a 3600 second fudge factor to allow for daylight savings
+ # changes.
+ assert abs(nextweek - then < 3610)
+
+ # remove the NTA
+ ns4.rndc("nta -r secure.example", log=False)
+
+
+def test_nta_forward(servers):
+ ns9 = servers["ns9"]
+
+ m = isctest.query.create("badds.example", "SOA")
+ res = isctest.query.tcp(m, "10.53.0.9")
+ isctest.check.servfail(res)
+ isctest.check.empty_answer(res)
+ isctest.check.noadflag(res)
+
+ # add NTA and expect resolution to succeed
+ ns9.rndc("nta badds.example", log=False)
+ res = isctest.query.tcp(m, "10.53.0.9")
+ isctest.check.noerror(res)
+ isctest.check.rr_count_eq(res.answer, 2)
+ isctest.check.noadflag(res)
+
+ # remove NTA and expect resolution to fail again
+ ns9.rndc("nta -remove badds.example", log=False)
+ res = isctest.query.tcp(m, "10.53.0.9")
+ isctest.check.servfail(res)
+ isctest.check.empty_answer(res)
+ isctest.check.noadflag(res)