diff --git a/doc/Changelog b/doc/Changelog index 2ac0dda41..c10fd0f15 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,9 @@ +17 March 2016: Wouter + - Fix #746: Fix unbound sets CD bit on all forwards. + If no trust anchors, it'll not set CD bit when forwarding to another + server. If a trust anchor, no CD bit on the first attempt to a + forwarder, but CD bit thereafter on repeated attempts to get DNSSEC. + 16 March 2016: Wouter - Fix ip-transparent for ipv6 on FreeBSD, thanks to Nick Hibma. - Fix ip-transparent for tcp on freebsd. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index 58e62fbeb..a5aefa960 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -590,6 +590,27 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, return 1; } +int +iter_indicates_dnssec_fwd(struct module_env* env, struct query_info *qinfo) +{ + struct trust_anchor* a; + if(!env || !env->anchors || !qinfo || !qinfo->qname) + return 0; + /* a trust anchor exists above the name? */ + if((a=anchors_lookup(env->anchors, qinfo->qname, qinfo->qname_len, + qinfo->qclass))) { + if(a->numDS == 0 && a->numDNSKEY == 0) { + /* insecure trust point */ + lock_basic_unlock(&a->lock); + return 0; + } + lock_basic_unlock(&a->lock); + return 1; + } + /* no trust anchor above it. */ + return 0; +} + int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, struct dns_msg* msg, uint16_t dclass) diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 3a4df3e45..50c5fc093 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -173,6 +173,18 @@ void iter_mark_pside_cycle_targets(struct module_qstate* qstate, int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, struct delegpt* dp); +/** + * See if qname has DNSSEC needs in the forwarding case. This is true if + * there is a trust anchor above it. Whether there is an insecure delegation + * to the data is unknown, but CD-retry is needed. + * @param env: environment with anchors. + * @param qinfo: query name and class. + * @return true if trust anchor above qname, false if no anchor or insecure + * point above qname. + */ +int iter_indicates_dnssec_fwd(struct module_env* env, + struct query_info *qinfo); + /** * See if delegation is expected to have DNSSEC information (RRSIGs) in * its answers, or not. Inspects delegation point (name), trust anchors, diff --git a/iterator/iterator.c b/iterator/iterator.c index b1bf902d5..ccc5d3408 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -2090,7 +2090,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, outq = (*qstate->env->send_query)( iq->qinfo_out.qname, iq->qinfo_out.qname_len, iq->qinfo_out.qtype, iq->qinfo_out.qclass, - iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), EDNS_DO|BIT_CD, + iq->chase_flags | (iq->chase_to_rd?BIT_RD:0), + /* unset CD if to forwarder(RD set) and not dnssec retry + * (blacklist nonempty) and no trust-anchors are configured + * above the qname or on the first attempt when dnssec is on */ + EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&& + !qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env, + &iq->qinfo_out)||target->attempts==1)?0:BIT_CD), iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( ie, iq), &target->addr, target->addrlen, iq->dp->name, iq->dp->namelen, qstate);