return 1
}
-#
-# Ensure there is not multiple consecutive blank lines.
-# Ensure there is a blank line before "Start view" and
-# "Negative trust anchors:".
-# Ensure there is not a blank line before "Secure roots:".
-#
-check_secroots_layout() {
- awk '$0 == "" { if (empty) exit(1); empty=1; next }
- /Start view/ { if (!empty) exit(1) }
- /Secure roots:/ { if (empty) exit(1) }
- /Negative trust anchors:/ { if (!empty) exit(1) }
- { empty=0 }' $1 || return $?
-}
-
-# Check that for a query against a validating resolver where the
-# authoritative zone is unsigned (insecure delegation), glue is returned
-# in the additional section
-echo_i "checking that additional glue is returned for unsigned delegation ($n)"
-ret=0
-$DIG +tcp +dnssec -p "$PORT" a.insecure.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-grep "ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ns\\.insecure\\.example\\..*A.10\\.53\\.0\\.3" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-# Check the example. domain
-
-echo_i "checking that zone transfer worked ($n)"
-for i in 1 2 3 4 5 6 7 8 9; do
- ret=0
- dig_with_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
- dig_with_opts a.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
- $PERL ../digcomp.pl dig.out.ns2.test$n dig.out.ns3.test$n >/dev/null || ret=1
- [ "$ret" -eq 0 ] && break
- sleep 1
-done
-digcomp dig.out.ns2.test$n dig.out.ns3.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# test AD bit:
-# - dig +adflag asks for authentication (ad in response)
-echo_i "checking AD bit asking for validation ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth +noadd +nodnssec +adflag a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# test AD bit:
-# - dig +noadflag
-echo_i "checking that AD is not set without +adflag or +dnssec ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth +noadd +nodnssec +noadflag a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 for AD in authoritative answer ($n)"
-ret=0
-dig_with_opts a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns2.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking positive validation NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 recovery from spoofed server addresses ($n)"
-ret=0
-# prime cache with spoofed address records
-dig_with_opts +cd target.peer-ns-spoof @10.53.0.4 a >dig.out.prime.ns4.test$n || ret=1
-grep "status: SERVFAIL" dig.out.prime.ns4.test$n >/dev/null || ret=1
-rndccmd 10.53.0.4 dumpdb | sed 's/^/ns4 /' | cat_i
-mv ns4/named_dump.db ns4/named_dump.db.test$n >/dev/null || ret=1
-grep "10.53.0.100" ns4/named_dump.db.test$n || ret=1
-# reload server with properly signed zone
-cp ns2/peer.peer-ns-spoof.db.next ns2/peer.peer-ns-spoof.db.signed
-nextpart ns2/named.run >/dev/null
-rndccmd 10.53.0.2 reload peer.peer-ns-spoof | sed 's/^/ns2 /' | cat_i
-wait_for_log 5 "zone peer.peer-ns-spoof/IN: loaded serial 2000042408" ns2/named.run || ret=1
-dig_with_opts +noauth test.target.peer-ns-spoof @10.53.0.4 txt >dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags: qr rd ra 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 recovery from stripped DNSKEY RRSIG ($n)"
-ret=0
-# prime cache with DNSKEY without RRSIGs
-dig_with_opts +noauth +cd dnskey-rrsigs-stripped. @10.53.0.4 dnskey >dig.out.prime.ns4.test$n || ret=1
-grep ";; flags: qr rd ra cd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1" dig.out.prime.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1
-grep "RRSIG.DNSKEY" dig.out.prime.ns4.test$n >/dev/null && ret=1
-# reload server with properly signed zone
-cp ns2/dnskey-rrsigs-stripped.db.next ns2/dnskey-rrsigs-stripped.db.signed
-nextpart ns2/named.run >/dev/null
-rndccmd 10.53.0.2 reload dnskey-rrsigs-stripped | sed 's/^/ns2 /' | cat_i
-wait_for_log 5 "zone dnskey-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1
-dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth b.dnskey-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 recovery from stripped DS RRSIG ($n)"
-ret=0
-# prime cache with DS without RRSIGs
-dig_with_opts +noauth +cd child.ds-rrsigs-stripped. @10.53.0.4 ds >dig.out.prime.ns4.test$n || ret=1
-grep ";; flags: qr rd ra cd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.prime.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1
-grep "RRSIG.DS" dig.out.prime.ns4.test$n >/dev/null && ret=1
-# reload server with properly signed zone
-cp ns2/ds-rrsigs-stripped.db.next ns2/ds-rrsigs-stripped.db.signed
-nextpart ns2/named.run >/dev/null
-rndccmd 10.53.0.2 reload ds-rrsigs-stripped | sed 's/^/ns2 /' | cat_i
-wait_for_log 5 "zone ds-rrsigs-stripped/IN: loaded serial 2000042408" ns2/named.run || ret=1
-dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth b.child.ds-rrsigs-stripped. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 that 'example/DS' from the referral was used in previous validation ($n)"
-ret=0
-grep "query 'example/DS/IN' approved" ns1/named.run >/dev/null && ret=1
-grep "fetch: example/DS" ns4/named.run >/dev/null && ret=1
-grep "validating example/DS: starting" ns4/named.run >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
if [ -x "${DELV}" ]; then
ret=0
echo_i "checking positive validation NSEC using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.example >delv.out$n || ret=1
grep "a.example..*10.0.0.1" delv.out$n >/dev/null || ret=1
- grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n >/dev/null || ret=1
+ grep "a.example..*.RRSIG.A [0-9][0-9]* 2 3600 .*" delv.out$n >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
echo_i "checking positive validation NSEC using dns_client (trusted-keys) ($n)"
"$DELV" -a ns1/trusted.keys -p "$PORT" @10.53.0.4 a a.example >delv.out$n || ret=1
grep "a.example..*10.0.0.1" delv.out$n >/dev/null || ret=1
- grep "a.example..*.RRSIG.A [0-9][0-9]* 2 300 .*" delv.out$n >/dev/null || ret=1
+ grep "a.example..*.RRSIG.A [0-9][0-9]* 2 3600 .*" delv.out$n >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking positive validation NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking positive validation NSEC3 using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.nsec3.example >delv.out$n || ret=1
grep "a.nsec3.example..*10.0.0.1" delv.out$n >/dev/null || ret=1
- grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1
+ grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300 .*" delv.out$n >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking positive validation OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-SP="[[:space:]]+"
+ SP="[[:space:]]+"
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking positive validation OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.optout.example >delv.out$n || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-echo_i "checking positive wildcard validation NSEC ($n)"
-ret=0
-dig_with_opts a.wild.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts a.wild.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n
-stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n
-digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
-grep "\\*\\.wild\\.example\\..*RRSIG NSEC" dig.out.ns4.test$n >/dev/null || ret=1
-grep "\\*\\.wild\\.example\\..*NSEC z\\.example" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking positive wildcard validation NSEC using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.wild.example >delv.out$n || ret=1
grep "a.wild.example..*10.0.0.27" delv.out$n >/dev/null || ret=1
- grep -E "a.wild.example..*RRSIG.A [0-9]+ 2 300.*" delv.out$n >/dev/null || ret=1
+ grep -E "a.wild.example..*RRSIG.A [0-9]+ 2 3600 .*" delv.out$n >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking positive wildcard answer NSEC3 ($n)"
-ret=0
-dig_with_opts a.wild.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-grep "AUTHORITY: 4," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking positive wildcard answer NSEC3 ($n)"
-ret=0
-dig_with_opts a.wild.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-grep "AUTHORITY: 4," dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" 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 wildcard validation NSEC3 ($n)"
-ret=0
-dig_with_opts a.wild.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts a.wild.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n
-stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n
-digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking positive wildcard validation NSEC3 using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.wild.nsec3.example >delv.out$n || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-echo_i "checking positive wildcard validation OPTOUT ($n)"
-ret=0
-dig_with_opts a.wild.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts a.wild.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-stripns dig.out.ns3.test$n >dig.out.ns3.stripped.test$n
-stripns dig.out.ns4.test$n >dig.out.ns4.stripped.test$n
-digcomp dig.out.ns3.stripped.test$n dig.out.ns4.stripped.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking positive wildcard validation OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.wild.optout.example >delv.out$n || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking negative validation NXDOMAIN NSEC ($n)"
-ret=0
-dig_with_opts +noauth q.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth q.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative validation NXDOMAIN NSEC using dns_client ($n)"
delv_with_opts @10.53.0.4 a q.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking RRSIG covered type in negative cache entry ($n)"
-ret=0
-rndc_dumpdb ns4
-grep -F '; example. RRSIG NSEC ...' ns4/named_dump.db.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking negative validation NXDOMAIN NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth q.nsec3.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth q.nsec3.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative validation NXDOMAIN NSEC3 using dns_client ($n)"
delv_with_opts @10.53.0.4 a q.nsec3.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking negative validation NXDOMAIN OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth q.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth q.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative validation NXDOMAIN OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 a q.optout.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking negative validation NODATA NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth a.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 txt a.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-echo_i "checking negative validation NODATA NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.3 txt >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.4 txt >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative validation NODATA NSEC3 using dns_client ($n)"
delv_with_opts @10.53.0.4 txt a.nsec3.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking negative validation NODATA OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.3 txt >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.4 txt >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 0" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative validation NODATA OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 txt a.optout.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking negative wildcard validation NSEC ($n)"
-ret=0
-dig_with_opts b.wild.example. @10.53.0.2 txt >dig.out.ns2.test$n || ret=1
-dig_with_opts b.wild.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative wildcard validation NSEC using dns_client ($n)"
delv_with_opts @10.53.0.4 txt b.wild.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking negative wildcard validation NSEC3 ($n)"
-ret=0
-dig_with_opts b.wild.nsec3.example. @10.53.0.3 txt >dig.out.ns3.test$n || ret=1
-dig_with_opts b.wild.nsec3.example. @10.53.0.4 txt >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative wildcard validation NSEC3 using dns_client ($n)"
delv_with_opts @10.53.0.4 txt b.wild.nsec3.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking negative wildcard validation OPTOUT ($n)"
-ret=0
-dig_with_opts b.wild.optout.example. \
- @10.53.0.3 txt >dig.out.ns3.test$n || ret=1
-dig_with_opts b.wild.optout.example. \
- @10.53.0.4 txt >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking negative wildcard validation OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 txt b.optout.nsec3.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-# Check the insecure.example domain
-
-echo_i "checking 1-server insecurity proof NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.insecure.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.insecure.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking 1-server insecurity proof NSEC using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.insecure.example >delv.out$n || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking 1-server insecurity proof NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.insecure.nsec3.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking 1-server insecurity proof NSEC3 using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.insecure.nsec3.example >delv.out$n || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking 1-server insecurity proof OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth a.insecure.optout.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.insecure.optout.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking 1-server insecurity proof OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 a a.insecure.optout.example >delv.out$n || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking 1-server negative insecurity proof NSEC ($n)"
-ret=0
-dig_with_opts q.insecure.example. a @10.53.0.3 \
- >dig.out.ns3.test$n || ret=1
-dig_with_opts q.insecure.example. a @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking 1-server negative insecurity proof NSEC using dns_client ($n)"
delv_with_opts @10.53.0.4 a q.insecure.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-echo_i "checking 1-server negative insecurity proof NSEC3 ($n)"
-ret=0
-dig_with_opts q.insecure.nsec3.example. a @10.53.0.3 \
- >dig.out.ns3.test$n || ret=1
-dig_with_opts q.insecure.nsec3.example. a @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking 1-server negative insecurity proof NSEC3 using dns_client ($n)"
delv_with_opts @10.53.0.4 a q.insecure.nsec3.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking 1-server negative insecurity proof OPTOUT ($n)"
-ret=0
-dig_with_opts q.insecure.optout.example. a @10.53.0.3 \
- >dig.out.ns3.test$n || ret=1
-dig_with_opts q.insecure.optout.example. a @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-if [ -x "${DELV}" ]; then
ret=0
echo_i "checking 1-server negative insecurity proof OPTOUT using dns_client ($n)"
delv_with_opts @10.53.0.4 a q.insecure.optout.example >delv.out$n 2>&1 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-fi
-
-echo_i "checking 1-server negative insecurity proof with SOA hack NSEC ($n)"
-ret=0
-dig_with_opts r.insecure.example. soa @10.53.0.3 \
- >dig.out.ns3.test$n || ret=1
-dig_with_opts r.insecure.example. soa @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" 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 1-server negative insecurity proof with SOA hack NSEC3 ($n)"
-ret=0
-dig_with_opts r.insecure.nsec3.example. soa @10.53.0.3 \
- >dig.out.ns3.test$n || ret=1
-dig_with_opts r.insecure.nsec3.example. soa @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
+ ret=0
+ echo_i "checking failed validation using dns_client ($n)"
+ delv_with_opts +cd @10.53.0.4 a a.bogus.example >delv.out$n 2>&1 || ret=1
+ grep "resolution failed: RRSIG failed to verify" delv.out$n >/dev/null || ret=1
+ n=$((n + 1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status + ret))
-echo_i "checking 1-server negative insecurity proof with SOA hack OPTOUT ($n)"
-ret=0
-dig_with_opts r.insecure.optout.example. soa @10.53.0.3 \
- >dig.out.ns3.test$n || ret=1
-dig_with_opts r.insecure.optout.example. soa @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-grep "0 IN SOA" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
+ ret=0
+ echo_i "checking that validation fails when key record is missing using dns_client ($n)"
+ delv_with_opts +cd @10.53.0.4 a a.b.keyless.example >delv.out$n 2>&1 || ret=1
+ grep "resolution failed: insecurity proof failed" delv.out$n >/dev/null || ret=1
+ n=$((n + 1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status + ret))
-# Check the secure.example domain
+ ret=0
+ echo_i "checking that validation succeeds when a revoked key is encountered using dns_client ($n)"
+ delv_with_opts +cd @10.53.0.4 soa revkey.example >delv.out$n 2>&1 || ret=1
+ grep "fully validated" delv.out$n >/dev/null || ret=1
+ n=$((n + 1))
+ test "$ret" -eq 0 || echo_i "failed"
+ status=$((status + ret))
+fi
-echo_i "checking multi-stage positive validation NSEC/NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.secure.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.secure.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 mixed-case positive validation ($n)"
-ret=0
-for type in a txt aaaa loc; do
- dig_with_opts +noauth mixedcase.secure.example. \
- @10.53.0.3 $type >dig.out.$type.ns3.test$n || ret=1
- dig_with_opts +noauth mixedcase.secure.example. \
- @10.53.0.4 $type >dig.out.$type.ns4.test$n || ret=1
- digcomp --lc dig.out.$type.ns3.test$n dig.out.$type.ns4.test$n || ret=1
- grep "status: NOERROR" dig.out.$type.ns4.test$n >/dev/null || ret=1
- grep "flags:.*ad.*QUERY" dig.out.$type.ns4.test$n >/dev/null || ret=1
-done
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 multi-stage positive validation NSEC/OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 multi-stage positive validation NSEC3/NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.secure.nsec3.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.secure.nsec3.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 multi-stage positive validation NSEC3/NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth a.nsec3.nsec3.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.nsec3.nsec3.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 multi-stage positive validation NSEC3/OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth a.optout.nsec3.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.optout.nsec3.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 multi-stage positive validation OPTOUT/NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.secure.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.secure.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 multi-stage positive validation OPTOUT/NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth a.nsec3.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.nsec3.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 multi-stage positive validation OPTOUT/OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth a.optout.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.optout.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 empty NODATA OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth empty.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth empty.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-#grep "flags:.*ad.*QUERY" 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 validation with private algorithm works ($n)"
-ret=0
-dig_with_opts +noauth a.rsasha256oid.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.rsasha256oid.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if [ -x "${DELV}" ]; then
- ret=0
- echo_i "checking positive validation NSEC3 using dns_client ($n)"
- delv_with_opts @10.53.0.4 a a.nsec3.example >delv.out$n || ret=1
- grep "a.nsec3.example..*10.0.0.1" delv.out$n >/dev/null || ret=1
- grep "a.nsec3.example..*RRSIG.A [0-9][0-9]* 3 300.*" delv.out$n >/dev/null || ret=1
- n=$((n + 1))
- test "$ret" -eq 0 || echo_i "failed"
- status=$((status + ret))
-fi
-
-echo_i "checking positive validation with unknown private algorithm works ($n)"
-ret=0
-dig_with_opts +noauth a.unknownoid.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.unknownoid.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 validation with extra ds for private algorithm ($n)"
-ret=0
-dig_with_opts +noauth a.extradsoid.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.extradsoid.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 validation with extra ds for unknown private algorithm fails ($n)"
-ret=0
-dig_with_opts +noauth a.extradsunknownoid.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.extradsunknownoid.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
-grep 'No DNSKEY for extradsunknownoid.example/DS with PRIVATEOID algorithm, tag [1-9][0-9]*$' ns4/named.run >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if $FEATURETEST --extended-ds-digest; then
- echo_i "checking positive validation with extra ds using extended digest type for unknown private algorithm succeeds ($n)"
- ret=0
- dig_with_opts +noauth a.extended-ds-unknown-oid.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
- dig_with_opts +noauth a.extended-ds-unknown-oid.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
- digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
- grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
- n=$((n + 1))
- test "$ret" -eq 0 || echo_i "failed"
- status=$((status + ret))
-fi
-
-# Check the bogus domain
-
-echo_i "checking failed validation ($n)"
-ret=0
-dig_with_opts a.bogus.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if [ -x "${DELV}" ]; then
- ret=0
- echo_i "checking failed validation using dns_client ($n)"
- delv_with_opts +cd @10.53.0.4 a a.bogus.example >delv.out$n 2>&1 || ret=1
- grep "resolution failed: RRSIG failed to verify" delv.out$n >/dev/null || ret=1
- n=$((n + 1))
- test "$ret" -eq 0 || echo_i "failed"
- status=$((status + ret))
-fi
-
-echo_i "checking that validation fails when key record is missing ($n)"
-ret=0
-dig_with_opts a.b.keyless.example. a @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-if [ -x "${DELV}" ]; then
- ret=0
- echo_i "checking that validation fails when key record is missing using dns_client ($n)"
- delv_with_opts +cd @10.53.0.4 a a.b.keyless.example >delv.out$n 2>&1 || ret=1
- grep "resolution failed: insecurity proof failed" delv.out$n >/dev/null || ret=1
- n=$((n + 1))
- test "$ret" -eq 0 || echo_i "failed"
- status=$((status + ret))
-fi
-
-echo_i "checking that validation succeeds when a revoked key is encountered ($n)"
-ret=0
-dig_with_opts revkey.example soa @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))
-
-if [ -x "${DELV}" ]; then
- ret=0
- echo_i "checking that validation succeeds when a revoked key is encountered using dns_client ($n)"
- delv_with_opts +cd @10.53.0.4 soa revkey.example >delv.out$n 2>&1 || ret=1
- grep "fully validated" delv.out$n >/dev/null || ret=1
- n=$((n + 1))
- test "$ret" -eq 0 || echo_i "failed"
- status=$((status + ret))
-fi
-
-echo_i "Checking that a bad CNAME signature is caught after a +CD query ($n)"
-ret=0
-#prime
-dig_with_opts +cd bad-cname.example. @10.53.0.4 >dig.out.ns4.prime$n || ret=1
-#check: requery with +CD. pending data should be returned even if it's bogus
-expect="a.example.
-10.0.0.1"
-ans=$(dig_with_opts +cd +nodnssec +short bad-cname.example. @10.53.0.4) || ret=1
-test "$ans" = "$expect" || ret=1
-test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'"
-#check: requery without +CD. bogus cached data should be rejected.
-dig_with_opts +nodnssec bad-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "SERVFAIL" 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 that a bad DNAME signature is caught after a +CD query ($n)"
-ret=0
-#prime
-dig_with_opts +cd a.bad-dname.example. @10.53.0.4 >dig.out.ns4.prime$n || ret=1
-#check: requery with +CD. pending data should be returned even if it's bogus
-expect="example.
-a.example.
-10.0.0.1"
-ans=$(dig_with_opts +cd +nodnssec +short a.bad-dname.example. @10.53.0.4) || ret=1
-test "$ans" = "$expect" || ret=1
-test "$ret" -eq 0 || echo_i "failed, got '$ans', expected '$expect'"
-#check: requery without +CD. bogus cached data should be rejected.
-dig_with_opts +nodnssec a.bad-dname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check the insecure.secure.example domain (insecurity proof)
-
-echo_i "checking 2-server insecurity proof ($n)"
-ret=0
-dig_with_opts +noauth a.insecure.secure.example. @10.53.0.2 a \
- >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth a.insecure.secure.example. @10.53.0.4 a \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check a negative response in insecure.secure.example
-
-echo_i "checking 2-server insecurity proof with a negative answer ($n)"
-ret=0
-dig_with_opts q.insecure.secure.example. @10.53.0.2 a >dig.out.ns2.test$n \
- || ret=1
-dig_with_opts q.insecure.secure.example. @10.53.0.4 a >dig.out.ns4.test$n \
- || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" 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 2-server insecurity proof with a negative answer and SOA hack ($n)"
-ret=0
-dig_with_opts r.insecure.secure.example. @10.53.0.2 soa >dig.out.ns2.test$n \
- || ret=1
-dig_with_opts r.insecure.secure.example. @10.53.0.4 soa >dig.out.ns4.test$n \
- || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check that the query for a security root is successful and has ad set
-
-echo_i "checking security root query ($n)"
-ret=0
-dig_with_opts . @10.53.0.4 key >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 insecurity proof works using negative cache ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-dig_with_opts +cd @10.53.0.4 insecure.example. ds >dig.out.ns4.test$n.1 || ret=1
-for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18; do
- dig_with_opts @10.53.0.4 nonexistent.insecure.example. >dig.out.ns4.test$n.2 || ret=1
- if grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null; then
- break
- fi
- sleep 1
-done
-grep "status: NXDOMAIN" dig.out.ns4.test$n.2 >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Should work with FIPS mode as we are only validating
-echo_i "checking positive validation RSASHA1 NSEC ($n)"
-ret=0
-if $FEATURETEST --rsasha1; then
- dig_with_opts +noauth a.rsasha1.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
- dig_with_opts +noauth a.rsasha1.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
- digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
- grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-else
- echo_i "skip: RSASHA1 not supported by OS"
-fi
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Should work with FIPS mode as we are only validating
-echo_i "checking positive validation RSASHA1 (1024 bits) NSEC ($n)"
-ret=0
-if $FEATURETEST --rsasha1; then
- dig_with_opts +noauth a.rsasha1-1024.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
- dig_with_opts +noauth a.rsasha1-1024.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
- digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
- grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-else
- echo_i "skip: RSASHA1 not supported by OS"
-fi
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking positive validation RSASHA256 NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.rsasha256.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.rsasha256.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 validation RSASHA512 NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.rsasha512.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.rsasha512.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 validation with KSK-only DNSKEY signature ($n)"
-ret=0
-dig_with_opts +noauth a.kskonly.example. @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.kskonly.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 that validation of an ANY query works ($n)"
-ret=0
-dig_with_opts +noauth foo.example. any @10.53.0.2 >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth foo.example. any @10.53.0.4 >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# 2 records in the zone, 1 NXT, 3 SIGs
-grep "ANSWER: 6" 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 that validation of a query returning a CNAME works ($n)"
-ret=0
-dig_with_opts +noauth cname1.example. txt @10.53.0.2 \
- >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth cname1.example. txt @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# the CNAME & its sig, the TXT and its SIG
-grep "ANSWER: 4" 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 that validation of a query returning a DNAME works ($n)"
-ret=0
-dig_with_opts +noauth foo.dname1.example. txt @10.53.0.2 \
- >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth foo.dname1.example. txt @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# The DNAME & its sig, the TXT and its SIG, and the synthesized CNAME.
-# It would be nice to test that the CNAME is being synthesized by the
-# recursive server and not cached, but I don't know how.
-grep "ANSWER: 5" 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 that validation of an ANY query returning a CNAME works ($n)"
-ret=0
-dig_with_opts +noauth cname2.example. any @10.53.0.2 \
- >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth cname2.example. any @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-# The CNAME, NXT, and their SIGs
-grep "ANSWER: 4" 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 that validation of an ANY query returning a DNAME works ($n)"
-ret=0
-dig_with_opts +noauth foo.dname2.example. any @10.53.0.2 \
- >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth foo.dname2.example. any @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "NOERROR" 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 that lookups succeed after disabling an algorithm ($n)"
-ret=0
-dig_with_opts +noauth example. SOA @10.53.0.2 \
- >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth example. SOA @10.53.0.6 \
- >dig.out.ns6.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
-# Note - this is looking for failure, hence the &&
-grep "flags:.*ad.*QUERY" dig.out.ns6.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking a non-cachable NODATA works ($n)"
-ret=0
-dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.7 \
- >dig.out.ns7.test$n || ret=1
-grep "AUTHORITY: 0" dig.out.ns7.test$n >/dev/null || ret=1
-dig_with_opts +noauth a.nosoa.secure.example. txt @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" 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 a non-cachable NXDOMAIN works ($n)"
-ret=0
-dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.7 \
- >dig.out.ns7.test$n || ret=1
-grep "AUTHORITY: 0" dig.out.ns7.test$n >/dev/null || ret=1
-dig_with_opts +noauth b.nosoa.secure.example. txt @10.53.0.4 \
- >dig.out.ns4.test$n || ret=1
-grep "status: NXDOMAIN" 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 that we can load a rfc2535 signed zone ($n)"
-ret=0
-dig_with_opts rfc2535.example. SOA @10.53.0.2 \
- >dig.out.ns2.test$n || ret=1
-grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that we can transfer a rfc2535 signed zone ($n)"
-ret=0
-dig_with_opts rfc2535.example. SOA @10.53.0.3 \
- >dig.out.ns3.test$n || ret=1
-grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Test that "rndc secroots" is able to dump trusted keys
-echo_i "checking rndc secroots ($n)"
-ret=0
-keyid=$(cat ns1/managed.key.id)
-rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
-cp ns4/named.secroots named.secroots.test$n
-check_secroots_layout named.secroots.test$n || ret=1
-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 9 ] || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check direct query for RRSIG. If we first ask for normal (non RRSIG)
-# record, the corresponding RRSIG should be cached and subsequent query
-# for RRSIG will be returned with the cached record.
-echo_i "checking RRSIG query from cache ($n)"
-ret=0
-dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 a >/dev/null || ret=1
-ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1
-expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep -E '^(A|NSEC)') || ret=1
-test "$ans" = "$expect" || ret=1
-# also check that RA is set
-dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1
-grep "flags:.*ra.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check direct query for RRSIG: If it's not cached with other records,
-# it should result in an empty response.
-echo_i "checking RRSIG query not in cache ($n)"
-ret=0
-ans=$(dig_with_opts +short rrsigonly.secure.example. @10.53.0.4 rrsig) || ret=1
-test -z "$ans" || ret=1
-# also check that RA is cleared
-dig_with_opts rrsigonly.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1
-grep "flags:.*ra.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-#
-# RT21868 regression test.
-#
-echo_i "checking NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters ($n)"
-ret=0
-dig_with_opts non-exist.badparam. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-#
-# RT22007 regression test.
-#
-echo_i "checking optout NSEC3 referral with only insecure delegations ($n)"
-ret=0
-dig_with_opts +norec delegation.single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1
-grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking optout NSEC3 NXDOMAIN with only insecure delegations ($n)"
-ret=0
-dig_with_opts +norec nonexist.single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-grep "status: NXDOMAIN" dig.out.ns2.test$n >/dev/null || ret=1
-grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-
-status=$((status + ret))
-echo_i "checking optout NSEC3 nodata with only insecure delegations ($n)"
-ret=0
-dig_with_opts +norec single-nsec3. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1
-grep "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN.*NSEC3 1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" dig.out.ns2.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that a zone finishing the transition from $ALTERNATIVE_ALGORITHM to $DEFAULT_ALGORITHM validates secure ($n)"
-ret=0
-dig_with_opts ns algroll. @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))
-
-# Run a minimal update test if possible. This is really just
-# a regression test for RT #2399; more tests should be added.
+# Run a minimal update test if possible. This is really just
+# a regression test for RT #2399; more tests should be added.
if $PERL -e 'use Net::DNS;' 2>/dev/null; then
echo_i "running DNSSEC update test"
echo_i "The DNSSEC update test requires the Net::DNS library." >&2
fi
-n=$((n + 1))
-echo_i "checking managed key maintenance has not started yet ($n)"
-ret=0
-[ -f "ns4/managed-keys.bind.jnl" ] && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Reconfigure caching server to use "dnssec-validation auto", and repeat
-# some of the DNSSEC validation tests to ensure that it works correctly.
-# Also setup a placeholder managed-keys zone to check if named can process it
-# correctly.
-echo_i "switching to automatic root key configuration"
-cp ns4/managed-keys.bind.in ns4/managed-keys.bind
-copy_setports ns4/named2.conf.in ns4/named.conf
-rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
-sleep 5
-
-echo_i "checking managed key maintenance timer has now started ($n)"
-ret=0
-[ -f "ns4/managed-keys.bind.jnl" ] || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking positive validation NSEC ($n)"
-ret=0
-dig_with_opts +noauth a.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth a.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 validation NSEC3 ($n)"
-ret=0
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.nsec3.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 validation OPTOUT ($n)"
-ret=0
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.3 a >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth a.optout.example. \
- @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" 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 negative validation ($n)"
-ret=0
-dig_with_opts +noauth q.example. @10.53.0.2 a >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth q.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NXDOMAIN" 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 that root DS queries validate ($n)"
-ret=0
-dig_with_opts +noauth . @10.53.0.1 ds >dig.out.ns1.test$n || ret=1
-dig_with_opts +noauth . @10.53.0.4 ds >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns1.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" 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 that DS at a RFC 1918 empty zone lookup succeeds ($n)"
-ret=0
-dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.2 >dig.out.ns2.test$n || ret=1
-dig_with_opts +noauth 10.in-addr.arpa ds @10.53.0.4 >dig.out.ns6.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns6.test$n || ret=1
-grep "status: NOERROR" dig.out.ns6.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking expired signatures remain with "'"allow-update { none; };"'" and no keys available ($n)"
-ret=0
-dig_with_opts +noauth expired.example. +dnssec @10.53.0.3 soa >dig.out.ns3.test$n || ret=1
-grep "RRSIG.SOA" dig.out.ns3.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-
-status=$((status + ret))
-echo_i "checking expired signatures do not validate ($n)"
-ret=0
-dig_with_opts +noauth expired.example. +dnssec @10.53.0.4 soa >dig.out.ns4.test$n || ret=1
-grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-grep "expired.example/.*: RRSIG has expired" ns4/named.run >/dev/null || ret=1
-grep "; EDE: 7 (Signature Expired): (expired.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-status=$((status + ret))
-echo_i "checking signatures in the future do not validate ($n)"
-ret=0
-dig_with_opts +noauth future.example. +dnssec @10.53.0.4 soa >dig.out.ns4.test$n || ret=1
-grep "SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-grep "future.example/.*: RRSIG validity period has not begun" ns4/named.run >/dev/null || ret=1
-grep "; EDE: 8 (Signature Not Yet Valid): (future.example/DNSKEY)" 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 that the NSEC3 record for the apex is properly signed when a DNSKEY is added via UPDATE ($n)"
ret=0
(
dig_with_opts +dnssec a update-nsec3.example. @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
-grep "NSEC3 1 0 0 - .*" 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 that signing records have been marked as complete ($n)"
-ret=0
-checkprivate dynamic.example 10.53.0.3 || ret=1
-checkprivate auto-nsec3.example 10.53.0.3 || ret=1
-checkprivate expiring.example 10.53.0.3 || ret=1
-checkprivate auto-nsec.example 10.53.0.3 || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check that 'rndc signing' without arguments is handled ($n)"
-ret=0
-rndccmd 10.53.0.3 signing >/dev/null 2>&1 && ret=1
-rndccmd 10.53.0.3 status >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check that 'rndc signing -list' without zone is handled ($n)"
-ret=0
-rndccmd 10.53.0.3 signing -list >/dev/null 2>&1 && ret=1
-rndccmd 10.53.0.3 status >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)"
-ret=0
-rndccmd 10.53.0.3 signing -clear >/dev/null 2>&1 && ret=1
-rndccmd 10.53.0.3 status >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check that 'rndc signing -clear all' without zone is handled ($n)"
-ret=0
-rndccmd 10.53.0.3 signing -clear all >/dev/null 2>&1 && ret=1
-rndccmd 10.53.0.3 status >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check rndc signing -list output ($n)"
-ret=0
-{ rndccmd 10.53.0.3 signing -list dynamic.example >signing.out.dynamic.example; } 2>&1
-grep -q "No signing records found" signing.out.dynamic.example || {
- ret=1
- sed 's/^/ns3 /' signing.out.dynamic.example | cat_i
-}
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that a insecure zone beneath a cname resolves ($n)"
-ret=0
-dig_with_opts soa insecure.below-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 1," 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 that a secure zone beneath a cname resolves ($n)"
-ret=0
-dig_with_opts soa secure.below-cname.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 2," 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))
-
-my_dig() {
- "$DIG" +noadd +nosea +nostat +noquest +nocomm +nocmd -p "$PORT" @10.53.0.4 "$@"
-}
-
-echo_i "checking DNSKEY query with no data still gets put in cache ($n)"
-ret=0
-firstVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }')
-sleep 1
-secondVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }')
-if [ "${firstVal:-0}" -eq "${secondVal:-0}" ]; then
- sleep 1
- thirdVal=$(my_dig insecure.example. dnskey | awk '$1 != ";;" { print $2 }')
- if [ "${firstVal:-0}" -eq "${thirdVal:-0}" ]; then
- echo_i "cannot confirm query answer still in cache"
- ret=1
- fi
-fi
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check that a split dnssec dnssec-signzone work ($n)"
-ret=0
-dig_with_opts soa split-dnssec.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 2," 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 "check that a smart split dnssec dnssec-signzone work ($n)"
-ret=0
-dig_with_opts soa split-smart.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 2," 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 "check dnssec-dsfromkey from stdin ($n)"
-ret=0
-dig_with_opts dnskey algroll. @10.53.0.2 \
- | $DSFROMKEY -f - algroll. >dig.out.ns2.test$n || ret=1
-NF=$(awk '{print NF}' dig.out.ns2.test$n | sort -u)
-[ "${NF}" = 7 ] || ret=1
-# make canonical
-awk '{
- for (i=1;i<7;i++) printf("%s ", $i);
- for (i=7;i<=NF;i++) printf("%s", $i);
- printf("\n");
-}' <dig.out.ns2.test$n >canonical1.$n || ret=1
-awk '{
- for (i=1;i<7;i++) printf("%s ", $i);
- for (i=7;i<=NF;i++) printf("%s", $i);
- printf("\n");
-}' <ns1/dsset-algroll. >canonical2.$n || ret=1
-diff -b canonical1.$n canonical2.$n >/dev/null 2>&1 || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Intentionally strip ".key" from keyfile name to ensure the error message
-# includes it anyway to avoid confusion (RT #21731)
-echo_i "check dnssec-dsfromkey error message when keyfile is not found ($n)"
-ret=0
-key=$($KEYGEN -a $DEFAULT_ALGORITHM -q example.) || ret=1
-mv "$key.key" "$key"
-$DSFROMKEY "$key" >dsfromkey.out.$n 2>&1 && ret=1
-grep "$key.key: file not found" dsfromkey.out.$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check dnssec-dsfromkey with revoked key ($n)"
-ret=0
-dig_with_opts revkey.example dnskey @10.53.0.4 >dig.out.ns4.test$n || ret=1
-grep "DNSKEY.256 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # ZSK
-grep "DNSKEY.385 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # revoked KSK
-grep "DNSKEY.257 3 13" dig.out.ns4.test$n >/dev/null || ret=1 # KSK
-test $(awk '$4 == "DNSKEY" { print }' dig.out.ns4.test$n | wc -l) -eq 3 || ret=1
-$DSFROMKEY -f dig.out.ns4.test$n revkey.example. >dsfromkey.out.test$n || ret=1
-test $(wc -l <dsfromkey.out.test$n) -eq 1 || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-
-echo_i "testing soon-to-expire RRSIGs without a replacement private key ($n)"
-ret=0
-dig_with_answeropts +nottlid expiring.example ns @10.53.0.3 | grep RRSIG >dig.out.ns3.test$n 2>&1
-# there must be a signature here
-[ -s dig.out.ns3.test$n ] || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "testing legacy upper case signer name validation ($n)"
-ret=0
-$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa upper.example @10.53.0.4 \
- >dig.out.ns4.test$n 2>&1 || ret=1
-grep "flags:.* ad;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "RRSIG.*SOA.* UPPER\\.EXAMPLE\\. " dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "testing that we lower case signer name ($n)"
-ret=0
-$DIG +tcp +noadd +noauth +dnssec -p "$PORT" soa LOWER.EXAMPLE @10.53.0.4 \
- >dig.out.ns4.test$n 2>&1 || ret=1
-grep "flags:.* ad;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "RRSIG.*SOA.* lower\\.example\\. " dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "testing TTL is capped at RRSIG expiry time ($n)"
-ret=0
-rndccmd 10.53.0.3 freeze expiring.example 2>&1 | sed 's/^/ns3 /' | cat_i
-(
- cd ns3 || exit 1
- for file in K*.moved; do
- mv "$file" "$(basename "$file" .moved)"
- done
- $SIGNER -S -N increment -e now+1mi -o expiring.example expiring.example.db >/dev/null
-) || ret=1
-rndc_reload ns3 10.53.0.3 expiring.example
-
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-dig_with_answeropts +cd expiring.example soa @10.53.0.4 >dig.out.ns4.1.$n
-dig_with_answeropts expiring.example soa @10.53.0.4 >dig.out.ns4.2.$n
-ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
-ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
-for ttl in ${ttls:-0}; do
- [ "${ttl}" -eq 300 ] || ret=1
-done
-for ttl in ${ttls2:-0}; do
- [ "${ttl}" -le 60 ] || ret=1
-done
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (NS) ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-sleep 1
-dig_with_additionalopts +cd expiring.example ns @10.53.0.4 >dig.out.ns4.1.$n
-dig_with_additionalopts expiring.example ns @10.53.0.4 >dig.out.ns4.2.$n
-ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
-ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
-for ttl in ${ttls:-300}; do
- [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
-done
-for ttl in ${ttls2:-0}; do
- [ "$ttl" -le 60 ] || ret=1
-done
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section (MX) ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-sleep 1
-dig_with_additionalopts +cd expiring.example mx @10.53.0.4 >dig.out.ns4.1.$n
-dig_with_additionalopts expiring.example mx @10.53.0.4 >dig.out.ns4.2.$n
-ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
-ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
-for ttl in ${ttls:-300}; do
- [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
-done
-for ttl in ${ttls2:-0}; do
- [ "$ttl" -le 60 ] || ret=1
-done
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-copy_setports ns4/named3.conf.in ns4/named.conf
-rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
-sleep 3
-
-echo_i "testing TTL of about to expire RRsets with dnssec-accept-expired yes; ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-dig_with_answeropts +cd expiring.example soa @10.53.0.4 >dig.out.ns4.1.$n
-dig_with_answeropts expiring.example soa @10.53.0.4 >dig.out.ns4.2.$n
-ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
-ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
-for ttl in ${ttls:-0}; do
- [ "$ttl" -eq 300 ] || ret=1
-done
-for ttl in ${ttls2:-0}; do
- [ "$ttl" -eq 120 ] || ret=1
-done
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "testing TTL of expired RRsets with dnssec-accept-expired yes; ($n)"
-ret=0
-dig_with_answeropts +cd expired.example soa @10.53.0.4 >dig.out.ns4.1.$n
-dig_with_answeropts expired.example soa @10.53.0.4 >dig.out.ns4.2.$n
-ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
-ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
-for ttl in ${ttls:-0}; do
- [ "$ttl" -eq 300 ] || ret=1
-done
-for ttl in ${ttls2:-0}; do
- [ "$ttl" -eq 120 ] || ret=1
-done
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "testing TTL is capped at RRSIG expiry time for records in the additional section with dnssec-accept-expired yes; ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-dig_with_additionalopts +cd expiring.example mx @10.53.0.4 >dig.out.ns4.1.$n
-dig_with_additionalopts expiring.example mx @10.53.0.4 >dig.out.ns4.2.$n
-ttls=$(awk '$1 != ";;" {print $2}' dig.out.ns4.1.$n)
-ttls2=$(awk '$1 != ";;" {print $2}' dig.out.ns4.2.$n)
-for ttl in ${ttls:-300}; do
- [ "$ttl" -le 300 ] && [ "$ttl" -gt 240 ] || ret=1
-done
-for ttl in ${ttls2:-0}; do
- [ "$ttl" -le 120 ] && [ "$ttl" -gt 60 ] || ret=1
-done
+grep "NSEC3 1 0 0 - .*" dig.out.ns4.test$n >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "testing DNSKEY lookup via CNAME ($n)"
+echo_i "checking that signing records have been marked as complete ($n)"
ret=0
-dig_with_opts +noauth cnameandkey.secure.example. \
- @10.53.0.3 dnskey >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth cnameandkey.secure.example. \
- @10.53.0.4 dnskey >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "CNAME" dig.out.ns4.test$n >/dev/null || ret=1
+checkprivate dynamic.example 10.53.0.3 || ret=1
+checkprivate auto-nsec3.example 10.53.0.3 || ret=1
+checkprivate expiring.example 10.53.0.3 || ret=1
+checkprivate auto-nsec.example 10.53.0.3 || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "testing KEY lookup at CNAME (present) ($n)"
+echo_i "check that 'rndc signing' without arguments is handled ($n)"
ret=0
-dig_with_opts +noauth cnameandkey.secure.example. \
- @10.53.0.3 key >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth cnameandkey.secure.example. \
- @10.53.0.4 key >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "CNAME" dig.out.ns4.test$n >/dev/null && ret=1
+rndccmd 10.53.0.3 signing >/dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "testing KEY lookup at CNAME (not present) ($n)"
+echo_i "check that 'rndc signing -list' without zone is handled ($n)"
ret=0
-dig_with_opts +noauth cnamenokey.secure.example. \
- @10.53.0.3 key >dig.out.ns3.test$n || ret=1
-dig_with_opts +noauth cnamenokey.secure.example. \
- @10.53.0.4 key >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "CNAME" dig.out.ns4.test$n >/dev/null && ret=1
+rndccmd 10.53.0.3 signing -list >/dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "testing DNSKEY lookup via DNAME ($n)"
+echo_i "check that 'rndc signing -clear' without additional arguments is handled ($n)"
ret=0
-dig_with_opts a.dnameandkey.secure.example. \
- @10.53.0.3 dnskey >dig.out.ns3.test$n || ret=1
-dig_with_opts a.dnameandkey.secure.example. \
- @10.53.0.4 dnskey >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "CNAME" dig.out.ns4.test$n >/dev/null || ret=1
-grep "DNAME" dig.out.ns4.test$n >/dev/null || ret=1
+rndccmd 10.53.0.3 signing -clear >/dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "testing KEY lookup via DNAME ($n)"
+echo_i "check that 'rndc signing -clear all' without zone is handled ($n)"
ret=0
-dig_with_opts b.dnameandkey.secure.example. \
- @10.53.0.3 key >dig.out.ns3.test$n || ret=1
-dig_with_opts b.dnameandkey.secure.example. \
- @10.53.0.4 key >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns3.test$n dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "DNAME" dig.out.ns4.test$n >/dev/null || ret=1
+rndccmd 10.53.0.3 signing -clear all >/dev/null 2>&1 && ret=1
+rndccmd 10.53.0.3 status >/dev/null || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "check that named doesn't loop when all private keys are not available ($n)"
+echo_i "check rndc signing -list output ($n)"
ret=0
-lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true)
-test "${lines:-1000}" -lt 15 || ret=1
+{ rndccmd 10.53.0.3 signing -list dynamic.example >signing.out.dynamic.example; } 2>&1
+grep -q "No signing records found" signing.out.dynamic.example || {
+ ret=1
+ sed 's/^/ns3 /' signing.out.dynamic.example | cat_i
+}
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "check against against missing nearest provable proof ($n)"
-dig_with_opts +norec b.c.d.optout-tld. \
- @10.53.0.6 ds >dig.out.ds.ns6.test$n || ret=1
-nsec3=$(grep -c "IN.NSEC3" dig.out.ds.ns6.test$n || true)
-[ "$nsec3" -eq 2 ] || ret=1
-dig_with_opts +norec b.c.d.optout-tld. \
- @10.53.0.6 A >dig.out.ns6.test$n || ret=1
-nsec3=$(grep -c "IN.NSEC3" dig.out.ns6.test$n || true)
-[ "$nsec3" -eq 1 ] || ret=1
-dig_with_opts optout-tld. \
- @10.53.0.4 SOA >dig.out.soa.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.soa.ns4.test$n >/dev/null || ret=1
-dig_with_opts b.c.d.optout-tld. \
- @10.53.0.4 A >dig.out.ns4.test$n || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
+echo_i "check that a split dnssec dnssec-signzone work ($n)"
+ret=0
+dig_with_opts soa split-dnssec.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
+grep "ANSWER: 2," 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 "check that key id are logged when dumping the cache ($n)"
+echo_i "check that a smart split dnssec dnssec-signzone work ($n)"
ret=0
-rndc_dumpdb ns4
-grep "; key id = " ns4/named_dump.db.test$n >/dev/null || ret=1
+dig_with_opts soa split-smart.example. @10.53.0.4 >dig.out.ns4.test$n || ret=1
+grep "NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
+grep "ANSWER: 2," 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 "check KEYDATA records are printed in human readable form in key zone ($n)"
-# force the managed-keys zone to be written out
-rndccmd 10.53.0.4 managed-keys sync 2>&1 | sed 's/^/ns4 /' | cat_i
-for i in 1 2 3 4 5 6 7 8 9; do
- ret=0
- if test -f ns4/managed-keys.bind; then
- grep KEYDATA ns4/managed-keys.bind >/dev/null \
- && grep "next refresh:" ns4/managed-keys.bind >/dev/null \
- && break
- fi
- ret=1
- sleep 1
-done
+echo_i "testing soon-to-expire RRSIGs without a replacement private key ($n)"
+ret=0
+dig_with_answeropts +nottlid expiring.example ns @10.53.0.3 | grep RRSIG >dig.out.ns3.test$n 2>&1
+# there must be a signature here
+[ -s dig.out.ns3.test$n ] || ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-copy_setports ns4/named4.conf.in ns4/named.conf
-rndccmd 10.53.0.4 reconfig 2>&1 | sed 's/^/ns4 /' | cat_i
-sleep 3
-
-echo_i "check insecure delegation between static-stub zones ($n)"
+echo_i "check that named doesn't loop when all private keys are not available ($n)"
ret=0
-dig_with_opts ns insecure.secure.example \
- @10.53.0.4 >dig.out.ns4.1.test$n || ret=1
-grep "SERVFAIL" dig.out.ns4.1.test$n >/dev/null && ret=1
-dig_with_opts ns secure.example \
- @10.53.0.4 >dig.out.ns4.2.test$n || ret=1
-grep "SERVFAIL" dig.out.ns4.2.test$n >/dev/null && ret=1
+lines=$(grep -c "reading private key file expiring.example" ns3/named.run || true)
+test "${lines:-1000}" -lt 15 || 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 "check that split rrsigs are handled ($n)"
-ret=0
-dig_with_opts split-rrsig soa @10.53.0.7 >dig.out.test$n || ret=1
-awk 'BEGIN { ok=0; } $4 == "SOA" { if ($7 > 1) ok=1; } END { if (!ok) exit(1); }' dig.out.test$n || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check that not-at-zone-apex RRSIG(SOA) RRsets are removed from the zone after load ($n)"
-ret=0
-dig_with_opts split-rrsig AXFR @10.53.0.7 >dig.out.test$n || ret=1
-grep -q "not-at-zone-apex.*RRSIG.*SOA" dig.out.test$n && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
echo_i "check that CDS records are signed using KSK by dnssec-signzone ($n)"
ret=0
dig_with_opts +noall +answer @10.53.0.2 cds cds.secure >dig.out.test$n
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "checking that positive unknown NSEC3 hash algorithm does validate ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example SOA >dig.out.ns3.test$n
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example SOA >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
echo_i "check that CDS records are signed using KSK by with dnssec-policy ($n)"
ret=0
dig_with_opts +noall +answer @10.53.0.2 cds cds-auto.secure >dig.out.test$n
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "checking that positive unknown NSEC3 hash algorithm with OPTOUT does validate ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example SOA >dig.out.ns3.test$n
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example SOA >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 1," dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
echo_i "check that a non matching CDS record is accepted with a matching CDS record ($n)"
ret=0
(
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "checking that negative unknown NSEC3 hash algorithm does not validate ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 nsec3-unknown.example A >dig.out.ns3.test$n
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 nsec3-unknown.example A >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: SERVFAIL," dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
echo_i "check that CDNSKEY records are signed using KSK by dnssec-signzone ($n)"
ret=0
dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey.secure >dig.out.test$n
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "checking that negative unknown NSEC3 hash algorithm with OPTOUT does not validate ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 optout-unknown.example A >dig.out.ns3.test$n
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 optout-unknown.example A >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: SERVFAIL," dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
echo_i "check that CDNSKEY records are signed using KSK by with dnssec-auto ($n)"
ret=0
dig_with_opts +noall +answer @10.53.0.2 cdnskey cdnskey-auto.secure >dig.out.test$n
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "checking that unknown DNSKEY algorithm validates as insecure ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unknown.example A >dig.out.ns3.test$n
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unknown.example A >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 that unsupported DNSKEY algorithm validates as insecure ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported.example A >dig.out.ns3.test$n
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-unsupported.example A >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1
-grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 dnskey-unsupported.example/SOA)" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 EDE code 2 for unsupported DS digest ($n)"
-ret=0
-dig_with_opts @10.53.0.4 a.ds-unsupported.example >dig.out.ns4.test$n || ret=1
-grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-256 ds-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 EDE code 1 for bad alg mnemonic ($n)"
-ret=0
-dig_with_opts @10.53.0.4 badalg.secure.example >dig.out.ns4.test$n || ret=1
-grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP256SHA256 badalg.secure.example/NSEC)" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 both EDE code 1 and 2 for unsupported digest on one DNSKEY and alg on the other ($n)"
-ret=0
-dig_with_opts @10.53.0.4 a.digest-alg-unsupported.example >dig.out.ns4.test$n || ret=1
-grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP384SHA384 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1
-grep "; EDE: 2 (Unsupported DS Digest Type): (SHA-384 digest-alg-unsupported.example/DNSKEY)" dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" 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 that unsupported DNSKEY algorithm is in DNSKEY RRset ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-unsupported-2.example DNSKEY >dig.out.test$n
-grep "status: NOERROR," dig.out.test$n >/dev/null || ret=1
-grep "dnskey-unsupported-2\.example\..*IN.*DNSKEY.*257 3 255" dig.out.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check that a query for a domain that has a KSK that is not actively signing
-# the DNSKEY RRset. This should not result in a broken trust chain if there is
-# another KSK that is signing the DNSKEY RRset.
-echo_i "checking that a secure chain with one active and one inactive KSK validates as secure ($n)"
-ret=0
-dig_with_opts @10.53.0.4 a.lazy-ksk A >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
# TODO: test case for GL #1689.
# If we allow the dnssec tools to use deprecated algorithms (such as RSAMD5)
# we could write a test that signs a zone with supported and unsupported
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "checking that unknown DNSKEY algorithm + unknown NSEC3 has algorithm validates as insecure ($n)"
-ret=0
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.3 dnskey-nsec3-unknown.example A >dig.out.ns3.test$n
-dig_with_opts +noauth +noadd +nodnssec +adflag @10.53.0.4 dnskey-nsec3-unknown.example A >dig.out.ns4.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
echo_i "check that CDNSKEY records are signed using KSK only when added by nsupdate ($n)"
ret=0
keyid=$(cat ns2/cdnskey-update.secure.id)
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-echo_i "check that a named managed zone that was signed 'in-the-future' is re-signed when loaded ($n)"
-ret=0
-dig_with_opts managed-future.example. @10.53.0.4 a >dig.out.ns4.test$n || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "check that the view is logged in messages from the validator when using views ($n)"
-ret=0
-grep "view rec: *validat" ns4/named.run >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
echo_i "check that DNAME at apex with NSEC3 is correctly signed (dnssec-signzone) ($n)"
ret=0
dig_with_opts txt dname-at-apex-nsec3.example @10.53.0.3 >dig.out.ns3.test$n || ret=1
test "$ret" -eq 0 || echo_i "failed"
status=$((status + ret))
-#
-# DNSSEC tests related to unsupported, disabled and revoked trust anchors.
-#
-
-# This nameserver (ns8) is loaded with a bunch of trust anchors. Some of
-# them are good (enabled.managed, enabled.trusted, secure.managed,
-# secure.trusted), and some of them are bad (disabled.managed,
-# revoked.managed, unsupported.managed, disabled.trusted, revoked.trusted,
-# unsupported.trusted). Make sure that the bad trust anchors are ignored.
-# This is tested by looking for the corresponding lines in the logfile.
-echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)"
-ret=0
-grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1
-grep -q "ignoring static-key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1
-grep -q "ignoring static-key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1
-grep -q "ignoring initial-key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1
-grep -q "ignoring initial-key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1
-grep -q "ignoring initial-key for 'revoked\.managed\.': bad key type" ns8/named.run || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# The next two tests are fairly normal DNSSEC queries to signed zones with a
-# default algorithm. First, a query is made against the server that is
-# authoritative for the given zone (ns3). Second, a query is made against a
-# resolver with trust anchors for the given zone (ns8). Both are expected to
-# return an authentic data positive response.
-echo_i "checking that a trusted key using a supported algorithm validates as secure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.secure.trusted A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.secure.trusted A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1
-grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that a managed key using a supported algorithm validates as secure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.secure.managed A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.secure.managed A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1
-grep "; EDE: " dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# The next two queries ensure that a zone signed with a DNSKEY with an unsupported
-# algorithm will yield insecure positive responses. These trust anchors in ns8 are
-# ignored and so this domain is treated as insecure. The AD bit should not be set
-# in the response.
-echo_i "checking that a trusted key using an unsupported algorithm validates as insecure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.unsupported.trusted A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.unsupported.trusted A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.trusted (cached))" dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that a managed key using an unsupported algorithm validates as insecure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.unsupported.managed A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.unsupported.managed A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (255 ns3.unsupported.managed (cached))" dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# The next two queries ensure that a zone signed with a DNSKEY that the nameserver
-# has a disabled algorithm match for will yield insecure positive responses.
-# These trust anchors in ns8 are ignored and so this domain is treated as insecure.
-# The AD bit should not be set in the response.
-echo_i "checking that a trusted key using a disabled algorithm validates as insecure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.disabled.trusted A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.disabled.trusted A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that a managed key using a disabled algorithm validates as insecure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.disabled.managed A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.disabled.managed A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# The next two queries ensure that a zone signed with a DNSKEY that the
-# nameserver has a disabled algorithm for, but for a different domain, will
-# yield secure positive responses. Since "enabled.trusted." and
-# "enabled.managed." do not match the "disable-algorithms" option, no
-# special rules apply and these zones should validate as secure, with the AD
-# bit set.
-echo_i "checking that a trusted key using an algorithm disabled for another domain validates as secure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.enabled.trusted A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.enabled.trusted A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that a managed key using an algorithm disabled for another domain validates as secure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.enabled.managed A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.enabled.managed A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# A configured revoked trust anchor is ignored and thus the two queries below
-# should result in insecure responses, since no trust points for the
-# "revoked.trusted." and "revoked.managed." zones are created.
-echo_i "checking that a trusted key that is revoked validates as insecure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.revoked.trusted A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.revoked.trusted A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking that a managed key that is revoked validates as insecure ($n)"
-ret=0
-dig_with_opts @10.53.0.3 a.revoked.managed A >dig.out.ns3.test$n
-dig_with_opts @10.53.0.8 a.revoked.managed A >dig.out.ns8.test$n
-grep "status: NOERROR," dig.out.ns3.test$n >/dev/null || ret=1
-grep "status: NOERROR," dig.out.ns8.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns8.test$n >/dev/null && ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
###
### Additional checks for when the KSK is offline.
###
status=$((status + ret))
done
-echo_i "checking secroots output with multiple views ($n)"
-ret=0
-rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i
-cp ns4/named.secroots named.secroots.test$n
-check_secroots_layout named.secroots.test$n || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-echo_i "checking validation succeeds during transition to signed ($n)"
-ret=0
-dig_with_opts @10.53.0.4 inprogress A >dig.out.ns4.test$n || ret=1
-grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep 'A.10\.53\.0\.10' 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 excessive NSEC3 iteration warnings in named.run ($n)"
-ret=0
-grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 50" ns2/named.run >/dev/null 2>&1 || ret=1
-grep "zone too-many-iterations/IN: excessive NSEC3PARAM iterations [0-9]* > 50" ns3/named.run >/dev/null 2>&1 || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check that the validating resolver will fallback to insecure if the answer
-# contains NSEC3 records with high iteration count.
-echo_i "checking fallback to insecure when NSEC3 iterations is too high (nxdomain) ($n)"
-ret=0
-dig_with_opts @10.53.0.2 does-not-exist.too-many-iterations >dig.out.ns2.test$n || ret=1
-dig_with_opts @10.53.0.4 does-not-exist.too-many-iterations >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 0, AUTHORITY: 8" 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 fallback to insecure when NSEC3 iterations is too high (nodata) ($n)"
-ret=0
-dig_with_opts @10.53.0.2 a.too-many-iterations txt >dig.out.ns2.test$n || ret=1
-dig_with_opts @10.53.0.4 a.too-many-iterations txt >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 0, AUTHORITY: 4" 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 fallback to insecure when NSEC3 iterations is too high (wildcard) ($n)"
-ret=0
-dig_with_opts @10.53.0.2 wild.a.too-many-iterations >dig.out.ns2.test$n || ret=1
-dig_with_opts @10.53.0.4 wild.a.too-many-iterations >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep 'wild\.a\.too-many-iterations\..*A.10\.0\.0\.3' dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 2, AUTHORITY: 4" 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 fallback to insecure when NSEC3 iterations is too high (wildcard nodata) ($n)"
-ret=0
-dig_with_opts @10.53.0.2 type100 wild.a.too-many-iterations >dig.out.ns2.test$n || ret=1
-dig_with_opts @10.53.0.4 type100 wild.a.too-many-iterations >dig.out.ns4.test$n || ret=1
-digcomp dig.out.ns2.test$n dig.out.ns4.test$n || ret=1
-grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 0, AUTHORITY: 8" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-test "$ret" -eq 0 || echo_i "failed"
-status=$((status + ret))
-
-# Check that a query against a validating resolver succeeds when there is
-# a negative cache entry with trust level "pending" for the DS. Prime
-# with a +cd DS query to produce the negative cache entry, then send a
-# query that uses that entry as part of the validation process. [GL #3279]
-echo_i "check that pending negative DS cache entry validates ($n)"
-ret=0
-dig_with_opts @10.53.0.4 +cd insecure2.example. ds >dig.out.prime.ns4.test$n || ret=1
-grep "flags: qr rd ra cd;" dig.out.prime.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.prime.ns4.test$n >/dev/null || ret=1
-grep "ANSWER: 0, AUTHORITY: 4, " dig.out.prime.ns4.test$n >/dev/null || ret=1
-dig_with_opts @10.53.0.4 a.insecure2.example. a >dig.out.ns4.test$n || ret=1
-grep "ANSWER: 1, AUTHORITY: 1, " dig.out.ns4.test$n >/dev/null || ret=1
-grep "flags: qr rd ra;" dig.out.ns4.test$n >/dev/null || ret=1
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking NSEC3 nxdomain response closest encloser with 0 ENT ($n)"
-ret=0
-dig_with_opts @10.53.0.4 b.b.b.b.b.a.nsec3.example. >dig.out.ns4.test$n
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# closest encloser (a.nsec3.example)
-pat1="^6OVDUHTN094ML2PV8AN90U0DPU823GH2\.nsec3\.example\..*NSEC3 1 0 0 - 7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4 A RRSIG\$"
-grep "$pat1" dig.out.ns4.test$n >/dev/null || ret=1
-# no QNAME proof (b.a.nsec3.example / DSPF4R9UKOEPJ9O34E1H4539LSOTL14E)
-pat2="^CG2DVCNE20EKU1PDRLMI2L4DGC2FO1H3\.nsec3\.example\..*NSEC3 1 0 0 - EF2S05SGK1IR2K5SKMFIRERGQCLMR18M A RRSIG\$"
-grep "$pat2" dig.out.ns4.test$n >/dev/null || ret=1
-# no WILDCARD proof (*.a.nsec3.example / TFGQ60S97BS31IT1EBEDO63ETM0T5JFA)
-pat3="^R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\.nsec3\.example\..*NSEC3 1 0 0 - VH656EQUD4J02OFVSO4GKOK5D02MS1TL NS DS RRSIG\$"
-grep "$pat3" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking NSEC3 nxdomain response closest encloser with 1 ENTs ($n)"
-ret=0
-dig_with_opts @10.53.0.4 b.b.b.b.b.a.a.nsec3.example. >dig.out.ns4.test$n
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# closest encloser (a.a.nsec3.example)
-pat1="^NGCJFSOLJUUE27PFNQNJIME4TQ0OU2DH\.nsec3\.example\..*NSEC3 1 0 0 - R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\$"
-grep "$pat1" dig.out.ns4.test$n >/dev/null || ret=1
-# no QNAME proof (b.a.a.nsec3.example / V8I8SAIIVC3HOVMOVENSDRA6ATDCEMJI)
-pat2="^R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\.nsec3\.example\..*NSEC3 1 0 0 - VH656EQUD4J02OFVSO4GKOK5D02MS1TL NS DS RRSIG\$"
-grep "$pat2" dig.out.ns4.test$n >/dev/null || ret=1
-# no WILDCARD proof (*.a.a.nsec3.example / V7JNNDJ4NLRIU195FRB7DLUCSLU4LLFM)
-pat3="^R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q\.nsec3\.example\..*NSEC3 1 0 0 - VH656EQUD4J02OFVSO4GKOK5D02MS1TL NS DS RRSIG\$"
-grep "$pat3" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking NSEC3 nxdomain response closest encloser with 2 ENTs ($n)"
-ret=0
-dig_with_opts @10.53.0.4 b.b.b.b.b.a.a.a.nsec3.example. >dig.out.ns4.test$n
-grep "status: NXDOMAIN" dig.out.ns4.test$n >/dev/null || ret=1
-# closest encloser (a.a.a.nsec3.example)
-pat1="^H7RHPDCHSVVRAND332F878C8AB6IBJQV\.nsec3\.example\..*NSEC3 1 0 0 - K8IG76R2UPQ13IKFO49L7IB9JRVB6QJI\$"
-grep "$pat1" dig.out.ns4.test$n >/dev/null || ret=1
-# no QNAME proof (b.a.a.a.nsec3.example / 18Q8D89RM8GGRSSOPFRB05QS6VEGB1P4)
-pat2="^VH656EQUD4J02OFVSO4GKOK5D02MS1TL\.nsec3\.example\..*NSEC3 1 0 0 - 1HARMGSKJH0EBU2EI2OJIKTDPIQA6KBI NS DS RRSIG\$"
-grep "$pat2" dig.out.ns4.test$n >/dev/null || ret=1
-# no WILDCARD proof (*.a.a.a.nsec3.example / 8113LDMSEFPUAG4VGFF1C8KLOUT4Q6PH)
-pat3="^7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4\.nsec3\.example\..*NSEC3 1 0 0 - BEJ5GMQA872JF4DAGQ0R3O5Q7A2O5S9L A RRSIG\$"
-grep "$pat3" dig.out.ns4.test$n >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking validator behavior with mismatching NS ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-$DIG +tcp +cd -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.1 || ret=1
-grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2" dig.out.ns4.test$n.1 >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.1 >/dev/null && ret=1
-$DIG +tcp +cd +dnssec -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.2 || ret=1
-grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2" dig.out.ns4.test$n.2 >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.2 >/dev/null && ret=1
-$DIG +tcp +dnssec -p "$PORT" -t ns inconsistent @10.53.0.4 >dig.out.ns4.test$n.3 || ret=1
-grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns4.test$n.3 >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns4.test$n.3 >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking that a insecure negative response where there is a NSEC without a RRSIG succeeds ($n)"
-ret=0
-# check server preconditions
-dig_with_opts +notcp @10.53.0.10 nsec-rrsigs-stripped. TXT +dnssec >dig.out.ns10.test$n
-grep "status: NOERROR" dig.out.ns10.test$n >/dev/null || ret=1
-grep "QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1" dig.out.ns10.test$n >/dev/null || ret=1
-grep "IN.RRSIG.NSEC" dig.out.ns10.test$n >/dev/null && ret=1
-# check resolver succeeds
-dig_with_opts @10.53.0.4 nsec-rrsigs-stripped. TXT +dnssec >dig.out.ns4.test$n
-grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1" dig.out.ns4.test$n >/dev/null || ret=1
-grep "IN.RRSIG.NSEC" dig.out.ns4.test$n >/dev/null && ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking validating forwarder behavior with mismatching NS ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-$DIG +tcp +cd -p "$PORT" -t ns inconsistent @10.53.0.9 >dig.out.ns9.test$n.1 || ret=1
-grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns9.test$n.1 >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns9.test$n.1 >/dev/null && ret=1
-$DIG +tcp +cd +dnssec -p "$PORT" -t ns inconsistent @10.53.0.9 >dig.out.ns9.test$n.2 || ret=1
-grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns9.test$n.2 >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns9.test$n.2 >/dev/null && ret=1
-$DIG +tcp +dnssec -p "$PORT" -t ns inconsistent @10.53.0.9 >dig.out.ns9.test$n.3 || ret=1
-grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.ns9.test$n.3 >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns9.test$n.3 >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-echo_i "checking forwarder CD behavior (DS mismatch and local trust anchor) ($n)"
-ret=0
-rndccmd 10.53.0.4 flush 2>&1 | sed 's/^/ns4 /' | cat_i
-# confirm invalid DS produces SERVFAIL in resolver
-$DIG +tcp +dnssec -p "$PORT" @10.53.0.4 localkey.example soa >dig.out.ns4.test$n || ret=1
-grep "status: SERVFAIL" dig.out.ns4.test$n >/dev/null || ret=1
-# check that lookup using forwarder succeeds and that SERVFAIL was received
-nextpart ns9/named.run >/dev/null
-$DIG +tcp +dnssec -p "$PORT" @10.53.0.9 localkey.example soa >dig.out.ns9.test$n || ret=1
-grep "status: NOERROR" dig.out.ns9.test$n >/dev/null || ret=1
-grep "flags:.*ad.*QUERY" dig.out.ns9.test$n >/dev/null || ret=1
-nextpart ns9/named.run | grep 'status: SERVFAIL' >/dev/null || ret=1
-n=$((n + 1))
-if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 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.
+
+import os
+import re
+import shutil
+import time
+
+from dns import edns, flags, name, rcode, rdataclass, rdatatype
+
+import pytest
+
+pytest.importorskip("dns", minversion="2.0.0")
+import isctest
+import isctest.mark
+from isctest.util import param
+
+
+# helper functions
+def grep_q(regex, filename):
+ with open(filename, "r", encoding="utf-8") as f:
+ blob = f.read().splitlines()
+ results = [x for x in blob if re.search(regex, x)]
+ return len(results) != 0
+
+
+def getfrom(file):
+ with open(file, encoding="utf-8") as f:
+ return f.read().strip()
+
+
+@pytest.mark.requires_zones_loaded("ns2", "ns3")
+@pytest.mark.parametrize(
+ "qname, qtype",
+ [
+ param("a.example.", "A"),
+ param("rfc2535.example.", "SOA"),
+ ],
+)
+def test_load_transfer(qname, qtype):
+ # check that we can load and transfer zone
+ msg = isctest.query.create(qname, qtype)
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.3")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res1)
+
+
+def test_insecure_glue():
+ # check that for a query against a validating resolver where the
+ # authoritative zone is unsigned (insecure delegation), glue is returned
+ # in the additional section
+ msg = isctest.query.create("a.insecure.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+ isctest.check.rr_count_eq(res.authority, 1)
+ isctest.check.rr_count_eq(res.additional, 1)
+ assert str(res.additional[0].name) == "ns.insecure.example."
+ addrs = [str(a) for a in res.additional[0]]
+ assert "10.53.0.3" in addrs
+
+
+def test_adflag():
+ # compare auth and recursive answers
+ msg = isctest.query.create("a.example", "A", dnssec=False)
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+
+ # check no AD flag in authoritative response
+ isctest.check.noadflag(res1)
+
+ # check validating resolver sends AD=1 if the client sent AD=1
+ isctest.check.adflag(res2)
+
+ # check that AD=0 unless the client sent AD=1
+ msg = isctest.query.create("a.example", "A", dnssec=False, ad=False)
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noadflag(res2)
+
+
+def test_secure_root(servers):
+ # check that a query for a secure root validates
+ msg = isctest.query.create(".", "KEY")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ # check that "rndc secroots" dumps the trusted keys
+ ns4 = servers["ns4"]
+ key = int(getfrom("ns1/managed.key.id"))
+ alg = os.environ["DEFAULT_ALGORITHM"]
+ expected = f"./{alg}/{key} ; static"
+ response = ns4.rndc("secroots -", log=False).splitlines()
+ assert expected in response
+ assert len(response) == 10
+
+
+def test_positive_validation_nsec():
+ # positive answer
+ msg = isctest.query.create("a.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # wildcard
+ msg = isctest.query.create("a.wild.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+ assert str(res2.authority[0].name) == "*.wild.example."
+ assert res2.authority[0].rdtype == rdatatype.NSEC
+ nsecs = [str(a).split(" ", maxsplit=1)[0] for a in res2.authority[0]]
+ assert "z.example." in nsecs
+ assert res2.authority[1].rdtype == rdatatype.RRSIG
+ assert res2.authority[1].covers == rdatatype.NSEC
+
+ # mixed case
+ for rrtype in ["a", "txt", "aaaa", "loc"]:
+ msg = isctest.query.create("mixedcase.secure.example", rrtype)
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+
+def test_positive_validation_nsec3():
+ # positive answer
+ msg = isctest.query.create("a.nsec3.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+ # wildcard
+ msg = isctest.query.create("a.wild.nsec3.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+ isctest.check.rr_count_eq(res2.authority, 4)
+
+ # unknown NSEC3 hash algorithm
+ msg = isctest.query.create("nsec3-unknown.example", "SOA", dnssec=False)
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+ isctest.check.rr_count_eq(res2.answer, 1)
+
+
+def test_positive_validation_optout():
+ # positive answer
+ msg = isctest.query.create("a.optout.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # wildcard
+ msg = isctest.query.create("a.wild.optout.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # unknown NSEC3 hash algorithm
+ msg = isctest.query.create("optout-unknown.example", "SOA", dnssec=False)
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+ isctest.check.rr_count_eq(res2.answer, 1)
+
+
+def answer_has(r, rdtype):
+ return bool([r for r in r.answer if r.rdtype == rdtype])
+
+
+def test_chain_validation():
+ # check validation of ANY response
+ msg = isctest.query.create("foo.example", "ANY")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.rr_count_eq(res2.answer, 6) # 2 records, 1 NSEC, 3 RRSIGs
+
+ # check validation of CNAME response
+ msg = isctest.query.create("cname1.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.rr_count_eq(res2.answer, 4) # CNAME, TXT, 2 RRSIGs
+
+ # check validation of DNAME response
+ msg = isctest.query.create("foo.dname1.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.rr_count_eq(res2.answer, 5) # DNAME, TXT, 2 RRSIGs, synth CNAME
+
+ # check validation of CNAME response to ANY query
+ msg = isctest.query.create("cname2.example", "ANY")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.rr_count_eq(res2.answer, 4) # CNAME, NSEC, 2 RRSIGs
+
+ # check validation of DNAME response to ANY query
+ msg = isctest.query.create("foo.dname2.example", "ANY")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.rr_count_eq(res2.answer, 3) # DNAME, RSRIG, synth CNAME
+
+ # check bad CNAME signature is caught after +CD query
+ msg = isctest.query.create("bad-cname.example", "A", dnssec=False, cd=True)
+ # query once with CD to prime the cache
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ # query again with CD, bogus pending data should be returned
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ assert "a.example." in str(res.answer[0])
+ assert "10.0.0.1" in str(res.answer[1])
+ # query again without CD, bogus data should be rejected
+ msg = isctest.query.create("bad-cname.example", "A", dnssec=False)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ # check bad DNAME signature is caught after +CD query
+ msg = isctest.query.create("a.bad-dname.example", "A", dnssec=False, cd=True)
+ # query once with CD to prime the cache
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ # query again with CD, bogus pending data should be returned
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ assert "example." in str(res.answer[0])
+ assert "a.example." in str(res.answer[1])
+ assert "10.0.0.1" in str(res.answer[2])
+ # query again without CD, bogus data should be rejected
+ msg = isctest.query.create("a.bad-dname.example", "A", dnssec=False)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ # check DNSKEY lookup via CNAME
+ msg = isctest.query.create("cnameandkey.secure.example", "DNSKEY")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+ assert answer_has(res2, rdatatype.CNAME)
+
+ # check KEY lookup via CNAME
+ msg = isctest.query.create("cnameandkey.secure.example", "KEY")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+ assert not answer_has(res2, rdatatype.CNAME)
+
+ # check KEY lookup via CNAME (not present)
+ msg = isctest.query.create("cnamenokey.secure.example", "KEY")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+ assert not answer_has(res2, rdatatype.CNAME)
+
+ # check DNSKEY lookup via DNAME
+ msg = isctest.query.create("a.dnameandkey.secure.example", "DNSKEY")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+ assert answer_has(res2, rdatatype.DNAME)
+
+ # check KEY lookup via DNAME
+ msg = isctest.query.create("a.dnameandkey.secure.example", "KEY")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+ assert answer_has(res2, rdatatype.DNAME)
+
+
+@isctest.mark.rsasha1
+def test_signing_algorithms_rsasha1():
+ # rsasha1 (should work with FIPS mode we're as only validating)
+ msg = isctest.query.create("a.rsasha1.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # rsasha1 (1024 bits) NSEC
+ msg = isctest.query.create("a.rsasha1-1024.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+
+def test_signing_algorithms():
+ # rsasha256
+ msg = isctest.query.create("a.rsasha256.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # rsasha512
+ msg = isctest.query.create("a.rsasha512.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # KSK-only DNSKEY
+ msg = isctest.query.create("a.kskonly.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+
+def test_private_algorithms(servers):
+ # positive answer, private algorithm
+ msg = isctest.query.create("a.rsasha256oid.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # positive answer, unknown private algorithm
+ msg = isctest.query.create("a.unknownoid.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noadflag(res2)
+
+ # positive answer, extra ds for private algorithm
+ msg = isctest.query.create("a.extradsoid.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # positive anwer, extra ds for unknown private algorithm
+ ns4 = servers["ns4"]
+ with ns4.watch_log_from_here() as watcher:
+ msg = isctest.query.create("a.extradsunknownoid.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res1)
+ isctest.check.servfail(res2)
+ watcher.wait_for_line(
+ "No DNSKEY for extradsunknownoid.example/DS with PRIVATEOID"
+ )
+
+
+@isctest.mark.extended_ds_digest
+def test_private_algorithms_extended_ds():
+ # check positive validation with extra ds using extended digest
+ # type for unknown private algorithm
+ msg = isctest.query.create("a.extended-ds-unknown-oid.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+
+def test_negative_validation_nsec():
+ # nxdomain
+ msg = isctest.query.create("q.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.adflag(res2)
+
+ # nodata
+ msg = isctest.query.create("a.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.empty_answer(res2)
+ isctest.check.adflag(res2)
+
+ # negative wildcard
+ msg = isctest.query.create("b.wild.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+
+def test_negative_validation_nsec3():
+ # nxdomain
+ msg = isctest.query.create("q.nsec3.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.adflag(res2)
+
+ # nodata
+ msg = isctest.query.create("a.nsec3.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.empty_answer(res2)
+ isctest.check.adflag(res2)
+
+ # negative wildcard
+ msg = isctest.query.create("b.wild.nsec3.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+ # check NSEC3 zone with mismatched NSEC3PARAM / NSEC parameters
+ msg = isctest.query.create("non-exist.badparam", "A")
+ res = isctest.query.tcp(msg, "10.53.0.2")
+ isctest.check.nxdomain(res)
+
+ # check negative unknown NSEC3 hash algorithm does not validate
+ msg = isctest.query.create("nsec3-unknown.example", "A", dnssec=False)
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res1)
+ isctest.check.servfail(res2)
+
+
+def test_excessive_nsec3_iterations():
+ assert grep_q(
+ "zone too-many-iterations/IN: excessive NSEC3PARAM iterations", "ns2/named.run"
+ )
+ assert grep_q(
+ "zone too-many-iterations/IN: excessive NSEC3PARAM iterations", "ns3/named.run"
+ )
+
+ # check fallback to insecure with NSEC3 iterations is too high
+ msg = isctest.query.create("does-not-exist.too-many-iterations", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noadflag(res2)
+ isctest.check.rr_count_eq(res2.answer, 0)
+ isctest.check.rr_count_eq(res2.authority, 8)
+
+ # check fallback to insecure with NSEC3 iterations is too high (nodata)
+ msg = isctest.query.create("a.too-many-iterations", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noadflag(res2)
+ isctest.check.rr_count_eq(res2.answer, 0)
+ isctest.check.rr_count_eq(res2.authority, 4)
+
+ # check fallback to insecure with NSEC3 iterations is too high (wildcard)
+ msg = isctest.query.create("wild.a.too-many-iterations", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noadflag(res2)
+ isctest.check.rr_count_eq(res2.answer, 2)
+ isctest.check.rr_count_eq(res2.authority, 4)
+ a, _ = res2.answer
+ assert str(a.name) == "wild.a.too-many-iterations."
+ assert str(a[0]) == "10.0.0.3"
+
+ # check fallback to insecure with high NSEC3 iterations (wildcard nodata)
+ msg = isctest.query.create("wild.a.too-many-iterations", 100)
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noadflag(res2)
+ isctest.check.rr_count_eq(res2.authority, 8)
+
+
+def test_auth_nsec3():
+ # nxdomain response, closest encloser with 0 empty non-terminals
+ msg = isctest.query.create("b.b.b.b.b.a.nsec3.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.nxdomain(res)
+ # closest encloser (a.nsec3.example):
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("6OVDUHTN094ML2PV8AN90U0DPU823GH2.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "NSEC3 missing from AUTHORITY: " + str(res)
+ assert "7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4" in str(rrset[0]).upper()
+ # no QNAME (b.a.nsec3.example/DSPF4R9UKOEPJ9O34E1H4539LSOTL14E)
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("BEJ5GMQA872JF4DAGQ0R3O5Q7A2O5S9L.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res)
+ assert "EF2S05SGK1IR2K5SKMFIRERGQCLMR18M" in str(rrset[0]).upper()
+ # no WILDCARD (*.a.nsec3.example/TFGQ60S97BS31IT1EBEDO63ETM0T5JFA)
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res)
+ assert "VH656EQUD4J02OFVSO4GKOK5D02MS1TL" in str(rrset[0]).upper()
+
+ # nxdomain response, closest encloser with 1 ENT
+ msg = isctest.query.create("b.b.b.b.b.a.a.nsec3.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.nxdomain(res)
+ # closest encloser (a.a.nsec3.example):
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("NGCJFSOLJUUE27PFNQNJIME4TQ0OU2DH.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res)
+ assert "R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q" in str(rrset[0]).upper()
+ # noqname (b.a.a.nsec3.example):
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("R8EVDMNIGNOKME4LH2H90OSP2PRSNJ1Q.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res)
+ assert "VH656EQUD4J02OFVSO4GKOK5D02MS1TL" in str(rrset[0]).upper()
+ # no wildcard (*.a.a.nsec3.example/V7JNNDJ4NLRIU195FRB7DLUCSLU4LLFM)
+ # is covered by the noqname proof in this case
+
+ # nxdomain response, closest encloser with 2 ENTs
+ msg = isctest.query.create("b.b.b.b.b.a.a.a.nsec3.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.nxdomain(res)
+ # closest encloser (a.a.a.nsec3.example):
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("H7RHPDCHSVVRAND332F878C8AB6IBJQV.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res)
+ assert "K8IG76R2UPQ13IKFO49L7IB9JRVB6QJI" in str(rrset[0]).upper()
+ # noqname (b.a.a.a.nsec3.example/18Q8D89RM8GGRSSOPFRB05QS6VEGB1P4)
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("0T7VH688AEK0612T69V8692OCMJD50M4.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res)
+ assert "1HARMGSKJH0EBU2EI2OJIKTDPIQA6KBI" in str(rrset[0]).upper()
+ # no WILDCARD (*.a.a.a.nsec3.example/8113LDMSEFPUAG4VGFF1C8KLOUT4Q6PH)
+ rrset = res.get_rrset(
+ res.authority,
+ name.from_text("7AT0S0RIDCJRFF2M5H5AAV22CSFJBUL4.nsec3.example."),
+ rdataclass.IN,
+ rdatatype.NSEC3,
+ )
+ assert rrset, "expected NSEC3 missing from AUTHORITY: " + str(res)
+ assert "BEJ5GMQA872JF4DAGQ0R3O5Q7A2O5S9L" in str(rrset[0]).upper()
+
+
+def test_negative_validation_optout():
+ # nxdomain
+ msg = isctest.query.create("q.optout.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+
+ # nodata
+ msg = isctest.query.create("a.optout.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.empty_answer(res2)
+ isctest.check.adflag(res2)
+
+ # negative wildcard
+ msg = isctest.query.create("b.wild.optout.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # empty NODATA
+ msg = isctest.query.create("empty.optout.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # (rt22007 regression tests:)
+ # check optout NSEC3 referral with only insecure delegatons
+ msg = isctest.query.create("delegation.single-nsec3", "A")
+ res = isctest.query.tcp(msg, "10.53.0.2")
+ isctest.check.noerror(res)
+ for rrset in res.authority:
+ if (
+ rrset.rdtype != rdatatype.NSEC3
+ or "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" not in rrset.name
+ ):
+ continue
+ assert "1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" in str(rrset[0])
+
+ # check optout NSEC3 NXDOMAIN with only insecure delegatons
+ msg = isctest.query.create("nonexist.single-nsec3", "A")
+ res = isctest.query.tcp(msg, "10.53.0.2")
+ isctest.check.nxdomain(res)
+ for rrset in res.authority:
+ if (
+ rrset.rdtype != rdatatype.NSEC3
+ or "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" not in rrset.name
+ ):
+ continue
+ assert "1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" in str(rrset[0])
+
+ # check optout NSEC3 NODATA with only insecure delegatons
+ msg = isctest.query.create("single-nsec3", "A")
+ res = isctest.query.tcp(msg, "10.53.0.2")
+ isctest.check.noerror(res)
+ for rrset in res.authority:
+ if (
+ rrset.rdtype != rdatatype.NSEC3
+ or "3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" not in rrset.name
+ ):
+ continue
+ assert "1 1 1 - 3KL3NK1HKQ4IUEEHBEF12VGFKUETNBAN" in str(rrset[0])
+
+ # check negative unknown NSEC3-OPTOUT hash algorithm does not validate
+ msg = isctest.query.create("optout-unknown.example", "A", dnssec=False)
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res1)
+ isctest.check.servfail(res2)
+
+
+def test_cache(servers):
+ ns4 = servers["ns4"]
+
+ # check that key id's are logged when dumping the cache
+ ns4.rndc("dumpdb -cache", log=False)
+ assert grep_q("; key id = ", "ns4/named_dump.db")
+
+ # check for RRSIG covered type in negative cache
+ assert grep_q("; example. RRSIG NSEC ", "ns4/named_dump.db")
+
+ # check validated data are not cached longer than originalttl
+ msg = isctest.query.create("a.ttlpatch.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.rr_count_eq(res1.answer, 2)
+ isctest.check.rr_count_eq(res2.answer, 2)
+ for rrset in res1.answer:
+ assert rrset.ttl <= 3600
+ for rrset in res2.answer:
+ assert rrset.ttl <= 300
+
+ # query for a record, then follow it with a query for the
+ # corresponding RRSIG, check that it's answered from the cache
+ msg = isctest.query.create("normalthenrrsig.secure.example", "A")
+ isctest.query.tcp(msg, "10.53.0.4")
+
+ msg = isctest.query.create("normalthenrrsig.secure.example", "RRSIG")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.raflag(res2)
+
+ # check direct query for RRSIG: if it's not cached with other records,
+ # it should result in an empty response.
+ msg = isctest.query.create("rrsigonly.secure.example", "RRSIG")
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.empty_answer(res1)
+ isctest.check.noraflag(res1)
+
+ # check that a DNSKEY query with no data still gets cached
+ msg = isctest.query.create("insecure.example", "DNSKEY")
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ time.sleep(1) # give the TTL time to change
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ if res1.authority[0].ttl == res2.authority[0].ttl:
+ time.sleep(1)
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ assert res1.authority[0].ttl != res2.authority[0].ttl
+
+
+def test_insecure_proof_nsec(servers):
+ # 1-server positive
+ msg = isctest.query.create("a.insecure.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # 1-server negative
+ msg = isctest.query.create("q.insecure.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+
+ # 1-server negative with SOA hack
+ msg = isctest.query.create("r.insecure.example", "SOA")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+ assert res2.authority[0].rdtype == rdatatype.SOA
+ assert res2.authority[0].ttl == 0
+
+ # 2-server positive
+ msg = isctest.query.create("a.insecure.secure.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # 2-server negative
+ msg = isctest.query.create("q.insecure.secure.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+
+ # 2-server negative with SOA hack
+ msg = isctest.query.create("r.insecure.secure.example", "SOA")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+
+ # insecurity proof using negative cache
+ ns4 = servers["ns4"]
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("insecure.example", "DS", cd=True)
+ isctest.query.tcp(msg, "10.53.0.4")
+
+ def query_and_check_nxdomain():
+ msg = isctest.query.create("nonexistent.insecure.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.nxdomain(res)
+ return True
+
+ isctest.run.retry_with_timeout(query_and_check_nxdomain, 20)
+
+ # check insecure negative response with an unsigned NSEC
+ # first try the auth server...
+ msg = isctest.query.create("nsec-rrsigs-stripped", "TXT")
+ res1 = isctest.query.udp(msg, "10.53.0.10")
+ isctest.check.noerror(res1)
+ isctest.check.empty_answer(res1)
+ isctest.check.rr_count_eq(res1.authority, 2)
+ isctest.check.rr_count_eq(res1.additional, 0)
+ # make sure there's no RRSIG(NSEC)
+ for rrset in res1.authority:
+ assert rrset.rdtype != rdatatype.RRSIG or rrset.covers != rdatatype.NSEC
+ # now try the resolver
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noadflag(res2)
+
+
+def test_insecure_proof_nsec3():
+ # 1-server
+ msg = isctest.query.create("a.insecure.nsec3.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # 1-server negative
+ msg = isctest.query.create("q.insecure.nsec3.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+
+ # 1-server negative with SOA hack
+ msg = isctest.query.create("r.insecure.nsec3.example", "SOA")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+ assert res2.authority[0].rdtype == rdatatype.SOA
+ assert res2.authority[0].ttl == 0
+
+
+def test_insecure_proof_optout():
+ # 1-server
+ msg = isctest.query.create("a.insecure.optout.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # 1-server negative
+ msg = isctest.query.create("q.insecure.optout.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+
+ # 1-server negative with SOA hack
+ msg = isctest.query.create("r.insecure.optout.example", "SOA")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.noadflag(res2)
+ assert res2.authority[0].rdtype == rdatatype.SOA
+ assert res2.authority[0].ttl == 0
+
+
+def test_below_cname():
+ # check insecure zone below a cname resolves
+ msg = isctest.query.create("insecure.below-cname.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+
+ # check secure zone below a cname resolves and validates
+ msg = isctest.query.create("secure.below-cname.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+ isctest.check.rr_count_eq(res.answer, 2)
+
+
+@pytest.mark.parametrize(
+ "qname",
+ [
+ "a.secure.example", # NSEC/NSEC
+ "a.nsec3.example", # NSEC/NSEC3
+ "a.optout.example", # NSEC/OPTOUT
+ "a.secure.nsec3.example", # NSEC3/NSEC
+ "a.nsec3.nsec3.example", # NSEC3/NSEC3
+ "a.optout.nsec3.example", # NSEC3/OPTOUT
+ "a.secure.optout.example", # OPTOUT/NSEC
+ "a.nsec3.optout.example", # OPTOUT/NSEC3
+ "a.optout.optout.example", # OPTOUT/OPTOUT
+ ],
+)
+def test_positive_validation_multistage(qname):
+ msg = isctest.query.create(qname, "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+
+def test_validation_recovery(servers):
+ ns2 = servers["ns2"]
+ ns4 = servers["ns4"]
+
+ # check recovery from spoofed server address.
+ # prime cache with spoofed address records...
+ msg = isctest.query.create("target.peer-ns-spoof", "A", cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+ ns4.rndc("dumpdb", log=False)
+ grep_q("10.53.0.100", "ns4/named_dump.db")
+
+ # then reload server with properly signed zone
+ shutil.copyfile(
+ "ns2/peer.peer-ns-spoof.db.next", "ns2/peer.peer-ns-spoof.db.signed"
+ )
+ with ns2.watch_log_from_here() as watcher:
+ ns2.rndc("reload peer.peer-ns-spoof", log=False)
+ watcher.wait_for_line("zone peer.peer-ns-spoof/IN: loaded serial 2000042408")
+
+ # and check we can resolve with the correct server address
+ msg = isctest.query.create("test.target.peer-ns-spoof", "TXT")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.nxdomain(res)
+ isctest.check.adflag(res)
+
+ # check recovery from stripped DNSKEY RRSIG.
+ # prime cache with spoofed address records...
+ msg = isctest.query.create("dnskey-rrsigs-stripped", "DNSKEY", cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.rr_count_eq(res.answer, 2)
+
+ # then reload server with properly signed zone
+ shutil.copyfile(
+ "ns2/dnskey-rrsigs-stripped.db.next", "ns2/dnskey-rrsigs-stripped.db.signed"
+ )
+ with ns2.watch_log_from_here() as watcher:
+ ns2.rndc("reload dnskey-rrsigs-stripped", log=False)
+ watcher.wait_for_line(
+ "zone dnskey-rrsigs-stripped/IN: loaded serial 2000042408"
+ )
+
+ # and check we can now resolve with the correct server address
+ msg = isctest.query.create("b.dnskey-rrsigs-stripped", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # check recovery from stripped DS RRSIG.
+ # prime cache with spoofed address records...
+ msg = isctest.query.create("child.ds-rrsigs-stripped", "DS", cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+
+ # then reload server with properly signed zone
+ shutil.copyfile(
+ "ns2/ds-rrsigs-stripped.db.next", "ns2/ds-rrsigs-stripped.db.signed"
+ )
+ with ns2.watch_log_from_here() as watcher:
+ ns2.rndc("reload ds-rrsigs-stripped", log=False)
+ watcher.wait_for_line("zone ds-rrsigs-stripped/IN: loaded serial 2000042408")
+
+ # and check we can now resolve with the correct server address
+ msg = isctest.query.create("b.child.ds-rrsigs-stripped", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+ # check recovery with mismatching NS
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("inconsistent", "NS", dnssec=False, cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noadflag(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+ isctest.check.rr_count_eq(res.additional, 1)
+
+ msg = isctest.query.create("inconsistent", "NS", cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noadflag(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+ isctest.check.rr_count_eq(res.additional, 1)
+
+ msg = isctest.query.create("inconsistent", "NS")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.adflag(res)
+ isctest.check.rr_count_eq(res.answer, 3)
+ isctest.check.rr_count_eq(res.additional, 0)
+
+
+def test_failed_validation():
+ # bogus zone
+ msg = isctest.query.create("a.bogus.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ # missing key record
+ msg = isctest.query.create("a.b.keyless.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+
+
+def test_revoked_key():
+ # validation should succeed if a revoked key is encountered
+ msg = isctest.query.create("revkey.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+
+def test_standby_key():
+ # check that a secure chain with one active and one inactive KSK
+ # validates as secure
+ msg = isctest.query.create("a.lazy-ksk", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+
+def test_transitions():
+ # check that a zone finishing transitioning from one algorithm
+ # to another validates secure
+ msg = isctest.query.create("algroll", "NS")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ # check that validation yields insecure during transition to signed
+ msg = isctest.query.create("inprogress", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+ a, _ = res.answer
+ assert str(a[0]) == "10.53.0.10"
+
+
+def test_validating_forwarder(servers):
+ ns9 = servers["ns9"]
+ ns4 = servers["ns4"]
+
+ # check validating forwarder behavior with mismatching NS
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("inconsistent", "NS", dnssec=False, cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.9")
+ isctest.check.noerror(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+ isctest.check.rr_count_eq(res.additional, 0)
+ isctest.check.noadflag(res)
+
+ msg = isctest.query.create("inconsistent", "NS", cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.9")
+ isctest.check.rr_count_eq(res.additional, 0)
+ isctest.check.noadflag(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+ isctest.check.rr_count_eq(res.authority, 0)
+ isctest.check.rr_count_eq(res.additional, 0)
+
+ msg.flags &= ~flags.CD
+ res = isctest.query.tcp(msg, "10.53.0.9")
+ isctest.check.rr_count_eq(res.answer, 3)
+ isctest.check.rr_count_eq(res.authority, 0)
+ isctest.check.rr_count_eq(res.additional, 0)
+ isctest.check.adflag(res)
+
+ # check validating forwarder sends CD to validate with a local trust anchor
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("localkey.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+
+ with ns9.watch_log_from_here() as watcher:
+ res = isctest.query.tcp(msg, "10.53.0.9")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+ watcher.wait_for_line("status: SERVFAIL")
+
+
+def test_expired_signatures(servers):
+ # check expired signatures are still in place when updates are disabled
+ msg = isctest.query.create("expired.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.3")
+ soa, sigs = res.answer
+ assert sigs
+
+ # check expired signatures do not validate
+ msg = isctest.query.create("expired.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.3")
+ rrsig = res.get_rrset(
+ res.answer,
+ name.from_text("expired.example."),
+ rdataclass.IN,
+ rdatatype.RRSIG,
+ rdatatype.SOA,
+ )
+ assert rrsig, "expected RRSIG(SOA) missing from AUTHORITY: " + str(rrsig)
+ isctest.check.rr_count_eq(res.answer, 2)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+ isctest.check.noadflag(res)
+ if hasattr(res, "extended_errors"):
+ assert res.extended_errors()[0].code == edns.EDECode.SIGNATURE_EXPIRED
+ assert grep_q("expired.example/.*: RRSIG has expired", "ns4/named.run")
+
+ # check future signatures do not validate
+ msg = isctest.query.create("future.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.servfail(res)
+ isctest.check.noadflag(res)
+ if hasattr(res, "extended_errors"):
+ assert res.extended_errors()[0].code == edns.EDECode.SIGNATURE_NOT_YET_VALID
+ assert grep_q(
+ "future.example/.*: RRSIG validity period has not begun", "ns4/named.run"
+ )
+
+ # check that a dynamic zone with future signatures is re-signed on load
+ msg = isctest.query.create("managed-future.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.adflag(res)
+ isctest.check.noerror(res)
+
+ ns4 = servers["ns4"]
+
+ # test TTL is capped at RRSIG expiry time
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("expiring.example", "SOA", cd=True)
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ msg = isctest.query.create("expiring.example", "SOA")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ for rrset in res1.answer:
+ assert rrset.ttl <= 3600
+ for rrset in res2.answer:
+ assert rrset.ttl <= 60
+
+ # test TTL is capped at RRSIG expiry time in the additional section (NS)
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("expiring.example", "NS", cd=True)
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ msg = isctest.query.create("expiring.example", "NS")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ for rrset in res1.additional:
+ assert rrset.ttl <= 3600
+ for rrset in res2.additional:
+ assert rrset.ttl <= 60
+
+ # test TTL is capped at RRSIG expiry time in the additional section (MX)
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("expiring.example", "MX", cd=True)
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ msg = isctest.query.create("expiring.example", "MX")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ for rrset in res1.additional:
+ assert rrset.ttl <= 3600
+ for rrset in res2.additional:
+ assert rrset.ttl <= 60
+
+
+def test_accept_expired(servers, templates):
+ ns4 = servers["ns4"]
+ templates.render("ns4/named.conf", {"accept_expired": True})
+ ns4.reconfigure(log=False)
+
+ # test TTL of about-to-expire rrsets with accept-expired
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("expiring.example", "SOA")
+ msg.flags |= flags.CD
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ msg = isctest.query.create("expiring.example", "SOA")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ for rrset in res1.answer:
+ assert rrset.ttl <= 3600
+ for rrset in res2.answer:
+ assert rrset.ttl <= 120
+
+ # test TTL is capped at RRSIG expiry time in the additional section
+ # with accept-expired
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("expiring.example", "MX")
+ msg.flags |= flags.CD
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ msg = isctest.query.create("expiring.example", "MX")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ for rrset in res1.additional:
+ assert rrset.ttl <= 3600
+ for rrset in res2.additional:
+ assert rrset.ttl <= 120
+
+ # test TTL of expired rrsets with accept-expired
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("expired.example", "SOA")
+ msg.flags |= flags.CD
+ res1 = isctest.query.tcp(msg, "10.53.0.4")
+ msg = isctest.query.create("expired.example", "SOA")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ for rrset in res1.additional:
+ assert rrset.ttl <= 3600
+ for rrset in res2.additional:
+ assert rrset.ttl <= 120
+
+
+def test_casing():
+ # test legacy upper-case signer name validation
+ msg = isctest.query.create("upper.example", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.adflag(res)
+ _, sig = res.answer
+ assert sig.rdtype == rdatatype.RRSIG
+ assert sig.covers == rdatatype.SOA
+ assert "UPPER.EXAMPLE." in str(sig[0])
+
+ # test that we lower-case signer name
+ msg = isctest.query.create("LOWER.EXAMPLE", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ _, sig = res.answer
+ assert sig.rdtype == rdatatype.RRSIG
+ assert sig.covers == rdatatype.SOA
+ assert "lower.example." in str(sig[0])
+
+
+def test_broken_servers():
+ # check that a non-cacheable NODATA works
+ msg = isctest.query.create("a.nosoa.secure.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.6")
+ isctest.check.rr_count_eq(res1.authority, 0)
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res2)
+
+ # check that a non-cacheable NXDOMAIN works
+ msg = isctest.query.create("b.nosoa.secure.example", "TXT")
+ res1 = isctest.query.tcp(msg, "10.53.0.6")
+ isctest.check.rr_count_eq(res1.authority, 0)
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.nxdomain(res2)
+
+ # check that split RRSIGs are handled
+ msg = isctest.query.create("split-rrsig", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.6")
+ soa, _ = res.answer
+ assert soa[0].serial > 1
+
+ # check that not-at-zone-apex RRSIG(SOA) rrsets are removed
+ msg = isctest.query.create("split-rrsig", "AXFR")
+ res = isctest.query.tcp(msg, "10.53.0.6")
+
+ nza = [
+ r
+ for r in res.answer
+ if str(r.name) == "not-at-zone-apex.split-rrsig."
+ and r.rdtype == rdatatype.RRSIG
+ and r.covers == rdatatype.SOA
+ ]
+ assert not nza
+
+ # check validation with missing nearest encloser proof
+ msg = isctest.query.create("b.c.d.optout-tld", "DS")
+ res = isctest.query.tcp(msg, "10.53.0.6")
+ nsec3s = [a for a in res.authority if a.rdtype == rdatatype.NSEC3]
+ assert len(nsec3s) == 2
+
+ msg = isctest.query.create("b.c.d.optout-tld", "A")
+ res = isctest.query.tcp(msg, "10.53.0.6")
+ nsec3s = [a for a in res.authority if a.rdtype == rdatatype.NSEC3]
+ assert len(nsec3s) == 1
+
+ res = isctest.query.tcp(msg, "10.53.0.6")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+ msg = isctest.query.create("optout-tld", "SOA")
+ res = isctest.query.tcp(msg, "10.53.0.6")
+ isctest.check.noadflag(res)
+
+
+def test_pending_ds():
+ # check that a query against a validating resolver succeeds when there is
+ # a negative cache entry with trust level "pending" for the DS. prime
+ # with a +cd DS query to produce the negative cache entry, then send a
+ # query that uses that entry as part of the validation process.
+ ns4.rndc("flush", log=False)
+ msg = isctest.query.create("insecure.example", "DS", cd=True)
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.rr_count_eq(res.authority, 4)
+ msg = isctest.query.create("a.insecure.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.rr_count_eq(res.answer, 1)
+ isctest.check.rr_count_eq(res.authority, 1)
+ isctest.check.noadflag(res)
+
+
+def test_trust_anchors(servers, templates):
+ # DNSSEC tests related to unsupported, disabled and revoked trust anchors.
+ #
+ # This nameserver is loaded with a bunch of trust anchors.
+ # Some of them are good (enabled.managed, enabled.trusted,
+ # secure.managed, secure.trusted), and some of them are bad
+ # (disabled.managed, revoked.managed, unsupported.managed,
+ # disabled.trusted, revoked.trusted, unsupported.trusted). Make sure
+ # that the bad trust anchors are ignored. This is tested by looking
+ # for the corresponding lines in the logfile.
+ ns5 = servers["ns5"]
+ templates.render("ns5/named.conf", {"many_anchors": True})
+ ns5.reconfigure(log=False)
+
+ # check that keys with unsupported/disabled algorithms are ignored
+ grep_q(
+ "ignoring static-key for 'disabled.trusted.': algorithm is disabled",
+ "ns5/named.run",
+ )
+ grep_q(
+ "ignoring static-key for 'disabled.managed.': algorithm is disabled",
+ "ns5/named.run",
+ )
+ grep_q(
+ "ignoring static-key for 'unsupported.trusted.': algorithm is unsupported",
+ "ns5/named.run",
+ )
+ grep_q(
+ "ignoring static-key for 'unsupported.managed.': algorithm is unsupported",
+ "ns5/named.run",
+ )
+ grep_q("ignoring static-key for 'revoked.trusted.': bad key type", "ns5/named.run")
+ grep_q("ignoring static-key for 'revoked.managed.': bad key type", "ns5/named.run")
+
+ # check that a key with supported algorithm validates as secure
+ msg = isctest.query.create("a.secure.trusted", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+ if hasattr(res2, "extended_errors"):
+ assert not res2.extended_errors()
+
+ msg = isctest.query.create("a.secure.managed", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+ if hasattr(res2, "extended_errors"):
+ assert not res2.extended_errors()
+
+ # check that an unsupported signing algorithm yields insecure
+ msg = isctest.query.create("a.unsupported.trusted", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ if hasattr(res2, "extended_errors"):
+ assert (
+ res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
+ )
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ msg = isctest.query.create("a.unsupported.managed", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ if hasattr(res2, "extended_errors"):
+ assert (
+ res2.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
+ )
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # check that a disabled signing algorithm yields insecure
+ msg = isctest.query.create("a.disabled.trusted", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ msg = isctest.query.create("a.disabled.managed", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # check that zone signed with an algorithm that's disabled for
+ # some other domain, but not for this one, validates as secure.
+ # "enabled.trusted." and "enabled.managed." do not match the
+ # "disable-algorithms" option, so no special rules apply. (static)
+ msg = isctest.query.create("a.enabled.trusted", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+ msg = isctest.query.create("a.enabled.managed", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+ # a revoked trust anchor is ignored when configured; check that
+ # this yields insecure.
+ msg = isctest.query.create("a.revoked.trusted", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ msg = isctest.query.create("a.revoked.managed", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.5")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+
+def test_unknown_algorithms():
+ # check that unknown DNSKEY algorithm validates as insecure
+ msg = isctest.query.create("dnskey-unknown.example", "A", dnssec=False)
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+ # check that unsupported DNSKEY algorithms are in the DNSKEY RRsets
+ msg = isctest.query.create("dnskey-unsupported.example", "DNSKEY")
+ res = isctest.query.tcp(msg, "10.53.0.3")
+ isctest.check.noerror(res)
+
+ msg = isctest.query.create("dnskey-unsupported-2.example", "DNSKEY")
+ res = isctest.query.tcp(msg, "10.53.0.3")
+ isctest.check.noerror(res)
+ rrsets = [str(r) for r in res.answer]
+ assert any("257 3 255" in r for r in rrsets)
+
+ # check that unsupported DNSKEY algorithm validates as insecure
+ msg = isctest.query.create("dnskey-unsupported.example", "DNSKEY")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.noadflag(res)
+ if hasattr(res, "extended_errors"):
+ assert (
+ res.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
+ )
+
+ # check that DNSKEY with an unsupported reserve key validates
+ msg = isctest.query.create("dnskey-unsupported-2.example", "DNSKEY")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ # check EDE code 2 for unsupported DS digest algorithm
+ msg = isctest.query.create("a.ds-unsupported.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ if hasattr(res, "extended_errors"):
+ assert res.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DS_DIGEST_TYPE
+
+ # check EDE code 1 for bad algorithm mnemonic
+ msg = isctest.query.create("badalg.secure.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noadflag(res)
+ if hasattr(res, "extended_errors"):
+ assert (
+ res.extended_errors()[0].code == edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM
+ )
+
+ # check both EDE code 1 and 2 for unsupported digest on one DNSKEY
+ # and unsupported algorithm on the other
+ msg = isctest.query.create("a.digest-alg-unsupported.example", "A")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noadflag(res)
+ if hasattr(res, "extended_errors"):
+ codes = {ede.code for ede in res.extended_errors()}
+ assert edns.EDECode.UNSUPPORTED_DNSKEY_ALGORITHM in codes
+ assert edns.EDECode.UNSUPPORTED_DS_DIGEST_TYPE in codes
+
+ # check that unknown DNSKEY algorithm + unknown NSEC3 hash algorithm
+ # validates as insecure
+ msg = isctest.query.create("dnskey-nsec3-unknown.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res1)
+ isctest.check.noerror(res2)
+ isctest.check.noadflag(res2)
+
+
+###################################
+##### BEGIN MANAGED KEY TESTS #####
+###################################
+def test_switch_managed(servers, templates):
+ # switch to intializing trust anchor instead of static
+ ns4 = servers["ns4"]
+ assert os.path.exists("ns4/managed-keys.bind.jnl") is False
+ shutil.copyfile("ns4/managed-keys.bind.in", "ns4/managed-keys.bind")
+ templates.render("ns4/named.conf", {"managed_key": True})
+ ns4.reconfigure(log=False)
+
+
+def test_secure_root_managed(servers):
+ # check that a query for a secure root validates
+ msg = isctest.query.create(".", "KEY")
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.noerror(res)
+ isctest.check.adflag(res)
+
+ # check that "rndc secroots" dumps the trusted keys
+ ns4 = servers["ns4"]
+ key = int(getfrom("ns1/managed.key.id"))
+ alg = os.environ["DEFAULT_ALGORITHM"]
+ expected = f"./{alg}/{key} ; managed"
+ response = ns4.rndc("secroots -", log=False).splitlines()
+ assert expected in response
+ assert len(response) == 10
+
+
+def test_positive_validation_nsec_managed():
+ msg = isctest.query.create("a.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+
+def test_positive_validation_nsec3_managed():
+ msg = isctest.query.create("a.nsec3.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.noerror(res2)
+ isctest.check.adflag(res2)
+
+
+def test_positive_validation_optout_managed():
+ msg = isctest.query.create("a.optout.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.3")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.adflag(res2)
+
+
+def test_negative_validation_nsec_managed():
+ # nxdomain
+ msg = isctest.query.create("q.example", "A")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_answer(res1, res2)
+ isctest.check.nxdomain(res2)
+ isctest.check.adflag(res2)
+
+
+def test_ds_managed():
+ # check root DS queries validate
+ msg = isctest.query.create(".", "DS")
+ res1 = isctest.query.tcp(msg, "10.53.0.1")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.adflag(res2)
+ isctest.check.noerror(res2)
+
+ # check DS queries succeed at RFC 1918 empty zone
+ msg = isctest.query.create("10.in-addr.arpa", "DS")
+ res1 = isctest.query.tcp(msg, "10.53.0.2")
+ res2 = isctest.query.tcp(msg, "10.53.0.4")
+ isctest.check.same_data(res1, res2)
+ isctest.check.noerror(res2)
+
+
+def test_keydata_storage(servers):
+ ns4 = servers["ns4"]
+ ns4.rndc("managed-keys sync", log=False)
+ with isctest.log.WatchLogFromStart("ns4/managed-keys.bind") as watcher:
+ watcher.wait_for_line(["KEYDATA", "next refresh:"])
+
+
+############################################
+##### BEGIN MULTIVIEW VALIDATION TESTS #####
+############################################
+def test_insecure_staticstub_delegation(servers, templates):
+ ns4 = servers["ns4"]
+ templates.render("ns4/named.conf", {"multi_view": True})
+ ns4.reconfigure(log=False)
+
+ # check insecure delegation between static-stub zones
+ msg = isctest.query.create("insecure.secure.example", "NS")
+ for _ in range(5):
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ if res.rcode() == rcode.SERVFAIL:
+ time.sleep(1)
+ continue
+ isctest.check.noerror(res)
+
+ msg = isctest.query.create("secure.example", "NS")
+ for _ in range(5):
+ res = isctest.query.tcp(msg, "10.53.0.4")
+ if res.rcode() == rcode.SERVFAIL:
+ time.sleep(1)
+ continue
+ isctest.check.noerror(res)