#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.63 for unbound 1.3.4.
+# Generated by GNU Autoconf 2.63 for unbound 1.4.0.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
#
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.3.4'
-PACKAGE_STRING='unbound 1.3.4'
+PACKAGE_VERSION='1.4.0'
+PACKAGE_STRING='unbound 1.4.0'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
# Factoring default headers for most tests.
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures unbound 1.3.4 to adapt to many kinds of systems.
+\`configure' configures unbound 1.4.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.3.4:";;
+ short | recursive ) echo "Configuration of unbound 1.4.0:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.3.4
+unbound configure 1.4.0
generated by GNU Autoconf 2.63
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by unbound $as_me 1.3.4, which was
+It was created by unbound $as_me 1.4.0, which was
generated by GNU Autoconf 2.63. Invocation command line was
$ $0 $@
LIBUNBOUND_CURRENT=1
-LIBUNBOUND_REVISION=4
+LIBUNBOUND_REVISION=5
LIBUNBOUND_AGE=0
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
# 1.3.2 had 1:2:0
# 1.3.3 had 1:3:0
# 1.3.4 had 1:4:0
+# 1.4.0 had 1:5:0
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:7281: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:7282: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:7284: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:7285: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:7287: output\"" >&5)
+ (eval echo "\"\$as_me:7288: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 8492 "configure"' > conftest.$ac_ext
+ echo '#line 8493 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:9859: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9860: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:9863: \$? = $ac_status" >&5
+ echo "$as_me:9864: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:10198: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:10199: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:10202: \$? = $ac_status" >&5
+ echo "$as_me:10203: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:10303: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:10304: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:10307: \$? = $ac_status" >&5
+ echo "$as_me:10308: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:10358: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:10359: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:10362: \$? = $ac_status" >&5
+ echo "$as_me:10363: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 13161 "configure"
+#line 13162 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 13257 "configure"
+#line 13258 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by unbound $as_me 1.3.4, which was
+This file was extended by unbound $as_me 1.4.0, which was
generated by GNU Autoconf 2.63. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
-unbound config.status 1.3.4
+unbound config.status 1.4.0
configured by $0, generated by GNU Autoconf 2.63,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
sinclude(acx_python.m4)
sinclude(ac_pkg_swig.m4)
-AC_INIT(unbound, 1.3.4, unbound-bugs@nlnetlabs.nl, unbound)
+AC_INIT(unbound, 1.4.0, unbound-bugs@nlnetlabs.nl, unbound)
LIBUNBOUND_CURRENT=1
-LIBUNBOUND_REVISION=4
+LIBUNBOUND_REVISION=5
LIBUNBOUND_AGE=0
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
# 1.3.2 had 1:2:0
# 1.3.3 had 1:3:0
# 1.3.4 had 1:4:0
+# 1.4.0 had 1:5:0
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
- Fixed security bug where the signatures for NSEC3 records were not
checked when checking for absence of DS records. This could have
enabled the substitution of an insecure delegation.
+ - moved version number to 1.4.0 because of 1.3.4 release with only
+ the NSEC3 patch from the entry above.
+ - val-log-level: 2 shows extended error information for validation
+ failures, but still one (longish) line per failure. For example:
+ validation failure <example.com. DNSKEY IN>: signature expired from
+ 192.0.2.4 for trust anchor example.com. while building chain of trust
+ validation failure <www.example.com. A IN>: no signatures from
+ 192.0.2.6 for key example.com. while building chain of trust
6 October 2009: Wouter
- Test set updated to provide additional ns lookup result.
fprintf(cfg, " chroot: \"\"\n");
fprintf(cfg, " username: \"\"\n");
fprintf(cfg, " pidfile: \"\"\n");
+ fprintf(cfg, " val-log-level: 2\n");
while(fgets(line, MAX_LINE_LEN-1, in)) {
parse = line;
(*lineno)++;
struct query_info* qinfo)
{
enum sec_status sec;
+ char* reason = NULL;
if(vsig) {
log_nametypeclass(VERB_QUERY, "verify of rrset",
rrset->rk.dname, ntohs(rrset->rk.type),
ntohs(rrset->rk.rrset_class));
}
- sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey);
+ sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, &reason);
if(vsig) {
- printf("verify outcome is: %s\n", sec_status_to_string(sec));
+ printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
+ reason?reason:"");
}
if(should_be_bogus(rrset, qinfo)) {
unit_assert(sec == sec_status_bogus);
--- /dev/null
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with NSEC3 with no DS referral with bad signature.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA REFUSED
+SECTION QUESTION
+ns.example.com. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2007090400 28800 7200 604800 18000
+example.com. 3600 IN RRSIG SOA 3 2 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCM6lsu9byZIQ1yYjJmyYfFWM2RWAIUcR5t84r2La824oWCkLjmHXRQlco= ;{id = 2854}
+
+; NODATA response. H(www.example.com.) = s1unhcti19bkdr98fegs0v46mbu3t4m3
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd s1unhcti19bkdr98fegs0v46mbu3t4m4 MX RRSIG
+s1unhcti19bkdr98fegs0v46mbu3t4m3.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MCwCFE/a24nsY2luhQmZjY/ObAIgNSMkAhQWd4MUOUVK55bD6AbMHWrDA0yvEA== ;{id = 2854}
+
+ENTRY_END
+
+; refer to server one down
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+; proof that there is no DS here.
+;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854}
+; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG
+; bad signature:
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20010926135752 20010829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+;8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.10
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION AUTHORITY
+; proof that there is no DS here.
+;sub.example.com. 3600 IN DS 2854 DSA 1 be4d46cd7489cce25a31af0dff2968ce0425dd31
+;sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQC1WMTfb25sTgeUEXCFR4+YiJqecwIUc2R/jrO4amyQxovSnld2reg8eyo= ;{id = 2854}
+; sub.example.com. -> 8r1f0ieoutlnjc03meng9e3bn2n0o9pd.
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. IN NSEC3 1 1 123 aabb00123456bbccdd 8r1f0ieoutlnjc03meng9e3bn3n0o9pd NS RRSIG
+; bad signature
+8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20010926135752 20010829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+;8r1f0ieoutlnjc03meng9e3bn2n0o9pd.example.com. 3600 IN RRSIG NSEC3 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFEC78oZJjqlV6kVyQb4X0o6tsUpUAhUAk+bgth7eeN+aO8ts2+yLSyzSX9g= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.10
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR REFUSED
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+ENTRY_END
+
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+sub.example.com. 3600 IN RRSIG DNSKEY 3 3 3600 20070926135752 20070829135752 2854 sub.example.com. MCwCFBznBTYM/SrdUnjQdBnLtRO79KAaAhQReG5nRuL7Xsdf6D0KKwPa1GpWyQ== ;{id = 2854}
+
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 1.2.3.123
+www.sub.example.com. 3600 IN RRSIG A 3 4 3600 20070926135752 20070829135752 2854 sub.example.com. MC0CFEExteiCsLkRi/md6o5K8BhRJAKFAhUAgg2tkvwaDn8Xbm9q+5xnjvgIB8k= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
--- /dev/null
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with no signatures after secure delegation
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+;sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+;sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+;ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+;www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA SERVFAIL
+SECTION QUESTION
+www.sub.example.com. IN A
+ENTRY_END
+
+SCENARIO_END
verify_dnskey(struct module_env* env, struct val_env* ve,
struct trust_anchor* tp, struct ub_packed_rrset_key* rrset)
{
+ char* reason = NULL;
if(tp->ds_rrset) {
/* verify with ds, any will do to prime autotrust */
enum sec_status sec = val_verify_DNSKEY_with_DS(
- env, ve, rrset, tp->ds_rrset);
+ env, ve, rrset, tp->ds_rrset, &reason);
verbose(VERB_ALGO, "autotrust: validate DNSKEY with DS: %s",
sec_status_to_string(sec));
if(sec == sec_status_secure) {
if(tp->dnskey_rrset) {
/* verify with keys */
enum sec_status sec = val_verify_rrset(env, ve, rrset,
- tp->dnskey_rrset);
+ tp->dnskey_rrset, &reason);
verbose(VERB_ALGO, "autotrust: validate DNSKEY with keys: %s",
sec_status_to_string(sec));
if(sec == sec_status_secure) {
struct ub_packed_rrset_key* dnskey_rrset, size_t i)
{
enum sec_status sec;
+ char* reason = NULL;
verbose(VERB_ALGO, "seen REVOKE flag, check self-signed, rr %d",
(int)i);
- sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i);
+ sec = dnskey_verify_rrset(env, ve, dnskey_rrset, dnskey_rrset, i,
+ &reason);
return (sec == sec_status_secure);
}
uint8_t* wc = NULL, *ce = NULL;
int valid_nsec = 0;
struct ub_packed_rrset_key* wc_nsec = NULL;
+ char* reason = NULL;
/* If we have a NSEC at the same name, it must prove one
* of two things
* 1) this is a delegation point and there is no DS
* 2) this is not a delegation point */
if(nsec) {
- sec = val_verify_rrset_entry(env, ve, nsec, kkey);
+ sec = val_verify_rrset_entry(env, ve, nsec, kkey, &reason);
if(sec != sec_status_secure) {
verbose(VERB_ALGO, "NSEC RRset for the "
"referral did not verify.");
i++) {
if(rep->rrsets[i]->rk.type != htons(LDNS_RR_TYPE_NSEC))
continue;
- sec = val_verify_rrset_entry(env, ve, rep->rrsets[i], kkey);
+ sec = val_verify_rrset_entry(env, ve, rep->rrsets[i], kkey,
+ &reason);
if(sec != sec_status_secure) {
verbose(VERB_ALGO, "NSEC for empty non-terminal "
"did not verify.");
{
size_t i;
enum sec_status sec;
+ char* reason = NULL;
for(i=0; i<num; i++) {
if(list[i]->rk.type != htons(LDNS_RR_TYPE_NSEC3))
continue;
- sec = val_verify_rrset_entry(env, ve, list[i], kkey);
+ sec = val_verify_rrset_entry(env, ve, list[i], kkey, &reason);
if(sec != sec_status_secure) {
verbose(VERB_ALGO, "NSEC3 did not verify");
return 0;
enum sec_status
dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
- struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey)
+ struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
+ char** reason)
{
enum sec_status sec;
size_t i, num, numneeds;
rbtree_t* sortree = NULL;
/* make sure that for all DNSKEY algorithms there are valid sigs */
uint8_t needs[256]; /* 1 if need sig for that algorithm */
+ int sawbogus = 0;
num = rrset_get_sigcount(rrset);
if(num == 0) {
verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
"signatures");
+ *reason = "no signatures";
return sec_status_bogus;
}
numneeds = dnskeyset_needs(dnskey, needs);
for(i=0; i<num; i++) {
sec = dnskeyset_verify_rrset_sig(env, ve, *env->now, rrset,
- dnskey, i, &sortree);
+ dnskey, i, &sortree, reason);
/* see which algorithm has been fixed up */
if(sec == sec_status_secure) {
uint8_t a = (uint8_t)rrset_get_sig_algo(rrset, i);
return sec;
}
}
+ else if(sec == sec_status_bogus)
+ sawbogus = 1;
}
verbose(VERB_ALGO, "rrset failed to verify: no valid signatures for "
"%d algorithms", (int)numneeds);
+ if(!sawbogus)
+ *reason = "no signatures for all algorithms";
return sec_status_bogus;
}
enum sec_status
dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
- size_t dnskey_idx)
+ size_t dnskey_idx, char** reason)
{
enum sec_status sec;
- size_t i, num;
+ size_t i, num, numchecked = 0;
rbtree_t* sortree = NULL;
int buf_canon = 0;
uint16_t tag = dnskey_calc_keytag(dnskey, dnskey_idx);
if(num == 0) {
verbose(VERB_QUERY, "rrset failed to verify due to a lack of "
"signatures");
+ *reason = "no signatures";
return sec_status_bogus;
}
for(i=0; i<num; i++) {
buf_canon = 0;
sec = dnskey_verify_rrset_sig(env->scratch,
env->scratch_buffer, ve, *env->now, rrset,
- dnskey, dnskey_idx, i, &sortree, &buf_canon);
+ dnskey, dnskey_idx, i, &sortree, &buf_canon, reason);
if(sec == sec_status_secure)
return sec;
+ numchecked ++;
}
verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
+ if(!numchecked) *reason = "signatures from unknown keys";
return sec_status_bogus;
}
dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
uint32_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
- struct rbtree_t** sortree)
+ struct rbtree_t** sortree, char** reason)
{
/* find matching keys and check them */
enum sec_status sec = sec_status_bogus;
/* see if key verifies */
sec = dnskey_verify_rrset_sig(env->scratch,
env->scratch_buffer, ve, now, rrset, dnskey, i,
- sig_idx, sortree, &buf_canon);
+ sig_idx, sortree, &buf_canon, reason);
if(sec == sec_status_secure)
return sec;
}
if(numchecked == 0) {
+ *reason = "signatures from unknown keys";
verbose(VERB_QUERY, "verify: could not find appropriate key");
return sec_status_bogus;
}
/** check rrsig dates */
static int
check_dates(struct val_env* ve, uint32_t unow,
- uint8_t* expi_p, uint8_t* incep_p)
+ uint8_t* expi_p, uint8_t* incep_p, char** reason)
{
/* read out the dates */
int32_t expi, incep, now;
if(incep - expi > 0) {
sigdate_error("verify: inception after expiration, "
"signature bad", expi, incep, now);
+ *reason = "signature inception after expiration";
return 0;
}
if(incep - now > 0) {
if(incep - now > skew) {
sigdate_error("verify: signature bad, current time is"
" before inception date", expi, incep, now);
+ *reason = "signature before inception date";
return 0;
}
sigdate_error("verify warning suspicious signature inception "
if(now - expi > skew) {
sigdate_error("verify: signature expired", expi,
incep, now);
+ *reason = "signature expired";
return 0;
}
sigdate_error("verify warning suspicious signature expiration "
struct val_env* ve, uint32_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
- struct rbtree_t** sortree, int* buf_canon)
+ struct rbtree_t** sortree, int* buf_canon, char** reason)
{
enum sec_status sec;
uint8_t* sig; /* RRSIG rdata */
/* min length of rdatalen, fixed rrsig, root signer, 1 byte sig */
if(siglen < 2+20) {
verbose(VERB_QUERY, "verify: signature too short");
+ *reason = "signature too short";
return sec_status_bogus;
}
if(!(dnskey_get_flags(dnskey, dnskey_idx) & DNSKEY_BIT_ZSK)) {
verbose(VERB_QUERY, "verify: dnskey without ZSK flag");
+ *reason = "dnskey without ZSK flag";
return sec_status_bogus;
}
if(dnskey_get_protocol(dnskey, dnskey_idx) != LDNS_DNSSEC_KEYPROTO) {
/* RFC 4034 says DNSKEY PROTOCOL MUST be 3 */
verbose(VERB_QUERY, "verify: dnskey has wrong key protocol");
+ *reason = "dnskey has wrong protocolnumber";
return sec_status_bogus;
}
signer_len = dname_valid(signer, siglen-2-18);
if(!signer_len) {
verbose(VERB_QUERY, "verify: malformed signer name");
+ *reason = "signer name malformed";
return sec_status_bogus; /* signer name invalid */
}
if(!dname_subdomain_c(rrset->rk.dname, signer)) {
verbose(VERB_QUERY, "verify: signer name is off-tree");
+ *reason = "signer name off-tree";
return sec_status_bogus; /* signer name offtree */
}
sigblock = (unsigned char*)signer+signer_len;
if(siglen < 2+18+signer_len+1) {
verbose(VERB_QUERY, "verify: too short, no signature data");
+ *reason = "signature too short, no signature data";
return sec_status_bogus; /* sig rdf is < 1 byte */
}
sigblock_len = (unsigned int)(siglen - 2 - 18 - signer_len);
signer, 0, 0);
log_nametypeclass(VERB_QUERY, "the key name is",
dnskey->rk.dname, 0, 0);
+ *reason = "signer name mismatches key name";
return sec_status_bogus;
}
/* memcmp works because type is in network format for rrset */
if(memcmp(sig+2, &rrset->rk.type, 2) != 0) {
verbose(VERB_QUERY, "verify: wrong type covered");
+ *reason = "signature covers wrong type";
return sec_status_bogus;
}
/* verify keytag and sig algo (possibly again) */
if((int)sig[2+2] != dnskey_get_algo(dnskey, dnskey_idx)) {
verbose(VERB_QUERY, "verify: wrong algorithm");
+ *reason = "signature has wrong algorithm";
return sec_status_bogus;
}
ktag = htons(dnskey_calc_keytag(dnskey, dnskey_idx));
if(memcmp(sig+2+16, &ktag, 2) != 0) {
verbose(VERB_QUERY, "verify: wrong keytag");
+ *reason = "signature has wrong keytag";
return sec_status_bogus;
}
/* verify labels is in a valid range */
if((int)sig[2+3] > dname_signame_label_count(rrset->rk.dname)) {
verbose(VERB_QUERY, "verify: labelcount out of range");
+ *reason = "signature labelcount out of range";
return sec_status_bogus;
}
/* original ttl, always ok */
/* verify inception, expiration dates */
- if(!check_dates(ve, now, sig+2+8, sig+2+12)) {
+ if(!check_dates(ve, now, sig+2+8, sig+2+12, reason)) {
return sec_status_bogus;
}
/* check if TTL is too high - reduce if so */
if(sec == sec_status_secure) {
adjust_ttl(ve, now, rrset, sig+2+4, sig+2+8, sig+2+12);
- }
+ } else if(sec == sec_status_bogus)
+ *reason = "signature crypto failed";
return sec;
}
* @param ve: validator environment, date settings.
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset to try.
+ * @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @return SECURE if one key in the set verifies one rrsig.
* UNCHECKED on allocation errors, unsupported algorithms, malformed data,
* and BOGUS on verification failures (no keys match any signatures).
*/
enum sec_status dnskeyset_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
- struct ub_packed_rrset_key* dnskey);
+ struct ub_packed_rrset_key* dnskey, char** reason);
/**
* verify rrset against one specific dnskey (from rrset)
* @param rrset: to be validated.
* @param dnskey: DNSKEY rrset, keyset.
* @param dnskey_idx: which key from the rrset to try.
+ * @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @return secure if *this* key signs any of the signatures on rrset.
* unchecked on error or and bogus on bad signature.
*/
enum sec_status dnskey_verify_rrset(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
- struct ub_packed_rrset_key* dnskey, size_t dnskey_idx);
+ struct ub_packed_rrset_key* dnskey, size_t dnskey_idx, char** reason);
/**
* verify rrset, with dnskey rrset, for a specific rrsig in rrset
* @param sig_idx: which signature to try to validate.
* @param sortree: reused sorted order. Stored in region. Pass NULL at start,
* and for a new rrset.
+ * @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @return secure if any key signs *this* signature. bogus if no key signs it,
* or unchecked on error.
*/
enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
struct val_env* ve, uint32_t now, struct ub_packed_rrset_key* rrset,
struct ub_packed_rrset_key* dnskey, size_t sig_idx,
- struct rbtree_t** sortree);
+ struct rbtree_t** sortree, char** reason);
/**
* verify rrset, with specific dnskey(from set), for a specific rrsig
* @param buf_canon: if true, the buffer is already canonical.
* pass false at start. pass old value only for same rrset and same
* signature (but perhaps different key) for reuse.
+ * @param reason: if bogus, a string returned, fixed or alloced in scratch.
* @return secure if this key signs this signature. unchecked on error or
* bogus if it did not validate.
*/
ldns_buffer* buf, struct val_env* ve, uint32_t now,
struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* dnskey,
size_t dnskey_idx, size_t sig_idx,
- struct rbtree_t** sortree, int* buf_canon);
+ struct rbtree_t** sortree, int* buf_canon, char** reason);
/**
* canonical compare for two tree entries
#include "util/net_help.h"
#include "util/module.h"
#include "util/regional.h"
+#include "util/config_file.h"
enum val_classification
val_classify_response(uint16_t query_flags, struct query_info* origqinf,
enum sec_status
val_verify_rrset(struct module_env* env, struct val_env* ve,
- struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys)
+ struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
+ char** reason)
{
enum sec_status sec;
struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
}
log_nametypeclass(VERB_ALGO, "verify rrset", rrset->rk.dname,
ntohs(rrset->rk.type), ntohs(rrset->rk.rrset_class));
- sec = dnskeyset_verify_rrset(env, ve, rrset, keys);
+ sec = dnskeyset_verify_rrset(env, ve, rrset, keys, reason);
verbose(VERB_ALGO, "verify result: %s", sec_status_to_string(sec));
regional_free_all(env->scratch);
enum sec_status
val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
- struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey)
+ struct ub_packed_rrset_key* rrset, struct key_entry_key* kkey,
+ char** reason)
{
/* temporary dnskey rrset-key */
struct ub_packed_rrset_key dnskey;
dnskey.rk.dname_len = kkey->namelen;
dnskey.entry.key = &dnskey;
dnskey.entry.data = kd->rrset_data;
- sec = val_verify_rrset(env, ve, rrset, &dnskey);
+ sec = val_verify_rrset(env, ve, rrset, &dnskey, reason);
return sec;
}
static enum sec_status
verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
- struct ub_packed_rrset_key* ds_rrset, size_t ds_idx)
+ struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason)
{
enum sec_status sec = sec_status_bogus;
- size_t i, num;
+ size_t i, num, numchecked = 0, numhashok = 0;
num = rrset_get_count(dnskey_rrset);
for(i=0; i<num; i++) {
/* Skip DNSKEYs that don't match the basic criteria. */
!= ds_get_keytag(ds_rrset, ds_idx)) {
continue;
}
+ numchecked++;
verbose(VERB_ALGO, "attempt DS match algo %d keytag %d",
ds_get_key_algo(ds_rrset, ds_idx),
ds_get_keytag(ds_rrset, ds_idx));
verbose(VERB_ALGO, "DS match attempt failed");
continue;
}
+ numhashok++;
verbose(VERB_ALGO, "DS match digest ok, trying signature");
/* Otherwise, we have a match! Make sure that the DNSKEY
* verifies *with this key* */
sec = dnskey_verify_rrset(env, ve, dnskey_rrset,
- dnskey_rrset, i);
+ dnskey_rrset, i, reason);
if(sec == sec_status_secure) {
return sec;
}
/* If it didn't validate with the DNSKEY, try the next one! */
}
+ if(numchecked == 0)
+ *reason = "no keys have a DS";
+ else if(numhashok == 0)
+ *reason = "DS hash mismatches key";
+ else if(!*reason)
+ *reason = "keyset not secured by DNSKEY that matches DS";
return sec_status_bogus;
}
enum sec_status
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
- struct ub_packed_rrset_key* ds_rrset)
+ struct ub_packed_rrset_key* ds_rrset, char** reason)
{
/* as long as this is false, we can consider this DS rrset to be
* equivalent to no DS rrset. */
!= 0) {
verbose(VERB_QUERY, "DNSKEY RRset did not match DS RRset "
"by name");
+ *reason = "DNSKEY RRset did not match DS RRset by name";
return sec_status_bogus;
}
has_useful_ds = true;
sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
- ds_rrset, i);
+ ds_rrset, i, reason);
if(sec == sec_status_secure) {
verbose(VERB_ALGO, "DS matched DNSKEY.");
return sec_status_secure;
struct key_entry_key*
val_verify_new_DNSKEYs(struct regional* region, struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
- struct ub_packed_rrset_key* ds_rrset)
+ struct ub_packed_rrset_key* ds_rrset, char** reason)
{
enum sec_status sec = val_verify_DNSKEY_with_DS(env, ve,
- dnskey_rrset, ds_rrset);
+ dnskey_rrset, ds_rrset, reason);
if(sec == sec_status_secure) {
return key_entry_create_rrset(region,
sock_list_prepend(blacklist, origin);
else sock_list_merge(blacklist, region, origin);
}
+
+void val_errinf(struct module_qstate* qstate, struct val_qstate* vq,
+ const char* str)
+{
+ struct config_strlist* p;
+ if(qstate->env->cfg->val_log_level < 2 || !str)
+ return;
+ p = (struct config_strlist*)regional_alloc(qstate->region, sizeof(*p));
+ if(!p) {
+ log_err("malloc failure in validator-error-info string");
+ return;
+ }
+ p->next = NULL;
+ p->str = regional_strdup(qstate->region, str);
+ if(!p->str) {
+ log_err("malloc failure in validator-error-info string");
+ return;
+ }
+ /* add at end */
+ if(vq->errinf) {
+ struct config_strlist* q = vq->errinf;
+ while(q->next)
+ q = q->next;
+ q->next = p;
+ } else vq->errinf = p;
+}
+
+void val_errinf_origin(struct module_qstate* qstate, struct val_qstate* vq,
+ struct sock_list *origin)
+{
+ struct sock_list* p;
+ if(qstate->env->cfg->val_log_level < 2)
+ return;
+ for(p=origin; p; p=p->next) {
+ char buf[256];
+ if(p == origin)
+ snprintf(buf, sizeof(buf), "from ");
+ else snprintf(buf, sizeof(buf), "and from ");
+ if(p->len == 0)
+ snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf),
+ "cache");
+ else
+ addr_to_str(&p->addr, p->len, buf+strlen(buf),
+ sizeof(buf)-strlen(buf));
+ val_errinf(qstate, vq, buf);
+ }
+}
+
+char* val_errinf_to_str(struct module_qstate* qstate, struct val_qstate* vq)
+{
+ char buf[20480];
+ char* p = buf;
+ size_t left = sizeof(buf);
+ struct config_strlist* s;
+ char dname[LDNS_MAX_DOMAINLEN+1];
+ char* t = ldns_rr_type2str(qstate->qinfo.qtype);
+ char* c = ldns_rr_class2str(qstate->qinfo.qclass);
+ if(!t || !c) {
+ free(t);
+ free(c);
+ log_err("malloc failure in errinf_to_str");
+ return NULL;
+ }
+ dname_str(qstate->qinfo.qname, dname);
+ snprintf(p, left, "validation failure <%s %s %s>:", dname, t, c);
+ free(t);
+ free(c);
+ left -= strlen(p); p += strlen(p);
+ if(!vq->errinf)
+ snprintf(p, left, " misc failure");
+ else for(s=vq->errinf; s; s=s->next) {
+ snprintf(p, left, " %s", s->str);
+ left -= strlen(p); p += strlen(p);
+ }
+ p = strdup(buf);
+ if(!p)
+ log_err("malloc failure in errinf_to_str");
+ return p;
+}
+
+void val_errinf_rrset(struct module_qstate* qstate, struct val_qstate* vq,
+ struct ub_packed_rrset_key *rr)
+{
+ char buf[1024];
+ char dname[LDNS_MAX_DOMAINLEN+1];
+ char *t, *c;
+ if(qstate->env->cfg->val_log_level < 2 || !rr)
+ return;
+ t = ldns_rr_type2str(ntohs(rr->rk.type));
+ c = ldns_rr_class2str(ntohs(rr->rk.rrset_class));
+ if(!t || !c) {
+ free(t);
+ free(c);
+ log_err("malloc failure in errinf_rrset");
+ return;
+ }
+ dname_str(qstate->qinfo.qname, dname);
+ snprintf(buf, sizeof(buf), "for <%s %s %s>", dname, t, c);
+ free(t);
+ free(c);
+ val_errinf(qstate, vq, buf);
+}
+
+void val_errinf_dname(struct module_qstate* qstate, struct val_qstate* vq,
+ const char* str, uint8_t* dname)
+{
+ char b[1024];
+ char buf[LDNS_MAX_DOMAINLEN+1];
+ if(qstate->env->cfg->val_log_level < 2 || !str || !dname)
+ return;
+ dname_str(dname, buf);
+ snprintf(b, sizeof(b), "%s %s", str, buf);
+ val_errinf(qstate, vq, b);
+}
struct val_anchors;
struct rrset_cache;
struct sock_list;
+struct module_qstate;
+struct val_qstate;
/**
* Response classifications for the validator. The different types of proofs.
* @param ve: validator environment (verification settings)
* @param rrset: what to verify
* @param keys: dnskey rrset to verify with.
+ * @param reason: reason of failure. Fixed string or alloced in scratch.
* @return security status of verification.
*/
enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
- struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys);
+ struct ub_packed_rrset_key* rrset, struct ub_packed_rrset_key* keys,
+ char** reason);
/**
* Verify RRset with keys from a keyset.
* @param ve: validator environment (verification settings)
* @param rrset: what to verify
* @param kkey: key_entry to verify with.
+ * @param reason: reason of failure. Fixed string or alloced in scratch.
* @return security status of verification.
*/
enum sec_status val_verify_rrset_entry(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* rrset,
- struct key_entry_key* kkey);
+ struct key_entry_key* kkey, char** reason);
/**
* Verify DNSKEYs with DS rrset. Like val_verify_new_DNSKEYs but
* @param ve: validator environment (verification settings)
* @param dnskey_rrset: DNSKEY rrset to verify
* @param ds_rrset: DS rrset to verify with.
+ * @param reason: reason of failure. Fixed string or alloced in scratch.
* @return: sec_status_secure if a DS matches.
* sec_status_insecure if end of trust (i.e., unknown algorithms).
* sec_status_bogus if it fails.
*/
enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
struct val_env* ve, struct ub_packed_rrset_key* dnskey_rrset,
- struct ub_packed_rrset_key* ds_rrset);
+ struct ub_packed_rrset_key* ds_rrset, char** reason);
/**
* Verify new DNSKEYs with DS rrset. The DS contains hash values that should
* @param ve: validator environment (verification settings)
* @param dnskey_rrset: DNSKEY rrset to verify
* @param ds_rrset: DS rrset to verify with.
+ * @param reason: reason of failure. Fixed string or alloced in scratch.
* @return a KeyEntry. This will either contain the now trusted
* dnskey_rrset, a "null" key entry indicating that this DS
* rrset/DNSKEY pair indicate an secure end to the island of trust
struct key_entry_key* val_verify_new_DNSKEYs(struct regional* region,
struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
- struct ub_packed_rrset_key* ds_rrset);
+ struct ub_packed_rrset_key* ds_rrset, char** reason);
/**
* Determine if DS rrset is usable for validator or not.
void val_blacklist(struct sock_list** blacklist, struct regional* region,
struct sock_list* origin, int cross);
+/**
+ * Append text to the error info for validation.
+ * @param qstate: query state.
+ * @param vq: validator state.
+ * @param str: copied into query region and appended.
+ * Failures to allocate are logged.
+ */
+void val_errinf(struct module_qstate* qstate, struct val_qstate* vq,
+ const char* str);
+
+/**
+ * Append text to error info: from 1.2.3.4
+ * @param qstate: query state.
+ * @param vq: validator state.
+ * @param list: sock list with origin of trouble.
+ * Every element added.
+ * If NULL: nothing is added.
+ * if 0len element: 'from cache' is added.
+ */
+void val_errinf_origin(struct module_qstate* qstate, struct val_qstate* vq,
+ struct sock_list *origin);
+
+/**
+ * Append text to error info: for RRset name type class
+ * @param qstate: query state.
+ * @param vq: validator state.
+ * @param rr: rrset_key.
+ */
+void val_errinf_rrset(struct module_qstate* qstate, struct val_qstate* vq,
+ struct ub_packed_rrset_key *rr);
+
+/**
+ * Append text to error info: str dname
+ * @param qstate: query state.
+ * @param vq: validator state.
+ * @param str: explanation string
+ * @param dname: the dname.
+ * @param rr: rrset_key.
+ */
+void val_errinf_dname(struct module_qstate* qstate, struct val_qstate* vq,
+ const char* str, uint8_t* dname);
+
+/**
+ * Create error info in string
+ * @param qstate: query state. (for query name)
+ * @param vq: validator state.
+ * @return string or NULL on malloc failure (already logged).
+ * This string is malloced and has to be freed by caller.
+ */
+char* val_errinf_to_str(struct module_qstate* qstate, struct val_qstate* vq);
+
#endif /* VALIDATOR_VAL_UTILS_H */
* trusted DNSKEY rrset that signs this response must already have been
* completed.
*
+ * @param qstate: query state.
+ * @param vq: validator query state.
* @param env: module env for verify.
* @param ve: validator env for verify.
* @param qchase: query that was made.
* fail to verify. The message is then set to bogus.
*/
static int
-validate_msg_signatures(struct module_env* env, struct val_env* ve,
- struct query_info* qchase, struct reply_info* chase_reply,
- struct key_entry_key* key_entry)
+validate_msg_signatures(struct module_qstate* qstate, struct val_qstate* vq,
+ struct module_env* env, struct val_env* ve, struct query_info* qchase,
+ struct reply_info* chase_reply, struct key_entry_key* key_entry)
{
uint8_t* sname;
size_t i, slen;
struct ub_packed_rrset_key* s;
enum sec_status sec;
int dname_seen = 0;
+ char* reason = NULL;
/* validate the ANSWER section */
for(i=0; i<chase_reply->an_numrrsets; i++) {
}
/* Verify the answer rrset */
- sec = val_verify_rrset_entry(env, ve, s, key_entry);
+ sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason);
/* If the (answer) rrset failed to validate, then this
* message is BAD. */
if(sec != sec_status_secure) {
log_nametypeclass(VERB_QUERY, "validator: response "
"has failed ANSWER rrset:", s->rk.dname,
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
+ val_errinf(qstate, vq, reason);
+ if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME)
+ val_errinf(qstate, vq, "for CNAME");
+ else if(ntohs(s->rk.type) == LDNS_RR_TYPE_DNAME)
+ val_errinf(qstate, vq, "for DNAME");
+ val_errinf_origin(qstate, vq, qstate->reply_origin);
chase_reply->security = sec_status_bogus;
return 0;
}
for(i=chase_reply->an_numrrsets; i<chase_reply->an_numrrsets+
chase_reply->ns_numrrsets; i++) {
s = chase_reply->rrsets[i];
- sec = val_verify_rrset_entry(env, ve, s, key_entry);
+ sec = val_verify_rrset_entry(env, ve, s, key_entry, &reason);
/* If anything in the authority section fails to be secure,
* we have a bad message. */
if(sec != sec_status_secure) {
log_nametypeclass(VERB_QUERY, "validator: response "
"has failed AUTHORITY rrset:", s->rk.dname,
ntohs(s->rk.type), ntohs(s->rk.rrset_class));
+ val_errinf(qstate, vq, reason);
+ val_errinf_rrset(qstate, vq, s);
+ val_errinf_origin(qstate, vq, qstate->reply_origin);
chase_reply->security = sec_status_bogus;
return 0;
}
/* leave others unchecked, those get removed later on too */
val_find_rrset_signer(s, &sname, &slen);
if(sname && query_dname_compare(sname, key_entry->name)==0)
- (void)val_verify_rrset_entry(env, ve, s, key_entry);
+ (void)val_verify_rrset_entry(env, ve, s, key_entry,
+ &reason);
/* the additional section can fail to be secure,
* it is optional, check signature in case we need
* to clean the additional section later. */
return 1;
}
+ if(key_entry_isbad(vq->key_entry)) {
+ log_nametypeclass(VERB_DETAIL, "Could not establish a chain "
+ "of trust to keys for", vq->key_entry->name,
+ LDNS_RR_TYPE_DNSKEY, vq->key_entry->key_class);
+ vq->chase_reply->security = sec_status_bogus;
+ val_errinf(qstate, vq, "while building chain of trust");
+ return 1;
+ }
+
/* signerName being null is the indicator that this response was
* unsigned */
if(vq->signer_name == NULL) {
"signer name", &vq->qchase);
verbose(VERB_DETAIL, "Could not establish validation of "
"INSECURE status of unsigned response.");
- vq->chase_reply->security = sec_status_bogus;
- return 1;
- }
-
- if(key_entry_isbad(vq->key_entry)) {
- log_nametypeclass(VERB_DETAIL, "Could not establish a chain "
- "of trust to keys for", vq->key_entry->name,
- LDNS_RR_TYPE_DNSKEY, vq->key_entry->key_class);
+ val_errinf(qstate, vq, "no signatures");
+ val_errinf_origin(qstate, vq, qstate->reply_origin);
vq->chase_reply->security = sec_status_bogus;
return 1;
}
/* check signatures in the message;
* answer and authority must be valid, additional is only checked. */
- if(!validate_msg_signatures(qstate->env, ve, &vq->qchase,
+ if(!validate_msg_signatures(qstate, vq, qstate->env, ve, &vq->qchase,
vq->chase_reply, vq->key_entry)) {
/* workaround bad recursor out there that truncates (even
* with EDNS4k) to 512 by removing RRSIG from auth section
vq->chase_reply->ar_numrrsets = 0;
vq->chase_reply->rrset_count =
vq->chase_reply->an_numrrsets;
+ vq->errinf = NULL;
}
else {
verbose(VERB_DETAIL, "Validate: message contains "
log_err("validate: unhandled response subtype: %d",
subtype);
}
+ if(vq->chase_reply->security == sec_status_bogus) {
+ if(subtype == VAL_CLASS_POSITIVE)
+ val_errinf(qstate, vq, "wildcard");
+ else val_errinf(qstate, vq,
+ val_classification_to_string(subtype));
+ val_errinf(qstate, vq, "proof failed");
+ val_errinf_origin(qstate, vq, qstate->reply_origin);
+ }
return 1;
}
vq->orig_msg->rep->ttl = ve->bogus_ttl;
if(qstate->env->cfg->val_log_level >= 1) {
- log_query_info(0, "validation failure", &qstate->qinfo);
+ if(qstate->env->cfg->val_log_level < 2)
+ log_query_info(0, "validation failure",
+ &qstate->qinfo);
+ else {
+ char* err = val_errinf_to_str(qstate, vq);
+ if(err) log_info(err);
+ free(err);
+ }
}
/* If we are in permissive mode, bogus gets indeterminate */
if(ve->permissive_mode)
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct key_entry_key* kkey = NULL;
enum sec_status sec = sec_status_unchecked;
+ char* reason = NULL;
if(!dnskey_rrset) {
log_nametypeclass(VERB_OPS, "failed to prime trust anchor -- "
"could not fetch DNSKEY rrset",
ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
- if(qstate->env->cfg->harden_dnssec_stripped)
+ if(qstate->env->cfg->harden_dnssec_stripped) {
+ struct val_qstate* vq = (struct val_qstate*)
+ qstate->minfo[id];
+ val_errinf(qstate, vq, "no DNSKEY rrset");
kkey = key_entry_create_bad(qstate->region, ta->name,
ta->namelen, ta->dclass);
- else kkey = key_entry_create_null(qstate->region, ta->name,
+ } else kkey = key_entry_create_null(qstate->region, ta->name,
ta->namelen, ta->dclass, NULL_KEY_TTL,
*qstate->env->now);
if(!kkey) {
/* attempt to verify with trust anchor DS and DNSKEY */
if(ta->ds_rrset) {
kkey = val_verify_new_DNSKEYs(qstate->region, qstate->env, ve,
- dnskey_rrset, ta->ds_rrset);
+ dnskey_rrset, ta->ds_rrset, &reason);
if(!kkey) {
log_err("out of memory: verifying prime DS");
return NULL;
}
if(sec != sec_status_secure && ta->dnskey_rrset) {
sec = val_verify_rrset(qstate->env, ve, dnskey_rrset,
- ta->dnskey_rrset);
+ ta->dnskey_rrset, &reason);
verbose(VERB_DETAIL, "validate keys with anchor(DNSKEY): %s",
sec_status_to_string(sec));
if(sec == sec_status_secure) {
ta->name, LDNS_RR_TYPE_DNSKEY, ta->dclass);
/* NOTE: in this case, we should probably reject the trust
* anchor for longer, perhaps forever. */
- if(qstate->env->cfg->harden_dnssec_stripped)
+ if(qstate->env->cfg->harden_dnssec_stripped) {
+ struct val_qstate* vq = (struct val_qstate*)
+ qstate->minfo[id];
+ val_errinf(qstate, vq, reason);
kkey = key_entry_create_bad(qstate->region, ta->name,
ta->namelen, ta->dclass);
- else kkey = key_entry_create_null(qstate->region, ta->name,
+ } else kkey = key_entry_create_null(qstate->region, ta->name,
ta->namelen, ta->dclass, NULL_KEY_TTL,
*qstate->env->now);
if(!kkey) {
struct key_entry_key** ke)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
+ char* reason = NULL;
enum val_classification subtype;
if(rcode != LDNS_RCODE_NOERROR) {
+ char* rc = ldns_pkt_rcode2str(rcode);
/* errors here pretty much break validation */
verbose(VERB_DETAIL, "DS response was error, thus bogus");
+ val_errinf(qstate, vq, rc);
+ val_errinf(qstate, vq, "no DS");
+ free(rc);
goto return_bogus;
}
if(!ds) {
log_warn("internal error: POSITIVE DS response was "
"missing DS.");
+ val_errinf(qstate, vq, "no DS record");
goto return_bogus;
}
/* Verify only returns BOGUS or SECURE. If the rrset is
* bogus, then we are done. */
sec = val_verify_rrset_entry(qstate->env, ve, ds,
- vq->key_entry);
+ vq->key_entry, &reason);
if(sec != sec_status_secure) {
verbose(VERB_DETAIL, "DS rrset in DS response did "
"not verify");
+ val_errinf(qstate, vq, reason);
goto return_bogus;
}
case sec_status_bogus:
verbose(VERB_DETAIL, "NSEC RRset for the "
"referral did not prove no DS.");
+ val_errinf(qstate, vq, "NSEC DS absent proof "
+ "failed");
goto return_bogus;
case sec_status_unchecked:
default:
case sec_status_bogus:
verbose(VERB_DETAIL, "NSEC3s for the "
"referral did not prove no DS.");
+ val_errinf(qstate, vq, "NSEC3 DS absent proof "
+ "failed");
goto return_bogus;
case sec_status_insecure:
case sec_status_unchecked:
* this is BOGUS. */
verbose(VERB_DETAIL, "DS %s ran out of options, so return "
"bogus", val_classification_to_string(subtype));
+ val_errinf(qstate, vq, "no DS but also no proof of that");
goto return_bogus;
} else {
verbose(VERB_QUERY, "Encountered an unhandled type of "
"DS response, thus bogus.");
+ val_errinf(qstate, vq, "no DS and ");
+ if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR) {
+ char* rc = ldns_pkt_rcode2str(
+ FLAGS_GET_RCODE(msg->rep->flags));
+ val_errinf(qstate, vq, rc);
+ free(rc);
+ } else val_errinf(qstate, vq,
+ val_classification_to_string(subtype));
+ val_errinf(qstate, vq, "message fails to prove that");
goto return_bogus;
}
return_bogus:
&& vq->restart_count < VAL_MAX_RESTART_COUNT) {
vq->empty_DS_name = olds;
val_blacklist(&vq->chain_blacklist, qstate->region, origin, 1);
+ vq->errinf = NULL;
vq->restart_count++;
} else {
+ if(key_entry_isbad(dske)) {
+ val_errinf_origin(qstate, vq, origin);
+ val_errinf_dname(qstate, vq, "for DS", qinfo->qname);
+ }
/* NOTE: the reason for the DS to be not good (that is,
* either bad or null) should have been logged by
* dsResponseToKE. */
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
struct key_entry_key* old = vq->key_entry;
struct ub_packed_rrset_key* dnskey = NULL;
+ char* reason = NULL;
if(rcode == LDNS_RCODE_NOERROR)
dnskey = reply_find_answer_rrset(qinfo, msg->rep);
verbose(VERB_DETAIL, "Missing DNSKEY RRset in response to "
"DNSKEY query.");
if(vq->restart_count < VAL_MAX_RESTART_COUNT) {
- vq->restart_count++;
val_blacklist(&vq->chain_blacklist, qstate->region,
origin, 1);
+ vq->errinf = NULL;
+ vq->restart_count++;
return;
}
vq->key_entry = key_entry_create_bad(qstate->region,
return;
}
vq->key_entry = val_verify_new_DNSKEYs(qstate->region, qstate->env,
- ve, dnskey, vq->ds_rrset);
+ ve, dnskey, vq->ds_rrset, &reason);
if(!vq->key_entry) {
log_err("out of memory in verify new DNSKEYs");
if(vq->restart_count < VAL_MAX_RESTART_COUNT) {
val_blacklist(&vq->chain_blacklist,
qstate->region, origin, 1);
+ vq->errinf = NULL;
vq->restart_count++;
vq->key_entry = old;
return;
}
verbose(VERB_DETAIL, "Did not match a DS to a DNSKEY, "
"thus bogus.");
+ val_errinf(qstate, vq, reason);
+ val_errinf_origin(qstate, vq, origin);
+ val_errinf_dname(qstate, vq, "for key", qinfo->qname);
}
vq->chain_blacklist = NULL;
vq->state = VAL_VALIDATE_STATE;
return;
}
vq->chain_blacklist = NULL;
+ vq->errinf = NULL;
/* The DNSKEY validated, so cache it as a trusted key rrset. */
key_cache_insert(ve->kcache, vq->key_entry);
&& vq->restart_count < VAL_MAX_RESTART_COUNT) {
val_blacklist(&vq->chain_blacklist, qstate->region,
origin, 1);
- vq->key_entry = NULL;
+ vq->errinf = NULL;
vq->restart_count++;
+ vq->key_entry = NULL;
vq->state = VAL_INIT_STATE;
return;
}
vq->chain_blacklist = NULL;
+ val_errinf_origin(qstate, vq, origin);
+ val_errinf_dname(qstate, vq, "for trust anchor", ta->name);
/* store the freshly primed entry in the cache */
key_cache_insert(ve->kcache, vq->key_entry);
}
* @param rcode: rcode result value.
* @param msg: result message (if rcode is OK).
* @param qinfo: from the sub query state, query info.
- * @param origin: the origin of msg.
*/
static void
process_dlv_response(struct module_qstate* qstate, struct val_qstate* vq,
- int id, int rcode, struct dns_msg* msg, struct query_info* qinfo,
- struct sock_list* origin)
+ int id, int rcode, struct dns_msg* msg, struct query_info* qinfo)
{
struct val_env* ve = (struct val_env*)qstate->env->modinfo[id];
return;
} else if(qstate->qinfo.qtype == LDNS_RR_TYPE_DLV) {
process_dlv_response(super, vq, id, qstate->return_rcode,
- qstate->return_msg, &qstate->qinfo,
- qstate->reply_origin);
+ qstate->return_msg, &qstate->qinfo);
return;
}
log_err("internal error in validator: no inform_supers possible");
struct key_cache;
struct key_entry_key;
struct val_neg_cache;
+struct config_strlist;
/**
* This is the TTL to use when a trust anchor fails to prime. A trust anchor
dlv_ask_higher, /* ask again */
dlv_there_is_no_dlv /* got no DLV, sure of it */
} dlv_status;
+
+ /** failure reason information if val-log-level is high */
+ struct config_strlist* errinf;
};
/**