3443. [bug] The NOQNAME proof was not being returned from cached

insecure responses. [RT #21409]
This commit is contained in:
Mark Andrews 2012-12-19 09:55:02 +11:00
parent 03958ad4b9
commit 8462dfb880
24 changed files with 1198 additions and 479 deletions

View file

@ -1,3 +1,6 @@
3443. [bug] The NOQNAME proof was not being returned from cached
insecure responses. [RT #21409]
3442. [port] Net::DNS 0.69 introduced a non backwards compatible
change. [RT #32216]

View file

@ -61,7 +61,7 @@ SUBDIRS="acl allow_query addzone autosign builtin cacheclean checkconf
inline limits logfileconfig lwresd masterfile masterformat metadata
notify nsupdate pending pkcs11 redirect resolver rndc rpz rrsetorder
rsabigexponent sortlist smartsign staticstub statistics stub
tkey tsig tsiggss unknown upforwd verify views xfer xferquota
tkey tsig tsiggss unknown upforwd verify views wildcard xfer xferquota
zonechecks"
# PERL will be an empty string if no perl interpreter was found.

View file

@ -0,0 +1,30 @@
#!/bin/sh
#
# Copyright (C) 2004, 2007, 2010 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: clean.sh,v 1.1.2.1 2010/06/01 03:55:01 marka Exp $
rm -f random.data
rm -f ns*/named.run
rm -f ns1/K*
rm -f ns1/*.db
rm -f ns1/*.signed
rm -f ns1/dsset-*
rm -f ns1/trusted.conf
rm -f ns1/private.nsec.conf
rm -f ns1/private.nsec3.conf
rm -f ns1/signer.err
rm -f */named.memstats
rm -f dig.out.ns*.test*

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.1.2.3 2010/06/01 07:04:49 marka Exp $ */
controls { /* empty */ };
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
notify yes;
dnssec-enable yes;
};
zone "." { type master; file "root.db.signed"; };
zone "nsec" { type master; file "nsec.db.signed"; };
zone "private.nsec" { type master; file "private.nsec.db.signed"; };
/*
* The contents of nsec3 and private.nsec3 are specially choosen to
* have seperate NSEC3 records for the "no qname proof" and the
* "closest encloser proof".
*/
zone "nsec3" { type master; file "nsec3.db.signed"; };
zone "private.nsec3" { type master; file "private.nsec3.db.signed"; };

View file

@ -0,0 +1,7 @@
; Copyright
$TTL 120
@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
@ NS a.root-servers.nil.
private NS a.root-servers.nil.
*.wild CNAME a.
a.wild A 1.2.3.5

View file

@ -0,0 +1,7 @@
; Copyright
$TTL 120
@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
@ NS a.root-servers.nil.
private NS a.root-servers.nil.
*.wild CNAME a.
a.wild A 1.2.3.5

View file

@ -0,0 +1,6 @@
; Copyright
$TTL 120
@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
@ NS a.root-servers.nil.
*.wild CNAME a.
a.wild A 1.2.3.5

View file

@ -0,0 +1,8 @@
; Copyright
$TTL 120
@ SOA a.root-servers.nil. hostmaster.root-servers.nil. 1 1800 900 604800 86400
@ NS a.root-servers.nil.
b A 1.2.3.4
*.wild CNAME a.
a.wild A 1.2.3.5

View file

@ -0,0 +1,7 @@
; Copyright
$TTL 120
@ SOA a.root-servers.nil hostmaster.root-servers.nil 1 1800 900 604800 86400
@ NS a.root-servers.nil
a.root-servers.nil A 10.53.0.1
nsec NS a.root-servers.nil
nsec3 NS a.root-servers.nil

View file

@ -0,0 +1,120 @@
#!/bin/sh
#
# Copyright (C) 2004, 2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: sign.sh,v 1.1.2.2 2010/06/01 06:38:47 marka Exp $
SYSTEMTESTTOP=../..
. $SYSTEMTESTTOP/conf.sh
RANDFILE=../random.data
dssets=
zone=nsec.
infile=nsec.db.in
zonefile=nsec.db
outfile=nsec.db.signed
dssets="$dssets dsset-$zone"
keyname1=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo "I: signed $zone"
zone=private.nsec.
infile=private.nsec.db.in
zonefile=private.nsec.db
outfile=private.nsec.db.signed
keyname1=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo "I: signed $zone"
grep -v '^;' $keyname2.key | $PERL -n -e '
local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
local $key = join("", @rest);
print <<EOF
trusted-keys {
"$dn" $flags $proto $alg "$key";
};
EOF
' > private.nsec.conf
zone=nsec3.
infile=nsec3.db.in
zonefile=nsec3.db
outfile=nsec3.db.signed
dssets="$dssets dsset-$zone"
keyname1=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
keyname2=`$KEYGEN -f KSK -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -r $RANDFILE -3 - -i 10 -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo "I: signed $zone"
zone=private.nsec3.
infile=private.nsec3.db.in
zonefile=private.nsec3.db
outfile=private.nsec3.db.signed
keyname1=`$KEYGEN -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
keyname2=`$KEYGEN -f KSK -r $RANDFILE -a NSEC3RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
cat $infile $keyname1.key $keyname2.key > $zonefile
$SIGNER -r $RANDFILE -3 - -i 10 -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo "I: signed $zone"
grep -v '^;' $keyname2.key | $PERL -n -e '
local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
local $key = join("", @rest);
print <<EOF
trusted-keys {
"$dn" $flags $proto $alg "$key";
};
EOF
' > private.nsec3.conf
zone=.
infile=root.db.in
zonefile=root.db
outfile=root.db.signed
keyname1=`$KEYGEN -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
keyname2=`$KEYGEN -f KSK -r $RANDFILE -a RSASHA1 -b 1024 -n zone $zone 2> /dev/null`
cat $infile $keyname1.key $keyname2.key $dssets >$zonefile
$SIGNER -r $RANDFILE -o $zone -f $outfile $zonefile > /dev/null 2> signer.err || cat signer.err
echo "I: signed $zone"
grep -v '^;' $keyname2.key | $PERL -n -e '
local ($dn, $class, $type, $flags, $proto, $alg, @rest) = split;
local $key = join("", @rest);
print <<EOF
trusted-keys {
"$dn" $flags $proto $alg "$key";
};
EOF
' > trusted.conf

View file

@ -0,0 +1,18 @@
; Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
; $Id: hints,v 1.1.2.1 2010/06/01 03:55:02 marka Exp $
. 0 NS ns.root-servers.nil.
ns.root-servers.nil. 0 A 10.53.0.1

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.1.2.1 2010/06/01 03:55:02 marka Exp $ */
controls { /* empty */ };
options {
query-source address 10.53.0.2;
notify-source 10.53.0.2;
transfer-source 10.53.0.2;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
recursion yes;
notify yes;
};
zone "." { type hint; file "hints"; };

View file

@ -0,0 +1,18 @@
; Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
;
; Permission to use, copy, modify, and/or distribute this software for any
; purpose with or without fee is hereby granted, provided that the above
; copyright notice and this permission notice appear in all copies.
;
; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
; PERFORMANCE OF THIS SOFTWARE.
; $Id: hints,v 1.1.2.1 2010/06/01 03:55:02 marka Exp $
. 0 NS ns.root-servers.nil.
ns.root-servers.nil. 0 A 10.53.0.1

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.1.2.1 2010/06/01 03:55:02 marka Exp $ */
controls { /* empty */ };
options {
query-source address 10.53.0.3;
notify-source 10.53.0.3;
transfer-source 10.53.0.3;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
recursion yes;
notify yes;
};
include "../ns1/trusted.conf";
zone "." { type hint; file "hints"; };

View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: named.conf,v 1.1.2.1 2010/06/01 03:55:02 marka Exp $ */
controls { /* empty */ };
options {
query-source address 10.53.0.4;
notify-source 10.53.0.4;
transfer-source 10.53.0.4;
port 5300;
pid-file "named.pid";
listen-on { 10.53.0.4; };
listen-on-v6 { none; };
recursion yes;
notify yes;
forward only;
forwarders { 10.53.0.2; };
};
include "../ns1/trusted.conf";
include "../ns1/private.nsec.conf";
include "../ns1/private.nsec3.conf";

View file

@ -0,0 +1,21 @@
#!/bin/sh
#
# Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: setup.sh,v 1.1.2.1 2010/06/01 03:55:01 marka Exp $
../../../tools/genrandom 400 random.data
(cd ns1 && sh -e sign.sh)

View file

@ -0,0 +1,136 @@
#!/bin/sh
#
# Copyright (C) 2004, 2007, 2010 Internet Systems Consortium, Inc. ("ISC")
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
# $Id: tests.sh,v 1.1.2.3 2010/06/01 06:57:31 marka Exp $
SYSTEMTESTTOP=..
. $SYSTEMTESTTOP/conf.sh
status=0
n=0
rm -f dig.out.*
DIGOPTS="+tcp +noadd +nosea +nostat +nocmd +dnssec -p 5300"
n=`expr $n + 1`
echo "I: checking that NSEC wildcard non-existance proof is returned auth ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec +norec @10.53.0.1 > dig.out.ns1.test$n || ret=1
grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns1.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that NSEC wildcard non-existance proof is returned non-validating ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns2.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns2.test$n > /dev/null && ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that NSEC wildcard non-existance proof is returned validating ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns3.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that returned NSEC wildcard non-existance proof validates ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec @10.53.0.4 > dig.out.ns4.test$n || ret=1
grep -i 'a\.wild\.nsec\..*NSEC.*nsec\..*NSEC' dig.out.ns4.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that NSEC wildcard non-existance proof is returned private, validating ($n)"
ret=0
$DIG $DIGOPTS a b.wild.private.nsec @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep -i 'a\.wild\.private\.nsec\..*NSEC.*private\.nsec\..*NSEC' dig.out.ns3.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null && ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that returned NSEC wildcard non-existance proof for private zone validates ($n)"
ret=0
$DIG $DIGOPTS a b.wild.private.nsec @10.53.0.4 > dig.out.ns4.test$n || ret=1
grep -i 'a\.wild\.private\.nsec\..*NSEC.*private\.nsec\..*NSEC' dig.out.ns4.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that NSEC3 wildcard non-existance proof is returned auth ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec3 +norec @10.53.0.1 > dig.out.ns1.test$n || ret=1
grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns1.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that NSEC3 wildcard non-existance proof is returned non-validating ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec3 @10.53.0.2 > dig.out.ns2.test$n || ret=1
grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns2.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns2.test$n > /dev/null && ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that NSEC3 wildcard non-existance proof is returned validating ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns3.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that returned NSEC3 wildcard non-existance proof validates ($n)"
ret=0
$DIG $DIGOPTS a b.wild.nsec3 @10.53.0.4 > dig.out.ns4.test$n || ret=1
grep -i 'O3TJ8D9AJ54CBTFCQCJ3QK49CH7SF6H9\.nsec3\..*V5DLFB6UJNHR94LQ61FO607KGK12H88A' dig.out.ns4.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that NSEC3 wildcard non-existance proof is returned private, validating ($n)"
ret=0
$DIG $DIGOPTS a b.wild.private.nsec3 @10.53.0.3 > dig.out.ns3.test$n || ret=1
grep -i 'UDBSP4R8OUOT6HSO39VD8B5LMOSHRD5N\.private\.nsec3\..*NSEC3.*ASDRUIB7GO00OR92S5OUGI404LT27RNU' dig.out.ns3.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns3.test$n > /dev/null && ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I: checking that returned NSEC3 wildcard non-existance proof for private zone validates ($n)"
ret=0
$DIG $DIGOPTS a b.wild.private.nsec3 @10.53.0.4 > dig.out.ns4.test$n || ret=1
grep -i 'UDBSP4R8OUOT6HSO39VD8B5LMOSHRD5N\.private\.nsec3\..*NSEC3.*ASDRUIB7GO00OR92S5OUGI404LT27RNU' dig.out.ns4.test$n > /dev/null || ret=1
grep -i 'flags:.* ad[ ;]' dig.out.ns4.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:exit status: $status"
exit $status

View file

@ -98,6 +98,19 @@ dns_nsec_isset(const unsigned char *array, unsigned int type);
* Test if the corresponding 'type' bit is set in 'array'.
*/
isc_result_t
dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name,
dns_name_t *nsecname, dns_rdataset_t *nsecset,
isc_boolean_t *exists, isc_boolean_t *data,
dns_name_t *wild, dns_nseclog_t log, void *arg);
/*%
* Return ISC_R_SUCCESS if we can determine that the name doesn't exist
* or we can determine whether there is data or not at the name.
* If the name does not exist return the wildcard name.
*
* Return ISC_R_IGNORE when the NSEC is not the appropriate one.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_NSEC_H */

View file

@ -248,6 +248,14 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
* Mark NSEC3PARAM for deletion.
*/
isc_result_t
dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name,
dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
dns_name_t *zonename, isc_boolean_t *exists,
isc_boolean_t *data, isc_boolean_t *optout,
isc_boolean_t *unknown, isc_boolean_t *setclosest,
isc_boolean_t *setnearest, dns_name_t *closest,
dns_name_t *nearest, dns_nseclog_t logit, void *arg);
ISC_LANG_ENDDECLS

View file

@ -400,4 +400,7 @@ typedef isc_boolean_t
typedef isc_result_t
(*dns_deserializefunc_t)(void *, FILE *, off_t);
typedef void
(*dns_nseclog_t)(void *val, int , const char *, ...);
#endif /* DNS_TYPES_H */

View file

@ -21,6 +21,7 @@
#include <config.h>
#include <isc/log.h>
#include <isc/string.h>
#include <isc/util.h>
@ -290,3 +291,161 @@ dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
}
return (result);
}
/*%
* Return ISC_R_SUCCESS if we can determine that the name doesn't exist
* or we can determine whether there is data or not at the name.
* If the name does not exist return the wildcard name.
*
* Return ISC_R_IGNORE when the NSEC is not the appropriate one.
*/
isc_result_t
dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name,
dns_name_t *nsecname, dns_rdataset_t *nsecset,
isc_boolean_t *exists, isc_boolean_t *data,
dns_name_t *wild, dns_nseclog_t logit, void *arg)
{
int order;
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_result_t result;
dns_namereln_t relation;
unsigned int olabels, nlabels, labels;
dns_rdata_nsec_t nsec;
isc_boolean_t atparent;
isc_boolean_t ns;
isc_boolean_t soa;
REQUIRE(exists != NULL);
REQUIRE(data != NULL);
REQUIRE(nsecset != NULL &&
nsecset->type == dns_rdatatype_nsec);
result = dns_rdataset_first(nsecset);
if (result != ISC_R_SUCCESS) {
(*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC set");
return (result);
}
dns_rdataset_current(nsecset, &rdata);
(*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant nsec");
relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
if (order < 0) {
/*
* The name is not within the NSEC range.
*/
(*logit)(arg, ISC_LOG_DEBUG(3),
"NSEC does not cover name, before NSEC");
return (ISC_R_IGNORE);
}
if (order == 0) {
/*
* The names are the same. If we are validating "."
* then atparent should not be set as there is no parent.
*/
atparent = (olabels != 1) && dns_rdatatype_atparent(type);
ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
if (ns && !soa) {
if (!atparent) {
/*
* This NSEC record is from somewhere higher in
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring parent nsec");
return (ISC_R_IGNORE);
}
} else if (atparent && ns && soa) {
/*
* This NSEC record is from the child.
* It can not be legitimately used here.
*/
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring child nsec");
return (ISC_R_IGNORE);
}
if (type == dns_rdatatype_cname || type == dns_rdatatype_nxt ||
type == dns_rdatatype_nsec || type == dns_rdatatype_key ||
!dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
*exists = ISC_TRUE;
*data = dns_nsec_typepresent(&rdata, type);
(*logit)(arg, ISC_LOG_DEBUG(3),
"nsec proves name exists (owner) data=%d",
*data);
return (ISC_R_SUCCESS);
}
(*logit)(arg, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
return (ISC_R_IGNORE);
}
if (relation == dns_namereln_subdomain &&
dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
!dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
{
/*
* This NSEC record is from somewhere higher in
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
(*logit)(arg, ISC_LOG_DEBUG(3), "ignoring parent nsec");
return (ISC_R_IGNORE);
}
result = dns_rdata_tostruct(&rdata, &nsec, NULL);
if (result != ISC_R_SUCCESS)
return (result);
relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
if (order == 0) {
dns_rdata_freestruct(&nsec);
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring nsec matches next name");
return (ISC_R_IGNORE);
}
if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
/*
* The name is not within the NSEC range.
*/
dns_rdata_freestruct(&nsec);
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring nsec because name is past end of range");
return (ISC_R_IGNORE);
}
if (order > 0 && relation == dns_namereln_subdomain) {
(*logit)(arg, ISC_LOG_DEBUG(3),
"nsec proves name exist (empty)");
dns_rdata_freestruct(&nsec);
*exists = ISC_TRUE;
*data = ISC_FALSE;
return (ISC_R_SUCCESS);
}
if (wild != NULL) {
dns_name_t common;
dns_name_init(&common, NULL);
if (olabels > nlabels) {
labels = dns_name_countlabels(nsecname);
dns_name_getlabelsequence(nsecname, labels - olabels,
olabels, &common);
} else {
labels = dns_name_countlabels(&nsec.next);
dns_name_getlabelsequence(&nsec.next, labels - nlabels,
nlabels, &common);
}
result = dns_name_concatenate(dns_wildcardname, &common,
wild, NULL);
if (result != ISC_R_SUCCESS) {
dns_rdata_freestruct(&nsec);
(*logit)(arg, ISC_LOG_DEBUG(3),
"failure generating wildcard name");
return (result);
}
}
dns_rdata_freestruct(&nsec);
(*logit)(arg, ISC_LOG_DEBUG(3), "nsec range ok");
*exists = ISC_FALSE;
return (ISC_R_SUCCESS);
}

View file

@ -22,6 +22,7 @@
#include <isc/buffer.h>
#include <isc/hex.h>
#include <isc/iterated_hash.h>
#include <isc/log.h>
#include <isc/string.h>
#include <isc/util.h>
@ -1802,3 +1803,285 @@ dns_nsec3_maxiterations(dns_db_t *db, dns_dbversion_t *version,
dns_rdataset_disassociate(&rdataset);
return (result);
}
isc_result_t
dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name,
dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
dns_name_t *zonename, isc_boolean_t *exists,
isc_boolean_t *data, isc_boolean_t *optout,
isc_boolean_t *unknown, isc_boolean_t *setclosest,
isc_boolean_t *setnearest, dns_name_t *closest,
dns_name_t *nearest, dns_nseclog_t logit, void *arg)
{
char namebuf[DNS_NAME_FORMATSIZE];
dns_fixedname_t fzone;
dns_fixedname_t qfixed;
dns_label_t hashlabel;
dns_name_t *qname;
dns_name_t *zone;
dns_rdata_nsec3_t nsec3;
dns_rdata_t rdata = DNS_RDATA_INIT;
int order;
int scope;
isc_boolean_t atparent;
isc_boolean_t first;
isc_boolean_t ns;
isc_boolean_t soa;
isc_buffer_t buffer;
isc_result_t answer = ISC_R_IGNORE;
isc_result_t result;
unsigned char hash[NSEC3_MAX_HASH_LENGTH];
unsigned char owner[NSEC3_MAX_HASH_LENGTH];
unsigned int length;
unsigned int qlabels;
unsigned int zlabels;
REQUIRE((exists == NULL && data == NULL) ||
(exists != NULL && data != NULL));
REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
REQUIRE((setclosest == NULL && closest == NULL) ||
(setclosest != NULL && closest != NULL));
REQUIRE((setnearest == NULL && nearest == NULL) ||
(setnearest != NULL && nearest != NULL));
result = dns_rdataset_first(nsec3set);
if (result != ISC_R_SUCCESS) {
(*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC3 set");
return (result);
}
dns_rdataset_current(nsec3set, &rdata);
result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
if (result != ISC_R_SUCCESS)
return (result);
(*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
dns_fixedname_init(&fzone);
zone = dns_fixedname_name(&fzone);
zlabels = dns_name_countlabels(nsec3name);
/*
* NSEC3 records must have two or more labels to be valid.
*/
if (zlabels < 2)
return (ISC_R_IGNORE);
/*
* Strip off the NSEC3 hash to get the zone.
*/
zlabels--;
dns_name_split(nsec3name, zlabels, NULL, zone);
/*
* If not below the zone name we can ignore this record.
*/
if (!dns_name_issubdomain(name, zone))
return (ISC_R_IGNORE);
/*
* Is this zone the same or deeper than the current zone?
*/
if (dns_name_countlabels(zonename) == 0 ||
dns_name_issubdomain(zone, zonename))
dns_name_copy(zone, zonename, NULL);
if (!dns_name_equal(zone, zonename))
return (ISC_R_IGNORE);
/*
* Are we only looking for the most enclosing zone?
*/
if (exists == NULL || data == NULL)
return (ISC_R_SUCCESS);
/*
* Only set unknown once we are sure that this NSEC3 is from
* the deepest covering zone.
*/
if (!dns_nsec3_supportedhash(nsec3.hash)) {
if (unknown != NULL)
*unknown = ISC_TRUE;
return (ISC_R_IGNORE);
}
/*
* Recover the hash from the first label.
*/
dns_name_getlabel(nsec3name, 0, &hashlabel);
isc_region_consume(&hashlabel, 1);
isc_buffer_init(&buffer, owner, sizeof(owner));
result = isc_base32hex_decoderegion(&hashlabel, &buffer);
if (result != ISC_R_SUCCESS)
return (result);
/*
* The hash lengths should match. If not ignore the record.
*/
if (isc_buffer_usedlength(&buffer) != nsec3.next_length)
return (ISC_R_IGNORE);
/*
* Work out what this NSEC3 covers.
* Inside (<0) or outside (>=0).
*/
scope = memcmp(owner, nsec3.next, nsec3.next_length);
/*
* Prepare to compute all the hashes.
*/
dns_fixedname_init(&qfixed);
qname = dns_fixedname_name(&qfixed);
dns_name_downcase(name, qname, NULL);
qlabels = dns_name_countlabels(qname);
first = ISC_TRUE;
while (qlabels >= zlabels) {
length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
nsec3.salt, nsec3.salt_length,
qname->ndata, qname->length);
/*
* The computed hash length should match.
*/
if (length != nsec3.next_length) {
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring NSEC bad length %u vs %u",
length, nsec3.next_length);
return (ISC_R_IGNORE);
}
order = memcmp(hash, owner, length);
if (first && order == 0) {
/*
* The hashes are the same.
*/
atparent = dns_rdatatype_atparent(type);
ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
if (ns && !soa) {
if (!atparent) {
/*
* This NSEC3 record is from somewhere
* higher in the DNS, and at the
* parent of a delegation. It can not
* be legitimately used here.
*/
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring parent NSEC3");
return (ISC_R_IGNORE);
}
} else if (atparent && ns && soa) {
/*
* This NSEC3 record is from the child.
* It can not be legitimately used here.
*/
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring child NSEC3");
return (ISC_R_IGNORE);
}
if (type == dns_rdatatype_cname ||
type == dns_rdatatype_nxt ||
type == dns_rdatatype_nsec ||
type == dns_rdatatype_key ||
!dns_nsec3_typepresent(&rdata, dns_rdatatype_cname)) {
*exists = ISC_TRUE;
*data = dns_nsec3_typepresent(&rdata, type);
(*logit)(arg, ISC_LOG_DEBUG(3),
"NSEC3 proves name exists (owner) "
"data=%d", *data);
return (ISC_R_SUCCESS);
}
(*logit)(arg, ISC_LOG_DEBUG(3),
"NSEC3 proves CNAME exists");
return (ISC_R_IGNORE);
}
if (order == 0 &&
dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
!dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
{
/*
* This NSEC3 record is from somewhere higher in
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
(*logit)(arg, ISC_LOG_DEBUG(3),
"ignoring parent NSEC3");
return (ISC_R_IGNORE);
}
/*
* Potential closest encloser.
*/
if (order == 0) {
if (closest != NULL &&
(dns_name_countlabels(closest) == 0 ||
dns_name_issubdomain(qname, closest)) &&
!dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
!dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
(dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
!dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
{
dns_name_format(qname, namebuf,
sizeof(namebuf));
(*logit)(arg, ISC_LOG_DEBUG(3),
"NSEC3 indicates potential closest "
"encloser: '%s'", namebuf);
dns_name_copy(qname, closest, NULL);
*setclosest = ISC_TRUE;
}
dns_name_format(qname, namebuf, sizeof(namebuf));
(*logit)(arg, ISC_LOG_DEBUG(3),
"NSEC3 at super-domain %s", namebuf);
return (answer);
}
/*
* Find if the name does not exist.
*
* We continue as we need to find the name closest to the
* closest encloser that doesn't exist.
*
* We also need to continue to ensure that we are not
* proving the non-existence of a record in a sub-zone.
* If that would be the case we will return ISC_R_IGNORE
* above.
*/
if ((scope < 0 && order > 0 &&
memcmp(hash, nsec3.next, length) < 0) ||
(scope >= 0 && (order > 0 ||
memcmp(hash, nsec3.next, length) < 0)))
{
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(qname, namebuf, sizeof(namebuf));
(*logit)(arg, ISC_LOG_DEBUG(3), "NSEC3 proves "
"name does not exist: '%s'", namebuf);
if (nearest != NULL &&
(dns_name_countlabels(nearest) == 0 ||
dns_name_issubdomain(nearest, qname))) {
dns_name_copy(qname, nearest, NULL);
*setnearest = ISC_TRUE;
}
*exists = ISC_FALSE;
*data = ISC_FALSE;
if (optout != NULL) {
if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
(*logit)(arg, ISC_LOG_DEBUG(3),
"NSEC3 indicates optout");
*optout =
ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
}
answer = ISC_R_SUCCESS;
}
qlabels--;
if (qlabels > 0)
dns_name_split(qname, qlabels, NULL, qname);
first = ISC_FALSE;
}
return (answer);
}

View file

@ -21,6 +21,7 @@
#include <config.h>
#include <isc/log.h>
#include <isc/platform.h>
#include <isc/print.h>
#include <isc/string.h>
@ -43,6 +44,8 @@
#include <dns/log.h>
#include <dns/message.h>
#include <dns/ncache.h>
#include <dns/nsec.h>
#include <dns/nsec3.h>
#include <dns/opcode.h>
#include <dns/peer.h>
#include <dns/rbt.h>
@ -76,7 +79,7 @@
DNS_LOGCATEGORY_RESOLVER, \
DNS_LOGMODULE_RESOLVER, \
ISC_LOG_DEBUG(3), \
"fctx %p(%s'): %s", fctx, fctx->info, (m))
"fctx %p(%s): %s", fctx, fctx->info, (m))
#define FCTXTRACE2(m1, m2) \
isc_log_write(dns_lctx, \
DNS_LOGCATEGORY_RESOLVER, \
@ -475,6 +478,9 @@ static void validated(isc_task_t *task, isc_event_t *event);
static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked);
static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
isc_result_t reason, badnstype_t badtype);
static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name,
dns_rdatatype_t type,
dns_name_t **noqname);
/*%
* Increment resolver-related statistics counters.
@ -4252,7 +4258,6 @@ validated(isc_task_t *task, isc_event_t *event) {
FCTXTRACE("validation OK");
if (vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF] != NULL) {
result = dns_rdataset_addnoqname(vevent->rdataset,
vevent->proofs[DNS_VALIDATOR_NOQNAMEPROOF]);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
@ -4263,6 +4268,18 @@ validated(isc_task_t *task, isc_event_t *event) {
vevent->proofs[DNS_VALIDATOR_CLOSESTENCLOSER]);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
}
} else if (vevent->rdataset->trust == dns_trust_answer &&
vevent->rdataset->type != dns_rdatatype_rrsig)
{
isc_result_t tresult;
dns_name_t *noqname = NULL;
tresult = findnoqname(fctx, vevent->name,
vevent->rdataset->type, &noqname);
if (tresult == ISC_R_SUCCESS && noqname != NULL) {
tresult = dns_rdataset_addnoqname(vevent->rdataset,
noqname);
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
}
}
/*
@ -4403,6 +4420,133 @@ validated(isc_task_t *task, isc_event_t *event) {
isc_event_free(&event);
}
static void
log(void *arg, int level, const char *fmt, ...) {
char msgbuf[2048];
va_list args;
fetchctx_t *fctx = arg;
va_start(args, fmt);
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
va_end(args);
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, level,
"fctx %p(%s): %s", fctx, fctx->info, msgbuf);
}
static inline isc_result_t
findnoqname(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type,
dns_name_t **noqname)
{
dns_rdataset_t *nrdataset, *next, *sigrdataset;
dns_rdata_rrsig_t rrsig;
isc_result_t result;
unsigned int labels;
dns_section_t section;
dns_name_t *zonename;
dns_fixedname_t fzonename;
dns_name_t *closest;
dns_fixedname_t fclosest;
dns_name_t *nearest;
dns_fixedname_t fnearest;
FCTXTRACE("findnoqname");
REQUIRE(noqname != NULL && *noqname == NULL);
/*
* Find the SIG for this rdataset, if we have it.
*/
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
if (sigrdataset->type == dns_rdatatype_rrsig &&
sigrdataset->covers == type)
break;
}
if (sigrdataset == NULL)
return (ISC_R_NOTFOUND);
labels = dns_name_countlabels(name);
for (result = dns_rdataset_first(sigrdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(sigrdataset)) {
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(sigrdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
/* Wildcard has rrsig.labels < labels - 1. */
if (rrsig.labels + 1 >= labels)
continue;
break;
}
if (result == ISC_R_NOMORE)
return (ISC_R_NOTFOUND);
if (result != ISC_R_SUCCESS)
return (result);
dns_fixedname_init(&fzonename);
zonename = dns_fixedname_name(&fzonename);
dns_fixedname_init(&fclosest);
closest = dns_fixedname_name(&fclosest);
dns_fixedname_init(&fnearest);
nearest = dns_fixedname_name(&fnearest);
#define NXND(x) ((x) == ISC_R_SUCCESS)
section = DNS_SECTION_AUTHORITY;
for (result = dns_message_firstname(fctx->rmessage, section);
result == ISC_R_SUCCESS;
result = dns_message_nextname(fctx->rmessage, section)) {
dns_name_t *nsec = NULL;
dns_message_currentname(fctx->rmessage, section, &nsec);
for (nrdataset = ISC_LIST_HEAD(nsec->list);
nrdataset != NULL; nrdataset = next) {
isc_boolean_t data = ISC_FALSE, exists = ISC_FALSE;
isc_boolean_t optout = ISC_FALSE, unknown = ISC_FALSE;
isc_boolean_t setclosest = ISC_FALSE;
isc_boolean_t setnearest = ISC_FALSE;
char namebuf[DNS_NAME_FORMATSIZE];
next = ISC_LIST_NEXT(nrdataset, link);
if (nrdataset->type != dns_rdatatype_nsec &&
nrdataset->type != dns_rdatatype_nsec3)
continue;
dns_name_format(nsec, namebuf, sizeof(namebuf));
if (nrdataset->type == dns_rdatatype_nsec &&
NXND(dns_nsec_noexistnodata(type, name, nsec,
nrdataset, &exists,
&data, NULL, log,
fctx)))
{
if (!exists)
*noqname = nsec;
}
if (nrdataset->type == dns_rdatatype_nsec3 &&
NXND(dns_nsec3_noexistnodata(type, name, nsec,
nrdataset, zonename,
&exists, &data,
&optout, &unknown,
&setclosest,
&setnearest,
closest, nearest,
log, fctx)))
{
if (!exists && setnearest)
*noqname = nsec;
}
}
}
if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
return (result);
}
static inline isc_result_t
cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
isc_stdtime_t now)
@ -4535,6 +4679,17 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
if (rdataset->ttl > res->view->maxcachettl)
rdataset->ttl = res->view->maxcachettl;
/*
* Find the SIG for this rdataset, if we have it.
*/
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
if (sigrdataset->type == dns_rdatatype_rrsig &&
sigrdataset->covers == rdataset->type)
break;
}
/*
* If this RRset is in a secure domain, is in bailiwick,
* and is not glue, attempt DNSSEC validation. (We do not
@ -4555,16 +4710,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
*/
if (rdataset->type == dns_rdatatype_rrsig)
continue;
/*
* Find the SIG for this rdataset, if we have it.
*/
for (sigrdataset = ISC_LIST_HEAD(name->list);
sigrdataset != NULL;
sigrdataset = ISC_LIST_NEXT(sigrdataset, link)) {
if (sigrdataset->type == dns_rdatatype_rrsig &&
sigrdataset->covers == rdataset->type)
break;
}
if (sigrdataset == NULL) {
if (!ANSWER(rdataset) && need_validation) {
/*
@ -4725,6 +4871,21 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
options = DNS_DBADD_FORCE;
} else
options = 0;
if (ANSWER(rdataset) &&
rdataset->type != dns_rdatatype_rrsig) {
isc_result_t tresult;
dns_name_t *noqname = NULL;
tresult = findnoqname(fctx, name,
rdataset->type, &noqname);
if (tresult == ISC_R_SUCCESS &&
noqname != NULL) {
tresult = dns_rdataset_addnoqname(
rdataset, noqname);
RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
}
}
/*
* Now we can add the rdataset.
*/
@ -4733,6 +4894,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
rdataset,
options,
addedrdataset);
if (result == DNS_R_UNCHANGED) {
if (ANSWER(rdataset) &&
ardataset != NULL &&

View file

@ -157,7 +157,7 @@ validator_logv(dns_validator_t *val, isc_logcategory_t *category,
ISC_FORMAT_PRINTF(5, 0);
static void
validator_log(dns_validator_t *val, int level, const char *fmt, ...)
validator_log(void *val, int level, const char *fmt, ...)
ISC_FORMAT_PRINTF(3, 4);
static void
@ -843,452 +843,6 @@ cnamevalidated(isc_task_t *task, isc_event_t *event) {
destroy(val);
}
/*%
* Return ISC_R_SUCCESS if we can determine that the name doesn't exist
* or we can determine whether there is data or not at the name.
* If the name does not exist return the wildcard name.
*
* Return ISC_R_IGNORE when the NSEC is not the appropriate one.
*/
static isc_result_t
nsecnoexistnodata(dns_validator_t *val, dns_name_t *name, dns_name_t *nsecname,
dns_rdataset_t *nsecset, isc_boolean_t *exists,
isc_boolean_t *data, dns_name_t *wild)
{
int order;
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_result_t result;
dns_namereln_t relation;
unsigned int olabels, nlabels, labels;
dns_rdata_nsec_t nsec;
isc_boolean_t atparent;
isc_boolean_t ns;
isc_boolean_t soa;
REQUIRE(exists != NULL);
REQUIRE(data != NULL);
REQUIRE(nsecset != NULL &&
nsecset->type == dns_rdatatype_nsec);
result = dns_rdataset_first(nsecset);
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3),
"failure processing NSEC set");
return (result);
}
dns_rdataset_current(nsecset, &rdata);
validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nsec");
relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
if (order < 0) {
/*
* The name is not within the NSEC range.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC does not cover name, before NSEC");
return (ISC_R_IGNORE);
}
if (order == 0) {
/*
* The names are the same. If we are validating "."
* then atparent should not be set as there is no parent.
*/
atparent = (olabels != 1) &&
dns_rdatatype_atparent(val->event->type);
ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
if (ns && !soa) {
if (!atparent) {
/*
* This NSEC record is from somewhere higher in
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring parent nsec");
return (ISC_R_IGNORE);
}
} else if (atparent && ns && soa) {
/*
* This NSEC record is from the child.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring child nsec");
return (ISC_R_IGNORE);
}
if (val->event->type == dns_rdatatype_cname ||
val->event->type == dns_rdatatype_nxt ||
val->event->type == dns_rdatatype_nsec ||
val->event->type == dns_rdatatype_key ||
!dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
*exists = ISC_TRUE;
*data = dns_nsec_typepresent(&rdata, val->event->type);
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves name exists (owner) data=%d",
*data);
return (ISC_R_SUCCESS);
}
validator_log(val, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
return (ISC_R_IGNORE);
}
if (relation == dns_namereln_subdomain &&
dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
!dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
{
/*
* This NSEC record is from somewhere higher in
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3), "ignoring parent nsec");
return (ISC_R_IGNORE);
}
result = dns_rdata_tostruct(&rdata, &nsec, NULL);
if (result != ISC_R_SUCCESS)
return (result);
relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
if (order == 0) {
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring nsec matches next name");
return (ISC_R_IGNORE);
}
if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
/*
* The name is not within the NSEC range.
*/
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring nsec because name is past end of range");
return (ISC_R_IGNORE);
}
if (order > 0 && relation == dns_namereln_subdomain) {
validator_log(val, ISC_LOG_DEBUG(3),
"nsec proves name exist (empty)");
dns_rdata_freestruct(&nsec);
*exists = ISC_TRUE;
*data = ISC_FALSE;
return (ISC_R_SUCCESS);
}
if (wild != NULL) {
dns_name_t common;
dns_name_init(&common, NULL);
if (olabels > nlabels) {
labels = dns_name_countlabels(nsecname);
dns_name_getlabelsequence(nsecname, labels - olabels,
olabels, &common);
} else {
labels = dns_name_countlabels(&nsec.next);
dns_name_getlabelsequence(&nsec.next, labels - nlabels,
nlabels, &common);
}
result = dns_name_concatenate(dns_wildcardname, &common,
wild, NULL);
if (result != ISC_R_SUCCESS) {
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3),
"failure generating wildcard name");
return (result);
}
}
dns_rdata_freestruct(&nsec);
validator_log(val, ISC_LOG_DEBUG(3), "nsec range ok");
*exists = ISC_FALSE;
return (ISC_R_SUCCESS);
}
static isc_result_t
nsec3noexistnodata(dns_validator_t *val, dns_name_t* name,
dns_name_t *nsec3name, dns_rdataset_t *nsec3set,
dns_name_t *zonename, isc_boolean_t *exists,
isc_boolean_t *data, isc_boolean_t *optout,
isc_boolean_t *unknown, isc_boolean_t *setclosest,
isc_boolean_t *setnearest, dns_name_t *closest,
dns_name_t *nearest)
{
char namebuf[DNS_NAME_FORMATSIZE];
dns_fixedname_t fzone;
dns_fixedname_t qfixed;
dns_label_t hashlabel;
dns_name_t *qname;
dns_name_t *zone;
dns_rdata_nsec3_t nsec3;
dns_rdata_t rdata = DNS_RDATA_INIT;
int order;
int scope;
isc_boolean_t atparent;
isc_boolean_t first;
isc_boolean_t ns;
isc_boolean_t soa;
isc_buffer_t buffer;
isc_result_t answer = ISC_R_IGNORE;
isc_result_t result;
unsigned char hash[NSEC3_MAX_HASH_LENGTH];
unsigned char owner[NSEC3_MAX_HASH_LENGTH];
unsigned int length;
unsigned int qlabels;
unsigned int zlabels;
REQUIRE((exists == NULL && data == NULL) ||
(exists != NULL && data != NULL));
REQUIRE(nsec3set != NULL && nsec3set->type == dns_rdatatype_nsec3);
REQUIRE((setclosest == NULL && closest == NULL) ||
(setclosest != NULL && closest != NULL));
REQUIRE((setnearest == NULL && nearest == NULL) ||
(setnearest != NULL && nearest != NULL));
result = dns_rdataset_first(nsec3set);
if (result != ISC_R_SUCCESS) {
validator_log(val, ISC_LOG_DEBUG(3),
"failure processing NSEC3 set");
return (result);
}
dns_rdataset_current(nsec3set, &rdata);
result = dns_rdata_tostruct(&rdata, &nsec3, NULL);
if (result != ISC_R_SUCCESS)
return (result);
validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant NSEC3");
dns_fixedname_init(&fzone);
zone = dns_fixedname_name(&fzone);
zlabels = dns_name_countlabels(nsec3name);
/*
* NSEC3 records must have two or more labels to be valid.
*/
if (zlabels < 2)
return (ISC_R_IGNORE);
/*
* Strip off the NSEC3 hash to get the zone.
*/
zlabels--;
dns_name_split(nsec3name, zlabels, NULL, zone);
/*
* If not below the zone name we can ignore this record.
*/
if (!dns_name_issubdomain(name, zone))
return (ISC_R_IGNORE);
/*
* Is this zone the same or deeper than the current zone?
*/
if (dns_name_countlabels(zonename) == 0 ||
dns_name_issubdomain(zone, zonename))
dns_name_copy(zone, zonename, NULL);
if (!dns_name_equal(zone, zonename))
return (ISC_R_IGNORE);
/*
* Are we only looking for the most enclosing zone?
*/
if (exists == NULL || data == NULL)
return (ISC_R_SUCCESS);
/*
* Only set unknown once we are sure that this NSEC3 is from
* the deepest covering zone.
*/
if (!dns_nsec3_supportedhash(nsec3.hash)) {
if (unknown != NULL)
*unknown = ISC_TRUE;
return (ISC_R_IGNORE);
}
/*
* Recover the hash from the first label.
*/
dns_name_getlabel(nsec3name, 0, &hashlabel);
isc_region_consume(&hashlabel, 1);
isc_buffer_init(&buffer, owner, sizeof(owner));
result = isc_base32hex_decoderegion(&hashlabel, &buffer);
if (result != ISC_R_SUCCESS)
return (result);
/*
* The hash lengths should match. If not ignore the record.
*/
if (isc_buffer_usedlength(&buffer) != nsec3.next_length)
return (ISC_R_IGNORE);
/*
* Work out what this NSEC3 covers.
* Inside (<0) or outside (>=0).
*/
scope = memcmp(owner, nsec3.next, nsec3.next_length);
/*
* Prepare to compute all the hashes.
*/
dns_fixedname_init(&qfixed);
qname = dns_fixedname_name(&qfixed);
dns_name_downcase(name, qname, NULL);
qlabels = dns_name_countlabels(qname);
first = ISC_TRUE;
while (qlabels >= zlabels) {
length = isc_iterated_hash(hash, nsec3.hash, nsec3.iterations,
nsec3.salt, nsec3.salt_length,
qname->ndata, qname->length);
/*
* The computed hash length should match.
*/
if (length != nsec3.next_length) {
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring NSEC bad length %u vs %u",
length, nsec3.next_length);
return (ISC_R_IGNORE);
}
order = memcmp(hash, owner, length);
if (first && order == 0) {
/*
* The hashes are the same.
*/
atparent = dns_rdatatype_atparent(val->event->type);
ns = dns_nsec3_typepresent(&rdata, dns_rdatatype_ns);
soa = dns_nsec3_typepresent(&rdata, dns_rdatatype_soa);
if (ns && !soa) {
if (!atparent) {
/*
* This NSEC3 record is from somewhere
* higher in the DNS, and at the
* parent of a delegation. It can not
* be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring parent NSEC3");
return (ISC_R_IGNORE);
}
} else if (atparent && ns && soa) {
/*
* This NSEC3 record is from the child.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring child NSEC3");
return (ISC_R_IGNORE);
}
if (val->event->type == dns_rdatatype_cname ||
val->event->type == dns_rdatatype_nxt ||
val->event->type == dns_rdatatype_nsec ||
val->event->type == dns_rdatatype_key ||
!dns_nsec3_typepresent(&rdata, dns_rdatatype_cname)) {
*exists = ISC_TRUE;
*data = dns_nsec3_typepresent(&rdata,
val->event->type);
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC3 proves name exists (owner) "
"data=%d", *data);
return (ISC_R_SUCCESS);
}
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC3 proves CNAME exists");
return (ISC_R_IGNORE);
}
if (order == 0 &&
dns_nsec3_typepresent(&rdata, dns_rdatatype_ns) &&
!dns_nsec3_typepresent(&rdata, dns_rdatatype_soa))
{
/*
* This NSEC3 record is from somewhere higher in
* the DNS, and at the parent of a delegation.
* It can not be legitimately used here.
*/
validator_log(val, ISC_LOG_DEBUG(3),
"ignoring parent NSEC3");
return (ISC_R_IGNORE);
}
/*
* Potential closest encloser.
*/
if (order == 0) {
if (closest != NULL &&
(dns_name_countlabels(closest) == 0 ||
dns_name_issubdomain(qname, closest)) &&
!dns_nsec3_typepresent(&rdata, dns_rdatatype_ds) &&
!dns_nsec3_typepresent(&rdata, dns_rdatatype_dname) &&
(dns_nsec3_typepresent(&rdata, dns_rdatatype_soa) ||
!dns_nsec3_typepresent(&rdata, dns_rdatatype_ns)))
{
dns_name_format(qname, namebuf,
sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC3 indicates potential "
"closest encloser: '%s'",
namebuf);
dns_name_copy(qname, closest, NULL);
*setclosest = ISC_TRUE;
}
dns_name_format(qname, namebuf, sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC3 at super-domain %s", namebuf);
return (answer);
}
/*
* Find if the name does not exist.
*
* We continue as we need to find the name closest to the
* closest encloser that doesn't exist.
*
* We also need to continue to ensure that we are not
* proving the non-existence of a record in a sub-zone.
* If that would be the case we will return ISC_R_IGNORE
* above.
*/
if ((scope < 0 && order > 0 &&
memcmp(hash, nsec3.next, length) < 0) ||
(scope >= 0 && (order > 0 ||
memcmp(hash, nsec3.next, length) < 0)))
{
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(qname, namebuf, sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(3), "NSEC3 proves "
"name does not exist: '%s'", namebuf);
if (nearest != NULL &&
(dns_name_countlabels(nearest) == 0 ||
dns_name_issubdomain(nearest, qname))) {
dns_name_copy(qname, nearest, NULL);
*setnearest = ISC_TRUE;
}
*exists = ISC_FALSE;
*data = ISC_FALSE;
if (optout != NULL) {
if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0)
validator_log(val, ISC_LOG_DEBUG(3),
"NSEC3 indicates optout");
*optout =
ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT);
}
answer = ISC_R_SUCCESS;
}
qlabels--;
if (qlabels > 0)
dns_name_split(qname, qlabels, NULL, qname);
first = ISC_FALSE;
}
return (answer);
}
/*%
* Callback for when NSEC records have been validated.
*
@ -1344,8 +898,9 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
rdataset->trust == dns_trust_secure &&
(NEEDNODATA(val) || NEEDNOQNAME(val)) &&
!FOUNDNODATA(val) && !FOUNDNOQNAME(val) &&
nsecnoexistnodata(val, val->event->name, devent->name,
rdataset, &exists, &data, wild)
dns_nsec_noexistnodata(val->event->type, val->event->name,
devent->name, rdataset, &exists,
&data, wild, validator_log, val)
== ISC_R_SUCCESS)
{
if (exists && !data) {
@ -2845,8 +2400,9 @@ checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
if (rdataset->type == dns_rdatatype_nsec &&
(NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
!FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
nsecnoexistnodata(val, wild, name, rdataset,
&exists, &data, NULL)
dns_nsec_noexistnodata(val->event->type, wild, name,
rdataset, &exists, &data, NULL,
validator_log, val)
== ISC_R_SUCCESS)
{
dns_name_t **proofs = val->event->proofs;
@ -2869,10 +2425,11 @@ checkwildcard(dns_validator_t *val, dns_rdatatype_t type, dns_name_t *zonename)
if (rdataset->type == dns_rdatatype_nsec3 &&
(NEEDNODATA(val) || NEEDNOWILDCARD(val)) &&
!FOUNDNODATA(val) && !FOUNDNOWILDCARD(val) &&
nsec3noexistnodata(val, wild, name, rdataset,
zonename, &exists, &data,
NULL, NULL, NULL, NULL, NULL,
NULL) == ISC_R_SUCCESS)
dns_nsec3_noexistnodata(val->event->type, wild, name,
rdataset, zonename, &exists, &data,
NULL, NULL, NULL, NULL, NULL, NULL,
validator_log, val)
== ISC_R_SUCCESS)
{
dns_name_t **proofs = val->event->proofs;
if (exists && !data)
@ -2934,11 +2491,12 @@ findnsec3proofs(dns_validator_t *val) {
rdataset->trust != dns_trust_secure)
continue;
result = nsec3noexistnodata(val, val->event->name,
name, rdataset,
zonename, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
NULL);
result = dns_nsec3_noexistnodata(val->event->type,
val->event->name, name,
rdataset, zonename, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL, NULL, validator_log,
val);
if (result != ISC_R_IGNORE && result != ISC_R_SUCCESS) {
if (dns_rdataset_isassociated(&trdataset))
dns_rdataset_disassociate(&trdataset);
@ -2986,11 +2544,13 @@ findnsec3proofs(dns_validator_t *val) {
setclosest = setnearest = ISC_FALSE;
optout = ISC_FALSE;
unknown = ISC_FALSE;
result = nsec3noexistnodata(val, val->event->name, name,
rdataset, zonename, &exists,
&data, &optout, &unknown,
setclosestp, &setnearest,
closestp, nearest);
result = dns_nsec3_noexistnodata(val->event->type,
val->event->name,
name, rdataset, zonename,
&exists, &data, &optout,
&unknown, setclosestp,
&setnearest, closestp,
nearest, validator_log, val);
if (unknown)
val->attributes |= VALATTR_FOUNDUNKNOWN;
if (result != ISC_R_SUCCESS)
@ -4366,7 +3926,7 @@ validator_logv(dns_validator_t *val, isc_logcategory_t *category,
}
static void
validator_log(dns_validator_t *val, int level, const char *fmt, ...) {
validator_log(void *val, int level, const char *fmt, ...) {
va_list ap;
if (! isc_log_wouldlog(dns_lctx, level))