]> 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:17:59 +0000 (22:17 +1100)
committerMark Andrews <marka@isc.org>
Thu, 10 Jan 2013 11:17:59 +0000 (22:17 +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 0c609cb12a4a2acaeed689ce886be0732d95055b..e82c18a4102556c9dfe98879981fd47aad672108 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+3461.  [bug]           Negative responses could incorrectly have AD=1
+                       set. [RT #32237]
+
 3458.  [bug]           Return FORMERR when presented with a overly long
                        domain named in a request. [RT #29682]
 
index 71bf1df929aa97e42741e605023a5e8b124949b1..c72fb2e330ed4380d0bb0b1e1e2d63dbf37b6c25 100644 (file)
@@ -155,6 +155,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 2af90b8fc8a9164acd97a1b954f08ff107bfc150..3701b4d55e718e4fc0868cafe1e86a793de26411 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 7806944d7ca7c1c702a7abafaac9a3ede1287daa..409a35ee8f3ef1ecbd24a3a304034cdc7e7b6e83 100644 (file)
@@ -6137,7 +6137,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 9c30ec531831d317b07ff8ec42ab0f6a55ecf70f..e5cf8930980ca6eba0db13d95cc097e8acae6dca 100644 (file)
@@ -58,4 +58,7 @@ rm -f ns3/ttlpatch.example.db ns3/ttlpatch.example.db.signed
 rm -f ns3/ttlpatch.example.db.patched
 rm -f ns3/lower.example.db ns3/upper.example.db ns3/upper.example.db.lower
 rm -f ns3/expiring.example.db
-
+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 aa2ddc28ea9ce7adc9fe62c2f700995d1274fdbe..e7eb7ff247b8229c91d89847af1cd45d77a431e0 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 0fbcd79ecc0d49ba5dfd4ea5aeba95f6f2eb1b40..f50a3f4027180e2a6fc93687f4e73314870093e9 100644 (file)
@@ -1623,5 +1623,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 5e1d5d7d6f1759c9d5a355941f56867876e0cf0a..65969f0948141996c763aefe2f24ba09c21f0bb3 100644 (file)
@@ -312,7 +312,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 8cc552d1e7f38dd8133f62bedffa83af0fa997a1..6e05326f5e48af020d705e8d63d6c70c49e6f803 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);
@@ -4233,7 +4234,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;
@@ -4975,8 +4976,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;
@@ -4985,8 +4986,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
@@ -5153,7 +5158,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 1035699f29635f738b9837bb04991f7ebe9d7a64..26ed736f1db51ba4e48b0ca475ae7969a1605a17 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
@@ -2849,6 +2850,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);
        }
 
@@ -3736,6 +3739,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;