mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-05-28 04:02:33 -04:00
- moved version number to 1.4.0 because of 1.3.4 release with only
the NSEC3 patch. - 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 git-svn-id: file:///svn/unbound/trunk@1868 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
6f37df3b92
commit
ce45cbda6d
16 changed files with 822 additions and 95 deletions
49
configure
vendored
49
configure
vendored
|
|
@ -1,6 +1,6 @@
|
|||
#! /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>.
|
||||
#
|
||||
|
|
@ -745,8 +745,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
|||
# 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.
|
||||
|
|
@ -1499,7 +1499,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# 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]...
|
||||
|
||||
|
|
@ -1564,7 +1564,7 @@ fi
|
|||
|
||||
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
|
||||
|
||||
|
|
@ -1710,7 +1710,7 @@ fi
|
|||
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,
|
||||
|
|
@ -1724,7 +1724,7 @@ cat >config.log <<_ACEOF
|
|||
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 $@
|
||||
|
|
@ -2094,7 +2094,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
|||
|
||||
|
||||
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
|
||||
|
|
@ -2108,6 +2108,7 @@ LIBUNBOUND_AGE=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
|
||||
|
|
@ -7278,13 +7279,13 @@ if test "${lt_cv_nm_interface+set}" = set; then
|
|||
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"
|
||||
|
|
@ -8489,7 +8490,7 @@ ia64-*-hpux*)
|
|||
;;
|
||||
*-*-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=$?
|
||||
|
|
@ -9856,11 +9857,11 @@ else
|
|||
-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.
|
||||
|
|
@ -10195,11 +10196,11 @@ else
|
|||
-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.
|
||||
|
|
@ -10300,11 +10301,11 @@ else
|
|||
-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
|
||||
|
|
@ -10355,11 +10356,11 @@ else
|
|||
-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
|
||||
|
|
@ -13158,7 +13159,7 @@ else
|
|||
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
|
||||
|
|
@ -13254,7 +13255,7 @@ else
|
|||
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
|
||||
|
|
@ -23301,7 +23302,7 @@ exec 6>&1
|
|||
# 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
|
||||
|
|
@ -23364,7 +23365,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
|||
_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'`\\"
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ sinclude(acx_pthread.m4)
|
|||
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
|
||||
|
|
@ -23,6 +23,7 @@ LIBUNBOUND_AGE=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
|
||||
|
|
|
|||
|
|
@ -7,6 +7,14 @@
|
|||
- 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.
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
|
|||
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)++;
|
||||
|
|
|
|||
|
|
@ -155,14 +155,16 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
|
|||
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);
|
||||
|
|
|
|||
227
testdata/val_nsec3_nods_badsig.rpl
vendored
Normal file
227
testdata/val_nsec3_nods_badsig.rpl
vendored
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
; 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
|
||||
191
testdata/val_secds_nosig.rpl
vendored
Normal file
191
testdata/val_secds_nosig.rpl
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
; 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
|
||||
|
|
@ -946,10 +946,11 @@ static int
|
|||
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) {
|
||||
|
|
@ -959,7 +960,7 @@ verify_dnskey(struct module_env* env, struct val_env* ve,
|
|||
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) {
|
||||
|
|
@ -995,9 +996,11 @@ rr_is_selfsigned_revoked(struct module_env* env, struct val_env* ve,
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
|
|||
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
|
||||
|
|
@ -190,7 +191,7 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
|
|||
* 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.");
|
||||
|
|
@ -219,7 +220,8 @@ val_nsec_prove_nodata_dsreply(struct module_env* env, struct val_env* ve,
|
|||
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.");
|
||||
|
|
|
|||
|
|
@ -1245,10 +1245,11 @@ list_is_secure(struct module_env* env, struct val_env* ve,
|
|||
{
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -461,25 +461,28 @@ dnskeyset_needs(struct ub_packed_rrset_key* dnskey, uint8_t needs[])
|
|||
|
||||
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);
|
||||
|
|
@ -490,19 +493,23 @@ dnskeyset_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||
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);
|
||||
|
|
@ -512,6 +519,7 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||
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++) {
|
||||
|
|
@ -522,11 +530,13 @@ dnskey_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -534,7 +544,7 @@ 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)
|
||||
{
|
||||
/* find matching keys and check them */
|
||||
enum sec_status sec = sec_status_bogus;
|
||||
|
|
@ -555,11 +565,12 @@ dnskeyset_verify_rrset_sig(struct module_env* env, struct val_env* ve,
|
|||
/* 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;
|
||||
}
|
||||
|
|
@ -1075,7 +1086,7 @@ sigdate_error(const char* str, int32_t expi, int32_t incep, int32_t now)
|
|||
/** 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;
|
||||
|
|
@ -1094,6 +1105,7 @@ check_dates(struct val_env* ve, uint32_t unow,
|
|||
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) {
|
||||
|
|
@ -1104,6 +1116,7 @@ check_dates(struct val_env* ve, uint32_t unow,
|
|||
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 "
|
||||
|
|
@ -1116,6 +1129,7 @@ check_dates(struct val_env* ve, uint32_t unow,
|
|||
if(now - expi > skew) {
|
||||
sigdate_error("verify: signature expired", expi,
|
||||
incep, now);
|
||||
*reason = "signature expired";
|
||||
return 0;
|
||||
}
|
||||
sigdate_error("verify warning suspicious signature expiration "
|
||||
|
|
@ -1430,7 +1444,7 @@ dnskey_verify_rrset_sig(struct regional* region, 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)
|
||||
{
|
||||
enum sec_status sec;
|
||||
uint8_t* sig; /* RRSIG rdata */
|
||||
|
|
@ -1447,17 +1461,20 @@ dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf,
|
|||
/* 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;
|
||||
}
|
||||
|
||||
|
|
@ -1466,15 +1483,18 @@ dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf,
|
|||
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);
|
||||
|
|
@ -1486,6 +1506,7 @@ dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1493,29 +1514,33 @@ dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf,
|
|||
/* 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;
|
||||
}
|
||||
|
||||
|
|
@ -1544,7 +1569,8 @@ dnskey_verify_rrset_sig(struct regional* region, ldns_buffer* buf,
|
|||
/* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,13 +146,14 @@ uint16_t dnskey_get_flags(struct ub_packed_rrset_key* k, size_t idx);
|
|||
* @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)
|
||||
|
|
@ -161,12 +162,13 @@ enum sec_status dnskeyset_verify_rrset(struct module_env* env,
|
|||
* @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
|
||||
|
|
@ -178,13 +180,14 @@ enum sec_status dnskey_verify_rrset(struct module_env* env,
|
|||
* @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
|
||||
|
|
@ -201,6 +204,7 @@ enum sec_status dnskeyset_verify_rrset_sig(struct module_env* env,
|
|||
* @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.
|
||||
*/
|
||||
|
|
@ -208,7 +212,7 @@ enum sec_status dnskey_verify_rrset_sig(struct regional* region,
|
|||
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
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#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,
|
||||
|
|
@ -303,7 +304,8 @@ rrset_get_ttl(struct ub_packed_rrset_key* rrset)
|
|||
|
||||
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->
|
||||
|
|
@ -325,7 +327,7 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||
}
|
||||
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);
|
||||
|
||||
|
|
@ -357,7 +359,8 @@ val_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||
|
||||
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;
|
||||
|
|
@ -370,7 +373,7 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -378,10 +381,10 @@ val_verify_rrset_entry(struct module_env* env, struct val_env* ve,
|
|||
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. */
|
||||
|
|
@ -391,6 +394,7 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
|
|||
!= 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));
|
||||
|
|
@ -402,24 +406,31 @@ verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
|
|||
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. */
|
||||
|
|
@ -433,6 +444,7 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
|||
!= 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;
|
||||
}
|
||||
|
||||
|
|
@ -462,7 +474,7 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
|||
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;
|
||||
|
|
@ -485,10 +497,10 @@ val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
|
|||
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,
|
||||
|
|
@ -837,3 +849,117 @@ void val_blacklist(struct sock_list** blacklist, struct regional* 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ struct regional;
|
|||
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.
|
||||
|
|
@ -117,10 +119,12 @@ void val_find_signer(enum val_classification subtype,
|
|||
* @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.
|
||||
|
|
@ -128,11 +132,12 @@ enum sec_status val_verify_rrset(struct module_env* env, struct val_env* ve,
|
|||
* @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
|
||||
|
|
@ -141,13 +146,14 @@ enum sec_status val_verify_rrset_entry(struct module_env* env,
|
|||
* @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
|
||||
|
|
@ -159,6 +165,7 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
|
|||
* @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
|
||||
|
|
@ -171,7 +178,7 @@ enum sec_status val_verify_DNSKEY_with_DS(struct module_env* env,
|
|||
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.
|
||||
|
|
@ -301,4 +308,55 @@ const char* val_classification_to_string(enum val_classification subtype);
|
|||
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 */
|
||||
|
|
|
|||
|
|
@ -409,6 +409,8 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
* 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.
|
||||
|
|
@ -419,15 +421,16 @@ prime_trust_anchor(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
* 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++) {
|
||||
|
|
@ -448,13 +451,19 @@ validate_msg_signatures(struct module_env* env, struct val_env* ve,
|
|||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
|
@ -471,13 +480,16 @@ validate_msg_signatures(struct module_env* env, struct val_env* ve,
|
|||
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;
|
||||
}
|
||||
|
|
@ -493,7 +505,8 @@ validate_msg_signatures(struct module_env* env, struct val_env* ve,
|
|||
/* 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. */
|
||||
|
|
@ -1493,6 +1506,15 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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) {
|
||||
|
|
@ -1500,14 +1522,8 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
"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;
|
||||
}
|
||||
|
|
@ -1516,7 +1532,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
|
||||
/* 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
|
||||
|
|
@ -1533,6 +1549,7 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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 "
|
||||
|
|
@ -1610,6 +1627,14 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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;
|
||||
}
|
||||
|
|
@ -1860,7 +1885,14 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
|
||||
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)
|
||||
|
|
@ -2118,15 +2150,19 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
|||
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) {
|
||||
|
|
@ -2138,7 +2174,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
|||
/* 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;
|
||||
|
|
@ -2152,7 +2188,7 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
|||
}
|
||||
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) {
|
||||
|
|
@ -2172,10 +2208,13 @@ primeResponseToKE(struct ub_packed_rrset_key* dnskey_rrset,
|
|||
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) {
|
||||
|
|
@ -2213,10 +2252,15 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2230,15 +2274,17 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2291,6 +2337,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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:
|
||||
|
|
@ -2318,6 +2366,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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:
|
||||
|
|
@ -2330,10 +2380,20 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
* 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:
|
||||
|
|
@ -2398,8 +2458,13 @@ process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
&& 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. */
|
||||
|
|
@ -2433,6 +2498,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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);
|
||||
|
|
@ -2442,9 +2508,10 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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,
|
||||
|
|
@ -2463,7 +2530,7 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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");
|
||||
|
|
@ -2477,18 +2544,23 @@ process_dnskey_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
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);
|
||||
|
|
@ -2547,12 +2619,15 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
&& 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);
|
||||
}
|
||||
|
|
@ -2578,12 +2653,10 @@ process_prime_response(struct module_qstate* qstate, struct val_qstate* vq,
|
|||
* @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];
|
||||
|
||||
|
|
@ -2697,8 +2770,7 @@ val_inform_super(struct module_qstate* qstate, int 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");
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ struct val_anchors;
|
|||
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
|
||||
|
|
@ -236,6 +237,9 @@ struct val_qstate {
|
|||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue