--- contrib/unbound/iterator/iter_scrub.c.orig +++ contrib/unbound/iterator/iter_scrub.c @@ -418,12 +418,13 @@ * @param qinfo: original query. * @param region: where to allocate synthesized CNAMEs. * @param env: module env with config options. + * @param zonename: name of server zone. * @return 0 on error. */ static int scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg, struct query_info* qinfo, struct regional* region, - struct module_env* env) + struct module_env* env, uint8_t* zonename) { uint8_t* sname = qinfo->qname; size_t snamelen = qinfo->qname_len; @@ -431,7 +432,8 @@ int cname_length = 0; /* number of CNAMEs, or DNAMEs */ if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR && - FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN) + FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN && + FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_YXDOMAIN) return 1; /* For the ANSWER section, remove all "irrelevant" records and add @@ -470,6 +472,11 @@ &aliaslen, pkt)) { verbose(VERB_ALGO, "synthesized CNAME " "too long"); + if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) { + prev = rrset; + rrset = rrset->rrset_all_next; + continue; + } return 0; } cname_length++; @@ -650,6 +657,29 @@ "RRset:", pkt, msg, prev, &rrset); continue; } + /* Also delete promiscuous NS for other RCODEs */ + if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR + && env->cfg->iter_scrub_promiscuous) { + remove_rrset("normalize: removing promiscuous " + "RRset:", pkt, msg, prev, &rrset); + continue; + } + /* Also delete promiscuous NS for NOERROR with nodata + * for authoritative answers, not for delegations. + * NOERROR with an_rrsets!=0 already handled. + * Also NOERROR and soa_in_auth already handled. + * NOERROR with an_rrsets==0, and not a referral. + * referral is (NS not the zonename, noSOA). + */ + if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR + && msg->an_rrsets == 0 + && !(dname_pkt_compare(pkt, rrset->dname, + zonename) != 0 && !soa_in_auth(msg)) + && env->cfg->iter_scrub_promiscuous) { + remove_rrset("normalize: removing promiscuous " + "RRset:", pkt, msg, prev, &rrset); + continue; + } if(nsset == NULL) { nsset = rrset; } else { @@ -1060,7 +1090,8 @@ /* this is not required for basic operation but is a forgery * resistance (security) feature */ if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR || - FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) && + FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN || + FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) && msg->qdcount == 0) return 0; @@ -1074,7 +1105,7 @@ } /* normalize the response, this cleans up the additional. */ - if(!scrub_normalize(pkt, msg, qinfo, region, env)) + if(!scrub_normalize(pkt, msg, qinfo, region, env, zonename)) return 0; /* delete all out-of-zone information */ if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))