diff --git a/CHANGES b/CHANGES index 6cfb4bf340..1d660d50ff 100644 --- 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] 3459. [func] Added -J option to named-checkzone/named-compilezone diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 2e26a9099a..7ac6632e2a 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -159,6 +159,7 @@ EXTERN isc_boolean_t ns_g_noedns INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_nosoa INIT(ISC_FALSE); EXTERN isc_boolean_t ns_g_noaa INIT(ISC_FALSE); EXTERN unsigned int ns_g_delay INIT(0); +EXTERN isc_boolean_t ns_g_nonearest INIT(ISC_FALSE); #undef EXTERN #undef INIT diff --git a/bin/named/main.c b/bin/named/main.c index adc394799b..d43510af3e 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -537,6 +537,8 @@ parse_command_line(int argc, char *argv[]) { ns_g_delay = atoi(isc_commandline_argument + 6); 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); diff --git a/bin/named/query.c b/bin/named/query.c index 36f74810be..2f7f960056 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -6397,7 +6397,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; diff --git a/bin/tests/system/dnssec/clean.sh b/bin/tests/system/dnssec/clean.sh index 189c01188b..1648669b40 100644 --- a/bin/tests/system/dnssec/clean.sh +++ b/bin/tests/system/dnssec/clean.sh @@ -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?.* diff --git a/bin/tests/system/dnssec/ns1/root.db.in b/bin/tests/system/dnssec/ns1/root.db.in index 4ff12582bd..be8d55db3f 100644 --- a/bin/tests/system/dnssec/ns1/root.db.in +++ b/bin/tests/system/dnssec/ns1/root.db.in @@ -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 diff --git a/bin/tests/system/dnssec/ns1/sign.sh b/bin/tests/system/dnssec/ns1/sign.sh index 96fc060bd8..0b117fb2aa 100644 --- a/bin/tests/system/dnssec/ns1/sign.sh +++ b/bin/tests/system/dnssec/ns1/sign.sh @@ -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 index 0000000000..340fbaf54a --- /dev/null +++ b/bin/tests/system/dnssec/ns6/named.args @@ -0,0 +1 @@ +-m record,size,mctx -c named.conf -d 99 -g -T nonearest -T clienttest diff --git a/bin/tests/system/dnssec/ns6/named.conf b/bin/tests/system/dnssec/ns6/named.conf index eb35680ef2..54221cefbd 100644 --- a/bin/tests/system/dnssec/ns6/named.conf +++ b/bin/tests/system/dnssec/ns6/named.conf @@ -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 index 0000000000..8cdb0aab36 --- /dev/null +++ b/bin/tests/system/dnssec/ns6/optout-tld.db.in @@ -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 index 0000000000..7c1179d418 --- /dev/null +++ b/bin/tests/system/dnssec/ns6/sign.sh @@ -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 diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index a6cb09aff8..735be59451 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -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 diff --git a/lib/dns/include/dns/ncache.h b/lib/dns/include/dns/ncache.h index 8d89879cc5..5064e91171 100644 --- a/lib/dns/include/dns/ncache.h +++ b/lib/dns/include/dns/ncache.h @@ -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. * diff --git a/lib/dns/include/dns/validator.h b/lib/dns/include/dns/validator.h index 7d6ea7a89d..486510a6fd 100644 --- a/lib/dns/include/dns/validator.h +++ b/lib/dns/include/dns/validator.h @@ -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 diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index c0e99d4969..7d50abc4df 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -47,6 +47,12 @@ * */ +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) diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c index 5ae1cf8739..bbdde55daf 100644 --- a/lib/dns/nsec.c +++ b/lib/dns/nsec.c @@ -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) { diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 0b30a8cd8a..0e78eb1157 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -472,6 +472,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); @@ -4248,7 +4249,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; @@ -4990,8 +4991,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; @@ -5000,8 +5001,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 @@ -5168,7 +5173,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; diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 319fc2bab9..69cee2827b 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -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 @@ -2847,6 +2848,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); } @@ -3734,6 +3737,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;