]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
3461. [bug] Negative responses could incorrectly have AD=1
authorMark Andrews <marka@isc.org>
Thu, 10 Jan 2013 11:38:10 +0000 (22:38 +1100)
committerMark Andrews <marka@isc.org>
Thu, 10 Jan 2013 11:38:10 +0000 (22:38 +1100)
                        set. [RT #32237]

18 files changed:
CHANGES
bin/named/include/named/globals.h
bin/named/main.c
bin/named/query.c
bin/tests/system/dnssec/clean.sh
bin/tests/system/dnssec/ns1/root.db.in
bin/tests/system/dnssec/ns1/sign.sh
bin/tests/system/dnssec/ns6/named.args [new file with mode: 0644]
bin/tests/system/dnssec/ns6/named.conf
bin/tests/system/dnssec/ns6/optout-tld.db.in [new file with mode: 0644]
bin/tests/system/dnssec/ns6/sign.sh [new file with mode: 0644]
bin/tests/system/dnssec/tests.sh
lib/dns/include/dns/ncache.h
lib/dns/include/dns/validator.h
lib/dns/ncache.c
lib/dns/nsec.c
lib/dns/resolver.c
lib/dns/validator.c

diff --git a/CHANGES b/CHANGES
index c51e2c7a19a8e6cdd8926ebe92de9323df1511d0..d7abf2ced6c4fc1b477b44df926a49bd23b8889d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3461.  [bug]           Negative responses could incorrectly have AD=1
+                       set. [RT #32237]
+
 3460.  [bug]           Only link against readline where needed. [RT #29810]
 
 3458.  [bug]           Return FORMERR when presented with a overly long
index b65ffd6d75bbd8a746a54384f58f78f3b18ffb00..56a30fe6eacf16f4a2b83501ed78ced53a00d237 100644 (file)
@@ -156,6 +156,7 @@ EXTERN isc_boolean_t                ns_g_memstatistics      INIT(ISC_FALSE);
 EXTERN isc_boolean_t           ns_g_clienttest         INIT(ISC_FALSE);
 EXTERN isc_boolean_t           ns_g_nosoa              INIT(ISC_FALSE);
 EXTERN isc_boolean_t           ns_g_noaa               INIT(ISC_FALSE);
+EXTERN isc_boolean_t           ns_g_nonearest          INIT(ISC_FALSE);
 
 #undef EXTERN
 #undef INIT
index 2336655eaf681e5087e9293fd9e243941091fe68..74ca3a2e3113dd26c95a4b52e69ba25f60cb4ab5 100644 (file)
@@ -525,6 +525,8 @@ parse_command_line(int argc, char *argv[]) {
                                maxudp = 1460;
                        else if (!strcmp(isc_commandline_argument, "nosyslog"))
                                ns_g_nosyslog = ISC_TRUE;
+                       else if (!strcmp(isc_commandline_argument, "nonearest"))
+                               ns_g_nonearest = ISC_TRUE;
                        else
                                fprintf(stderr, "unknown -T flag '%s\n",
                                        isc_commandline_argument);
index 71f2d851f572dfc2942be97ef2de38ca1e03b7f6..87394ba51b79cf6087ba2205cb4e3b75930c4001 100644 (file)
@@ -6344,7 +6344,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                                 * closest provable encloser.
                                 */
                                if (dns_rdataset_isassociated(rdataset) &&
-                                   !dns_name_equal(qname, found)) {
+                                   !dns_name_equal(qname, found) &&
+                                   !(ns_g_nonearest &&
+                                     qtype != dns_rdatatype_ds))
+                               {
                                        unsigned int count;
                                        unsigned int skip;
 
index c4f0c086001aa4c7a2f9555f8a363d8f3b9de987..3666a81dd6b74a179ce828dcca298c747ef167bd 100644 (file)
@@ -63,6 +63,7 @@ rm -f ns3/ttlpatch.example.db.patched
 rm -f ns3/split-smart.example.db
 rm -f ns3/inline.example.db.signed
 rm -f ns3/lower.example.db ns3/upper.example.db ns3/upper.example.db.lower
+rm -f ns6/optout-tld.db
 rm -f nosign.before
 rm -f signing.out*
 rm -f canonical?.*
index 4ff12582bdc1b8062ece9239ad7f56285a600631..be8d55db3f8f486671633fb3ad68f9e3c512df01 100644 (file)
@@ -32,3 +32,5 @@ dlv.                  NS      ns2.dlv.
 ns2.dlv.               A       10.53.0.2
 algroll                        NS      ns2.algroll
 ns2.algroll.           A       10.53.0.2
+optout-tld             NS      ns6.optout-tld.
+ns6.optout-tld.                A       10.53.0.6
index 96fc060bd86daf10c84dd114a77de131647ab50d..0b117fb2aaec129e4f2e796c08e1c9a499608af3 100644 (file)
@@ -27,10 +27,12 @@ infile=root.db.in
 zonefile=root.db
 
 (cd ../ns2 && sh sign.sh )
+(cd ../ns6 && sh sign.sh )
 
 cp ../ns2/dsset-example. .
 cp ../ns2/dsset-dlv. .
 grep "8 [12] " ../ns2/dsset-algroll. > dsset-algroll.
+cp ../ns6/dsset-optout-tld. .
 
 keyname=`$KEYGEN -q -r $RANDFILE -a RSAMD5 -b 768 -n zone $zone`
 
diff --git a/bin/tests/system/dnssec/ns6/named.args b/bin/tests/system/dnssec/ns6/named.args
new file mode 100644 (file)
index 0000000..340fbaf
--- /dev/null
@@ -0,0 +1 @@
+-m record,size,mctx -c named.conf -d 99 -g -T nonearest -T clienttest
index eb35680ef2c9ab3cf4c5160f2510d49701d20679..54221cefbdde33b8c5c4eebbd34e19690aee6d56 100644 (file)
@@ -42,4 +42,9 @@ zone "." {
        file "../../common/root.hint";
 };
 
+zone "optout-tld" {
+       type master;
+       file "optout-tld.db.signed";
+};
+
 include "trusted.conf";
diff --git a/bin/tests/system/dnssec/ns6/optout-tld.db.in b/bin/tests/system/dnssec/ns6/optout-tld.db.in
new file mode 100644 (file)
index 0000000..8cdb0aa
--- /dev/null
@@ -0,0 +1,26 @@
+; 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: example.db.in,v 1.2 2010/06/03 06:29:03 marka Exp $
+$TTL 60
+optout-tld. 60 IN SOA example. . 0 0 0 0 0
+optout-tld. 60 IN NS ns6.optout-tld.
+ns6.optout-tld. 60 IN A 10.53.0.6
+a 60 PTR example.
+b 60 PTR example.
+a.b.c.d 60 NS example.
+e 60 PTR example.
+f 60 PTR example.
+g 60 PTR example.
+h 60 PTR example.
diff --git a/bin/tests/system/dnssec/ns6/sign.sh b/bin/tests/system/dnssec/ns6/sign.sh
new file mode 100644 (file)
index 0000000..7c1179d
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh -e
+#
+# Copyright (C) 2004, 2006-2012  Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002  Internet Software Consortium.
+#
+# 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.43 2011/11/04 05:36:28 each Exp $
+
+SYSTEMTESTTOP=../..
+. $SYSTEMTESTTOP/conf.sh
+
+RANDFILE=../random.data
+
+zone=optout-tld
+infile=optout-tld.db.in
+zonefile=optout-tld.db
+
+keyname=`$KEYGEN -q -r $RANDFILE -a RSASHA256 -b 768 -n zone $zone`
+
+cat $infile $keyname.key >$zonefile
+
+$SIGNER -P -3 - -A -r $RANDFILE -o $zone $zonefile > /dev/null 2>&1
index d306aa8d3e376299c7a601568c974f23d7e7ada6..fc3669ba6b5daca8045b3621f5c439cf7c5c75fc 100644 (file)
@@ -1965,5 +1965,25 @@ n=`expr $n + 1`
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+echo "I:check against against missing nearest provable proof ($n)"
+$DIG $DIGOPTS +norec b.c.d.optout-tld. \
+       @10.53.0.6 ds > dig.out.ds.ns6.test$n || ret=1
+nsec3=`grep "IN.NSEC3" dig.out.ds.ns6.test$n | wc -l`
+[ $nsec3 -eq 2 ] || ret=1
+$DIG $DIGOPTS +norec b.c.d.optout-tld. \
+       @10.53.0.6 A > dig.out.ns6.test$n || ret=1
+nsec3=`grep "IN.NSEC3" dig.out.ns6.test$n | wc -l`
+[ $nsec3 -eq 1 ] || ret=1
+$DIG $DIGOPTS optout-tld. \
+       @10.53.0.4 SOA > dig.out.soa.ns4.test$n || ret=1
+grep "flags:.*ad.*QUERY" dig.out.soa.ns4.test$n > /dev/null || ret=1
+$DIG $DIGOPTS b.c.d.optout-tld. \
+       @10.53.0.4 A > dig.out.ns4.test$n || ret=1
+grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1
+grep "flags:.*ad.*QUERY" dig.out.ns4.test$n > /dev/null && ret=1
+n=`expr $n + 1`
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 echo "I:exit status: $status"
 exit $status
index 8d89879cc5e4f762480518d4aac0ae84c3582751..5064e91171d5791f40ff8ce277f94d5ddde4bb3e 100644 (file)
@@ -73,6 +73,11 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
  * rdataset, and store it in 'cache' at 'node' with a TTL limited to
  * 'maxttl'.
  *
+ * \li dns_ncache_add produces a negative cache entry with a trust of no
+ *     more than answer
+ * \li dns_ncache_addoptout produces a negative cache entry which will have
+ *     a trust of secure if all the records that make up the entry are secure.
+ *
  * The 'covers' argument is the RR type whose nonexistence we are caching,
  * or dns_rdatatype_any when caching a NXDOMAIN response.
  *
index 7d6ea7a89d2f7539f84553263817a741f4e30906..486510a6fd65ed98bb307b0a3c11291ccc1cb4cc 100644 (file)
@@ -104,6 +104,10 @@ typedef struct dns_validatorevent {
         * Optout proof seen.
         */
        isc_boolean_t                   optout;
+       /*
+        * Answer is secure.
+        */
+       isc_boolean_t                   secure;
 } dns_validatorevent_t;
 
 #define DNS_VALIDATOR_NOQNAMEPROOF 0
index c0e99d4969d467366b48eda03c9e7870e67f4e90..7d50abc4dfffc269d2511aa5ebb7245429fb7953 100644 (file)
  *
  */
 
+static isc_result_t
+addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
+         dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
+         isc_boolean_t optout, isc_boolean_t secure,
+         dns_rdataset_t *addedrdataset);
+
 static inline isc_result_t
 copy_rdataset(dns_rdataset_t *rdataset, isc_buffer_t *buffer) {
        isc_result_t result;
@@ -96,8 +102,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
               dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
               dns_rdataset_t *addedrdataset)
 {
-       return (dns_ncache_addoptout(message, cache, node, covers, now, maxttl,
-                                   ISC_FALSE, addedrdataset));
+       return (addoptout(message, cache, node, covers, now, maxttl,
+                         ISC_FALSE, ISC_FALSE, addedrdataset));
 }
 
 isc_result_t
@@ -105,6 +111,16 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
                     dns_dbnode_t *node, dns_rdatatype_t covers,
                     isc_stdtime_t now, dns_ttl_t maxttl,
                     isc_boolean_t optout, dns_rdataset_t *addedrdataset)
+{
+       return (addoptout(message, cache, node, covers, now, maxttl,
+                         optout, ISC_TRUE, addedrdataset));
+}
+
+static isc_result_t
+addoptout(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
+         dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
+         isc_boolean_t optout, isc_boolean_t secure,
+         dns_rdataset_t *addedrdataset)
 {
        isc_result_t result;
        isc_buffer_t buffer;
@@ -242,6 +258,8 @@ dns_ncache_addoptout(dns_message_t *message, dns_db_t *cache,
        dns_rdataset_init(&ncrdataset);
        RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
                      == ISC_R_SUCCESS);
+       if (!secure && trust > dns_trust_answer)
+               trust = dns_trust_answer;
        ncrdataset.trust = trust;
        ncrdataset.attributes |= DNS_RDATASETATTR_NEGATIVE;
        if (message->rcode == dns_rcode_nxdomain)
index 5ae1cf8739194029c94ac960767b53cb93a86787..bbdde55daffda3d0226f23ffa7ad3378244919b9 100644 (file)
@@ -327,7 +327,7 @@ dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name,
        }
        dns_rdataset_current(nsecset, &rdata);
 
-       (*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant nsec");
+       (*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC");
        relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
 
        if (order < 0) {
index 991c68e8cb5b145d815bcc55ad941b0a3b256570..72b34a701fb5eee839ce099cbe7f6e2dca83ebfc 100644 (file)
@@ -471,6 +471,7 @@ static isc_result_t ncache_adderesult(dns_message_t *message,
                                      dns_rdatatype_t covers,
                                      isc_stdtime_t now, dns_ttl_t maxttl,
                                      isc_boolean_t optout,
+                                     isc_boolean_t secure,
                                      dns_rdataset_t *ardataset,
                                      isc_result_t *eresultp);
 static void validated(isc_task_t *task, isc_event_t *event);
@@ -4239,7 +4240,7 @@ validated(isc_task_t *task, isc_event_t *event) {
 
                result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
                                           covers, now, ttl, vevent->optout,
-                                          ardataset, &eresult);
+                                          vevent->secure, ardataset, &eresult);
                if (result != ISC_R_SUCCESS)
                        goto noanswer_response;
                goto answer_response;
@@ -4981,8 +4982,8 @@ cache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_stdtime_t now)
 static isc_result_t
 ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
                  dns_rdatatype_t covers, isc_stdtime_t now, dns_ttl_t maxttl,
-                 isc_boolean_t optout, dns_rdataset_t *ardataset,
-                 isc_result_t *eresultp)
+                 isc_boolean_t optout, isc_boolean_t secure,
+                 dns_rdataset_t *ardataset, isc_result_t *eresultp)
 {
        isc_result_t result;
        dns_rdataset_t rdataset;
@@ -4991,8 +4992,12 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
                dns_rdataset_init(&rdataset);
                ardataset = &rdataset;
        }
-       result = dns_ncache_addoptout(message, cache, node, covers, now,
-                                    maxttl, optout, ardataset);
+       if (secure) 
+               result = dns_ncache_addoptout(message, cache, node, covers,
+                                             now, maxttl, optout, ardataset);
+       else
+               result = dns_ncache_add(message, cache, node, covers, now,
+                                       maxttl, ardataset);
        if (result == DNS_R_UNCHANGED || result == ISC_R_SUCCESS) {
                /*
                 * If the cache now contains a negative entry and we
@@ -5159,7 +5164,7 @@ ncache_message(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
 
        result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
                                   covers, now, ttl, ISC_FALSE,
-                                  ardataset, &eresult);
+                                  ISC_FALSE, ardataset, &eresult);
        if (result != ISC_R_SUCCESS)
                goto unlock;
 
index b76dae6f467423cd1bf1e1efc739a985179dd0a6..3cf2a28cbd2017a1a06b8b96753a91b42821c364 100644 (file)
@@ -195,6 +195,7 @@ marksecure(dns_validatorevent_t *event) {
        dns_rdataset_settrust(event->rdataset, dns_trust_secure);
        if (event->sigrdataset != NULL)
                dns_rdataset_settrust(event->sigrdataset, dns_trust_secure);
+       event->secure = ISC_TRUE;
 }
 
 static void
@@ -2852,6 +2853,8 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
                              "nonexistence proof(s) found");
                if (val->event->message == NULL)
                        marksecure(val->event);
+               else
+                       val->event->secure = ISC_TRUE;
                return (ISC_R_SUCCESS);
        }
 
@@ -3739,6 +3742,7 @@ dns_validator_create(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
        event->message = message;
        memset(event->proofs, 0, sizeof(event->proofs));
        event->optout = ISC_FALSE;
+       event->secure = ISC_FALSE;
        result = isc_mutex_init(&val->lock);
        if (result != ISC_R_SUCCESS)
                goto cleanup_event;