* @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;
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
&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++;
"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 {
/* 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;
}
/* 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))
; The spoofed contents are ns.attacker.mesa and its IPs 5.6.7.8 and 5.6.7.9.
; The pollute1.mesa NS, ns.pollute2.mesa A, and test3.atkr.pollute3.mesa NS
; with ns.pollute3.mesa A records are tested for cache placement.
+; pollute4.mesa uses YXDOMAIN.
; ns.root
RANGE_BEGIN 0 400
ns.pollute3.mesa. IN A 1.2.4.3
ENTRY_END
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+pollute4.mesa. IN NS
+SECTION AUTHORITY
+pollute4.mesa. IN NS ns.pollute4.mesa.
+SECTION ADDITIONAL
+ns.pollute4.mesa. IN A 1.2.4.4
+ENTRY_END
+
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
ENTRY_END
RANGE_END
+; ns.pollute4.mesa
+RANGE_BEGIN 0 400
+ ADDRESS 1.2.4.4
+
+; This is the spoofed answer that is returned.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA YXDOMAIN
+SECTION QUESTION
+test4.atkr.pollute4.mesa. IN A
+SECTION ANSWER
+test4.atkr.pollute4.mesa. 86400 IN A 1.2.3.4
+SECTION AUTHORITY
+pollute4.mesa. 86400 IN NS ns.attacker.mesa.
+ENTRY_END
+
+; correct answer for the check query.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+check.pollute4.mesa. IN A
+SECTION ANSWER
+check.pollute4.mesa. IN A 1.8.9.4
+ENTRY_END
+RANGE_END
+
; ns.attacker.mesa
RANGE_BEGIN 0 400
ADDRESS 5.6.7.8
;check.pollute3.mesa. IN A 5.6.7.9
ENTRY_END
+; Test query 4
+STEP 120 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+test4.atkr.pollute4.mesa. IN A
+ENTRY_END
+
+STEP 130 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA YXDOMAIN
+SECTION QUESTION
+test4.atkr.pollute4.mesa. IN A
+SECTION ANSWER
+test4.atkr.pollute4.mesa. 86400 IN A 1.2.3.4
+SECTION AUTHORITY
+; removed record
+;pollute4.mesa. 0 IN NS ns.attacker.mesa.
+ENTRY_END
+
+; Check the cache contents, for query 4.
+STEP 140 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+check.pollute4.mesa. IN A
+ENTRY_END
+
+STEP 150 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+check.pollute4.mesa. IN A
+SECTION ANSWER
+; good answer
+check.pollute4.mesa. IN A 1.8.9.4
+; bad answer
+;check.pollute4.mesa. IN A 5.6.7.9
+ENTRY_END
+
SCENARIO_END