]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix for mixed class referrals, the resolver uses the query
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 18 May 2026 14:42:39 +0000 (16:42 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 18 May 2026 14:42:39 +0000 (16:42 +0200)
  class. Thanks to Xin Wang and Jiajia Liu, Northwestern
  Polytechnical University, for the report.

doc/Changelog
iterator/iter_delegpt.c
iterator/iter_scrub.c
testdata/iter_class_mixreferral.rpl [new file with mode: 0644]

index 42a2192ac275b5e7111235dcc2cbc4907d8bcbd6..a51918e28009e5aa75346dfdd13abcc4be96ba05 100644 (file)
@@ -1,3 +1,8 @@
+18 May 2026: Wouter
+       - Fix for mixed class referrals, the resolver uses the query
+         class. Thanks to Xin Wang and Jiajia Liu, Northwestern
+         Polytechnical University, for the report.
+
 15 May 2026: Wouter
        - Fix man page entry for so-sndbuf, it is for responses sent out.
        - Fix val_find_DS for robustness, to check the result of
index be5bf482d67339c01fef65965451cf2f0b24def9..5b609c960dd28d3423e6102a1f08ec80a055774c 100644 (file)
@@ -398,11 +398,12 @@ delegpt_count_missing_targets(struct delegpt* dp, int* alllame)
 
 /** find NS rrset in given list */
 static struct ub_packed_rrset_key*
-find_NS(struct reply_info* rep, size_t from, size_t to)
+find_NS(struct reply_info* rep, size_t from, size_t to, uint16_t qclass)
 {
        size_t i;
        for(i=from; i<to; i++) {
-               if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
+               if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS &&
+                       ntohs(rep->rrsets[i]->rk.rrset_class) == qclass)
                        return rep->rrsets[i];
        }
        return NULL;
@@ -416,12 +417,14 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
        size_t i;
        /* look for NS records in the authority section... */
        ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets, 
-               msg->rep->an_numrrsets+msg->rep->ns_numrrsets);
+               msg->rep->an_numrrsets+msg->rep->ns_numrrsets,
+               msg->qinfo.qclass);
 
        /* In some cases (even legitimate, perfectly legal cases), the 
         * NS set for the "referral" might be in the answer section. */
        if(!ns_rrset)
-               ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets);
+               ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets,
+                       msg->qinfo.qclass);
        
        /* If there was no NS rrset in the authority section, then this 
         * wasn't a referral message. (It might not actually be a 
@@ -447,10 +450,12 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
                        i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets))
                        continue;
 
-               if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
+               if(ntohs(s->rk.type) == LDNS_RR_TYPE_A &&
+                       ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
                        if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))
                                return NULL;
-               } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
+               } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA &&
+                       ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
                        if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))
                                return NULL;
                }
index 37c4150cd2ddf82b833c8e27068ca0583bd8b11c..8870fb1dd12655146037df5add0ee9210e3f2756 100644 (file)
@@ -732,6 +732,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
                                        "RRset:", pkt, msg, prev, &rrset);
                                continue;
                        }
+                       if(ntohs(rrset->rrset_class) != qinfo->qclass) {
+                               remove_rrset("normalize: removing other class "
+                                       "RRset:", pkt, msg, prev, &rrset);
+                               continue;
+                       }
                        if(nsset == NULL) {
                                nsset = rrset;
                        } else {
diff --git a/testdata/iter_class_mixreferral.rpl b/testdata/iter_class_mixreferral.rpl
new file mode 100644 (file)
index 0000000..2438825
--- /dev/null
@@ -0,0 +1,144 @@
+; config options
+server:
+       target-fetch-policy: "0 0 0 0 0"
+       qname-minimisation: "no"
+       minimal-responses: no
+       iter-scrub-promiscuous: no
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test referral with mixed class items
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 193.0.14.129 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS        K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+; mixed class contents
+example.com.   CH NS   ch.example.com.
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ch.example.com. CH A 1.2.3.5
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+ENTRY_END
+RANGE_END
+
+; ch.example.com.
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com.   IN NS   ch.example.com.
+SECTION ADDITIONAL
+ch.example.com.                IN      A       1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.42
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+ENTRY_END
+
+SCENARIO_END