]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix to scrub resource records of type A and AAAA that have an
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 7 Sep 2023 09:08:04 +0000 (11:08 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Thu, 7 Sep 2023 09:08:04 +0000 (11:08 +0200)
  inappropriate size. They are removed from responses.

doc/Changelog
iterator/iter_priv.c
iterator/iter_priv.h
iterator/iter_scrub.c
testdata/dns64_lookup.rpl
testdata/iter_scrub_rr_length.rpl [new file with mode: 0644]

index bc6c143219f1e2f98ef6a37a9564e2df52c60751..fe03f43785921a54e59472e5ca302a662fc7db77 100644 (file)
@@ -1,3 +1,7 @@
+7 September 2023: Wouter
+       - Fix to scrub resource records of type A and AAAA that have an
+         inappropriate size. They are removed from responses.
+
 6 September 2023: Wouter
        - Merge #931: Prevent warnings from -Wmissing-prototypes.
 
index 90bea1746d9aa6f52ee579192170ea8af9dd1bb2..675c9390790b0a532eac02750b28435e379cf847 100644 (file)
@@ -208,14 +208,17 @@ size_t priv_get_mem(struct iter_priv* priv)
 }
 
 /** remove RR from msgparse RRset, return true if rrset is entirely bad */
-static int
-remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset,
+int
+msgparse_rrset_remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset,
        struct rr_parse* prev, struct rr_parse** rr, struct sockaddr_storage* addr, socklen_t addrlen)
 {
        if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) {
                uint8_t buf[LDNS_MAX_DOMAINLEN+1];
                dname_pkt_copy(pkt, buf, rrset->dname);
-               log_name_addr(VERB_QUERY, str, buf, addr, addrlen);
+               if(addr)
+                       log_name_addr(VERB_QUERY, str, buf, addr, addrlen);
+               else    log_nametypeclass(VERB_QUERY, str, buf,
+                               rrset->type, ntohs(rrset->rrset_class));
        }
        if(prev)
                prev->next = (*rr)->next;
@@ -261,7 +264,7 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
                                        INET_SIZE);
                                memmove(&addr, &sa, len);
                                if(priv_lookup_addr(priv, &addr, len)) {
-                                       if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
+                                       if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
                                                return 1;
                                        continue;
                                }
@@ -284,7 +287,7 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
                                        INET6_SIZE);
                                memmove(&addr, &sa, len);
                                if(priv_lookup_addr(priv, &addr, len)) {
-                                       if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
+                                       if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
                                                return 1;
                                        continue;
                                }
index 0430d57e3e3bffe2fd664956fef2a65845ca21ea..7f58ec2f70089216b21b2adc01f530d9332ed257 100644 (file)
@@ -48,6 +48,8 @@ struct iter_env;
 struct config_file;
 struct regional;
 struct rrset_parse;
+struct rr_parse;
+struct rrset_parse;
 
 /**
  * Iterator priv structure
@@ -109,4 +111,9 @@ int priv_rrset_bad(struct iter_priv* priv, struct sldns_buffer* pkt,
  */
 size_t priv_get_mem(struct iter_priv* priv);
 
+/** remove RR from msgparse RRset, return true if rrset is entirely bad */
+int msgparse_rrset_remove_rr(const char* str, struct sldns_buffer* pkt,
+       struct rrset_parse* rrset, struct rr_parse* prev, struct rr_parse** rr,
+       struct sockaddr_storage* addr, socklen_t addrlen);
+
 #endif /* ITERATOR_ITER_PRIV_H */
index d1fedcd0f908e61be72ec51c1ac0064448121d79..c34ccfd3cb95bbbe00ca1b892d34469b9f64b920 100644 (file)
@@ -716,6 +716,45 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
        return 0;
 }
 
+/** Remove individual RRs, if the length is wrong. Returns true if the RRset
+ * has been removed. */
+static int
+scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
+       struct rrset_parse* prev, struct rrset_parse** rrset)
+{
+       struct rr_parse* rr, *rr_prev = NULL;
+       for(rr = (*rrset)->rr_first; rr; rr = rr->next) {
+
+               /* Sanity check for length of records
+                * An A record should be 6 bytes only
+                * (2 bytes for length and 4 for IPv4 addr)*/
+               if((*rrset)->type == LDNS_RR_TYPE_A && rr->size != 6 ) {
+                       if(msgparse_rrset_remove_rr("sanitize: removing type A RR of inappropriate length:",
+                               pkt, *rrset, rr_prev, &rr, NULL, 0)) {
+                               remove_rrset("sanitize: removing type A RRset of inappropriate length:",
+                                       pkt, msg, prev, rrset);
+                               return 1;
+                       }
+                       continue;
+               }
+
+               /* Sanity check for length of records
+                * An AAAA record should be 18 bytes only
+                * (2 bytes for length and 16 for IPv6 addr)*/
+               if((*rrset)->type == LDNS_RR_TYPE_AAAA && rr->size != 18 ) {
+                       if(msgparse_rrset_remove_rr("sanitize: removing type AAAA RR of inappropriate length:",
+                               pkt, *rrset, rr_prev, &rr, NULL, 0)) {
+                               remove_rrset("sanitize: removing type AAAA RRset of inappropriate length:",
+                                       pkt, msg, prev, rrset);
+                               return 1;
+                       }
+                       continue;
+               }
+               rr_prev = rr;
+       }
+       return 0;
+}
+
 /**
  * Given a response event, remove suspect RRsets from the response.
  * "Suspect" rrsets are potentially poison. Note that this routine expects
@@ -781,6 +820,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
        rrset = msg->rrset_first;
        while(rrset) {
 
+               /* Sanity check for length of records */
+               if(rrset->type == LDNS_RR_TYPE_A ||
+                       rrset->type == LDNS_RR_TYPE_AAAA) {
+                       if(scrub_sanitize_rr_length(pkt, msg, prev, &rrset))
+                               continue;
+               }
+
                /* remove private addresses */
                if( (rrset->type == LDNS_RR_TYPE_A || 
                        rrset->type == LDNS_RR_TYPE_AAAA)) {
index 898d0d01ad167e4a50598fffddd287ccc7fba699..7986fc8fce80712c3e610bf249a6db16884ad428 100644 (file)
@@ -140,33 +140,6 @@ SECTION ADDITIONAL
 ns.example.com.                IN      A       1.2.3.4
 ENTRY_END
 
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-broken.example.com. IN AAAA
-SECTION ANSWER
-; NO AAAA present
-SECTION AUTHORITY
-example.com.   IN SOA  a. b. 1 2 3 4 5
-ENTRY_END
-
-ENTRY_BEGIN
-MATCH opcode qtype qname
-ADJUST copy_id
-REPLY QR NOERROR
-SECTION QUESTION
-broken.example.com. IN A
-SECTION ANSWER
-broken.example.com. IN A       5.6.7.8
-broken.example.com. IN A \# 3 030405
-SECTION AUTHORITY
-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
@@ -284,25 +257,4 @@ SECTION AUTHORITY
 7.6.5.in-addr.arpa. IN NS ns.example.com.
 ENTRY_END
 
-; synthesize from broken, malformed A records 
-STEP 80 QUERY
-ENTRY_BEGIN
-REPLY RD
-SECTION QUESTION
-broken.example.com. IN AAAA
-ENTRY_END
-
-; recursion happens here.
-STEP 90 CHECK_ANSWER
-ENTRY_BEGIN
-MATCH all
-REPLY QR RD RA NOERROR
-SECTION QUESTION
-broken.example.com. IN AAAA
-SECTION ANSWER
-SECTION AUTHORITY
-example.com.   IN SOA  a. b. 1 2 3 4 5
-SECTION ADDITIONAL
-ENTRY_END
-
 SCENARIO_END
diff --git a/testdata/iter_scrub_rr_length.rpl b/testdata/iter_scrub_rr_length.rpl
new file mode 100644 (file)
index 0000000..ccb791e
--- /dev/null
@@ -0,0 +1,273 @@
+; config options
+server:
+       target-fetch-policy: "0 0 0 0 0"
+       qname-minimisation: "no"
+       minimal-responses: no
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test scrub of RRs of inappropriate length
+
+; 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 qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+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
+www.example.com. IN A \# 3 030405
+SECTION AUTHORITY
+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 AAAA
+SECTION ANSWER
+www.example.com. IN AAAA       2001:db8::1234
+www.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F
+SECTION AUTHORITY
+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
+broken1.example.com. IN A
+SECTION ANSWER
+broken1.example.com. IN A \# 3 030405
+broken1.example.com. IN A \# 3 030406
+SECTION AUTHORITY
+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
+broken1.example.com. IN AAAA
+SECTION ANSWER
+broken1.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F
+broken1.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E30
+broken1.example.com. IN AAAA \# 48 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E31
+SECTION AUTHORITY
+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
+broken2.example.com. IN A
+SECTION ANSWER
+broken2.example.com. IN A 1.2.3.4
+broken2.example.com. IN A \# 3 030405
+broken2.example.com. IN A 1.2.3.5
+broken2.example.com. IN A \# 3 030406
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A \# 3 030407
+ns.example.com.                IN      A       1.2.3.6
+ns.example.com. IN A \# 3 030408
+ns.example.com. IN A \# 3 030409
+ns.example.com.                IN      A       1.2.3.7
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+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
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN AAAA
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN AAAA
+SECTION ANSWER
+www.example.com. IN AAAA       2001:db8::1234
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+broken1.example.com. IN A
+ENTRY_END
+
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+broken1.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+
+STEP 60 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+broken1.example.com. IN AAAA
+ENTRY_END
+
+STEP 70 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+broken1.example.com. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ENTRY_END
+
+STEP 80 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+broken2.example.com. IN A
+ENTRY_END
+
+STEP 90 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+broken2.example.com. IN A
+SECTION ANSWER
+broken2.example.com. IN A 1.2.3.4
+broken2.example.com. IN A 1.2.3.5
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.6
+ns.example.com.                IN      A       1.2.3.7
+ENTRY_END
+
+SCENARIO_END