From: Wouter Wijngaards Date: Mon, 22 Jan 2018 14:30:16 +0000 (+0000) Subject: - Fix #3397: Fix that when the cache contains an unsigned DNAME in X-Git-Tag: release-1.7.0rc1~115 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=859ca7db68014a2557c50fc1f2925962424e126c;p=thirdparty%2Funbound.git - Fix #3397: Fix that when the cache contains an unsigned DNAME in the middle of a cname chain, a result without the DNAME could be returned. git-svn-id: file:///svn/unbound/trunk@4446 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index c867efde0..e02ac95a5 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -4,6 +4,9 @@ tls-service-key, tls-service-pem, stub-tls-upstream and forward-tls-upstream. - Fix #3397: Fix that cachedb could return a partial CNAME chain. + - Fix #3397: Fix that when the cache contains an unsigned DNAME in + the middle of a cname chain, a result without the DNAME could + be returned. 19 January 2018: Wouter - tag 1.6.8 for release with CVE fix. diff --git a/services/cache/dns.c b/services/cache/dns.c index ddea47aa6..b725d8a34 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -568,7 +568,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region, /** synthesize DNAME+CNAME response from cached DNAME item */ static struct dns_msg* synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, - time_t now, struct query_info* q) + time_t now, struct query_info* q, struct module_env* env) { struct dns_msg* msg; struct ub_packed_rrset_key* ck; @@ -580,8 +580,19 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, return NULL; /* only allow validated (with DNSSEC) DNAMEs used from cache * for insecure DNAMEs, query again. */ - if(d->security != sec_status_secure) - return NULL; + if(d->security != sec_status_secure) { + /* but if we have a CNAME cached with this name, then we + * have previously already allowed this name to pass. + * the next cache lookup is going to fetch that CNAME itself, + * but it is better to have the (unsigned)DNAME + CNAME in + * that case */ + struct ub_packed_rrset_key* cname_rrset = rrset_cache_lookup( + env->rrset_cache, q->qname, q->qname_len, + LDNS_RR_TYPE_CNAME, q->qclass, 0, now, 0); + if(!cname_rrset) + return NULL; + lock_rw_unlock(&cname_rrset->entry.lock); + } msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */ if(!msg) return NULL; @@ -748,7 +759,8 @@ dns_cache_lookup(struct module_env* env, (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now, LDNS_RR_TYPE_DNAME, 1))) { /* synthesize a DNAME+CNAME message based on this */ - struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k); + struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k, + env); if(msg) { lock_rw_unlock(&rrset->entry.lock); return msg;