From: Wouter Wijngaards Date: Wed, 17 Feb 2010 16:50:04 +0000 (+0000) Subject: Scrub DNSKEY, DLV and DS much more stringently. X-Git-Tag: release-1.4.2~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=36ccd87840528c88d1655fee1dd7531a328e16b2;p=thirdparty%2Funbound.git Scrub DNSKEY, DLV and DS much more stringently. git-svn-id: file:///svn/unbound/trunk@1985 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 0d7e1bfd0..5e6632055 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,8 @@ +17 February 2010: Wouter + - Disregard DNSKEY from authority section for chain of trust. + DS records that are irrelevant to a referral scrubbed. Anti-poison. + - iana portlist updated. + 16 February 2010: Wouter - Check for 'no space left on device' (or other errors) when writing updated autotrust anchors and print errno to log. diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index b5364b615..2416f3abb 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -755,3 +755,30 @@ iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, else *c = c2; return 1; } + +void +iter_scrub_ds(struct ub_packed_rrset_key* ns, struct dns_msg* msg) +{ + /* Only the DS record for the delegation itself is expected. + * We allow DS for everything between the bailiwick and the + * zonecut, thus DS records must be at or above the zonecut. + * The answer section is already scrubbed. */ + size_t i = msg->rep->an_numrrsets; + while(i < (msg->rep->an_numrrsets + msg->rep->ns_numrrsets)) { + struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; + if(ntohs(s->rk.type) == LDNS_RR_TYPE_DS && + !dname_subdomain_c(ns->rk.dname, s->rk.dname)) { + log_nametypeclass(VERB_ALGO, "removing irrelevant DS " + "from referral", s->rk.dname, + ntohs(s->rk.type), ntohs(s->rk.rrset_class)); + memmove(msg->rep->rrsets+i, msg->rep->rrsets+i+1, + sizeof(struct ub_packed_rrset_key*) * + (msg->rep->rrset_count-i-1)); + msg->rep->ns_numrrsets--; + msg->rep->rrset_count--; + /* stay at same i, but new record */ + continue; + } + i++; + } +} diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 747b9a643..85d9c1a21 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -57,6 +57,7 @@ struct query_info; struct reply_info; struct module_qstate; struct sock_list; +struct ub_packed_rrset_key; /** * Process config options and set iterator module state. @@ -245,4 +246,11 @@ int iter_lookup_inzone_glue(struct module_env* env, struct delegpt* dp, int iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, uint16_t* c); +/** + * Remove DS records that are inappropriate before they are cached. + * @param ns: RRSET that is the NS record for the referral. + * @param msg: the response to scrub. + */ +void iter_scrub_ds(struct ub_packed_rrset_key* ns, struct dns_msg* msg); + #endif /* ITERATOR_ITER_UTILS_H */ diff --git a/iterator/iterator.c b/iterator/iterator.c index 43621bd8a..cc66c4895 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -1612,7 +1612,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, || !dname_subdomain_c(iq->qchase.qname, ns->rk.dname)){ verbose(VERB_ALGO, "bad referral, throwaway"); type = RESPONSE_TYPE_THROWAWAY; - } + } else + iter_scrub_ds(ns, iq->response); } /* handle each of the type cases */ @@ -1650,11 +1651,11 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, * see if that equals the query name... */ && ( /* auth section, but sometimes in answer section*/ reply_find_rrset_section_ns(iq->response->rep, - qstate->qinfo.qname, qstate->qinfo.qname_len, - LDNS_RR_TYPE_NS, qstate->qinfo.qclass) + iq->qchase.qname, iq->qchase.qname_len, + LDNS_RR_TYPE_NS, iq->qchase.qclass) || reply_find_rrset_section_an(iq->response->rep, - qstate->qinfo.qname, qstate->qinfo.qname_len, - LDNS_RR_TYPE_NS, qstate->qinfo.qclass) + iq->qchase.qname, iq->qchase.qname_len, + LDNS_RR_TYPE_NS, iq->qchase.qclass) ) )) { /* Store the referral under the current query */ diff --git a/services/cache/dns.c b/services/cache/dns.c index 25ca76813..057fa3e76 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -698,7 +698,10 @@ dns_cache_lookup(struct module_env* env, struct packed_rrset_data *d = (struct packed_rrset_data*) rrset->entry.data; if(d->trust != rrset_trust_add_noAA && - d->trust != rrset_trust_add_AA) { + d->trust != rrset_trust_add_AA && + (qtype == LDNS_RR_TYPE_DS || + (d->trust != rrset_trust_auth_noAA + && d->trust != rrset_trust_auth_AA) )) { struct dns_msg* msg = rrset_msg(rrset, region, now, &k); if(msg) { lock_rw_unlock(&rrset->entry.lock); diff --git a/util/iana_ports.inc b/util/iana_ports.inc index 84b89b7a9..d770618ed 100644 --- a/util/iana_ports.inc +++ b/util/iana_ports.inc @@ -4502,6 +4502,7 @@ 7025, 7030, 7070, +7071, 7080, 7099, 7100,