]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
extremely lenient for truncated positive replies
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Jun 2009 10:59:59 +0000 (10:59 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Jun 2009 10:59:59 +0000 (10:59 +0000)
git-svn-id: file:///svn/unbound/trunk@1670 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
testdata/val_pos_truncns.rpl [new file with mode: 0644]
validator/validator.c

index dddf7b481efae45da94d815f95ad2578a570874f..ce478670aac516dc68160f244191615397bebe13 100644 (file)
@@ -2,6 +2,9 @@
        - Fix of message parse bug where (specifically) an NSEC and RRSIG
          in the wrong order would be parsed, but put wrongly into internal
          structures so that later validation would fail.
+       - Extreme lenience for wrongly truncated replies where a positive
+         reply has an NS in the authority but no signatures.  They are
+         turned into minimal responses with only the (secure) answer.
 
 17 June 2009: Wouter
        - CREDITS entry for cz.nic, sponsoring a 'summer of code' that was
diff --git a/testdata/val_pos_truncns.rpl b/testdata/val_pos_truncns.rpl
new file mode 100644 (file)
index 0000000..63b7fd0
--- /dev/null
@@ -0,0 +1,148 @@
+; config options
+; The island of trust is at example.com
+server:
+       trust-anchor: "example.com.    3600    IN      DS      2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+       val-override-date: "20070916134226"
+       target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with badly truncated positive response
+
+; 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.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.         IN      A       1.2.3.4
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com.    3600    IN      DNSKEY  256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com.    3600    IN      RRSIG   DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com.                IN      A       1.2.3.4
+ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+www.example.com.        3600    IN      RRSIG   A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.com.
+
+; Truncated, no signature for NS record.
+;;;example.com.    3600    IN      RRSIG   NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+;;;SECTION ADDITIONAL
+;;;ns.example.com.             IN      A       1.2.3.4
+;;;ns.example.com. 3600    IN      RRSIG   A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+www.example.com.        3600    IN      RRSIG   A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
index f613f7775433d228d2ab5bcd3675f86ba9475a47..098cd3a6701098cb27a028c794ac10af1757dc46 100644 (file)
@@ -478,6 +478,36 @@ validate_msg_signatures(struct module_env* env, struct val_env* ve,
        return 1;
 }
 
+/**
+ * Detect wrong truncated response, by a bad recursor out there.
+ * The positive response has a mangled authority section.
+ * Remove that authority section.
+ * @param rep: reply
+ * @return true if a wrongly truncated response.
+ */
+static int
+detect_wrongly_truncated(struct reply_info* rep)
+{
+       size_t i;
+       /* no additional, only NS in authority, and it is bogus */
+       if(rep->ar_numrrsets != 0 || rep->ns_numrrsets != 1 ||
+               rep->an_numrrsets == 0)
+               return 0;
+       if(ntohs(rep->rrsets[ rep->an_numrrsets ]->rk.type) != LDNS_RR_TYPE_NS)
+               return 0;
+       if(((struct packed_rrset_data*)rep->rrsets[ rep->an_numrrsets ]
+               ->entry.data)->security != sec_status_bogus)
+               return 0;
+       /* answer section is present and secure */
+       for(i=0; i<rep->an_numrrsets; i++) {
+               if(((struct packed_rrset_data*)rep->rrsets[ i ]
+                       ->entry.data)->security != sec_status_secure)
+                       return 0;
+       }
+       return 1;
+}
+
+
 /**
  * Given a "positive" response -- a response that contains an answer to the
  * question, and no CNAME chain, validate this response. 
@@ -1449,17 +1479,31 @@ processValidate(struct module_qstate* qstate, struct val_qstate* vq,
                vq->chase_reply->security = sec_status_bogus;
                return 1;
        }
+       subtype = val_classify_response(qstate->query_flags, &qstate->qinfo,
+               &vq->qchase, vq->orig_msg->rep, vq->rrset_skip);
 
        /* check signatures in the message; 
         * answer and authority must be valid, additional is only checked. */
        if(!validate_msg_signatures(qstate->env, ve, &vq->qchase, 
                vq->chase_reply, vq->key_entry)) {
-               verbose(VERB_DETAIL, "Validate: message contains bad rrsets");
-               return 1;
+               /* workaround bad recursor out there that truncates (even
+                * with EDNS4k) to 512 by removing RRSIG from auth section
+                * for positive replies*/
+               if(subtype == VAL_CLASS_POSITIVE &&
+                       detect_wrongly_truncated(vq->orig_msg->rep)) {
+                       /* truncate the message some more */
+                       vq->orig_msg->rep->ns_numrrsets = 0;
+                       vq->orig_msg->rep->rrset_count--;
+                       vq->chase_reply->ns_numrrsets = 0;
+                       vq->chase_reply->rrset_count--;
+               }
+               else {
+                       verbose(VERB_DETAIL, "Validate: message contains "
+                               "bad rrsets");
+                       return 1;
+               }
        }
 
-       subtype = val_classify_response(qstate->query_flags, &qstate->qinfo,
-               &vq->qchase, vq->orig_msg->rep, vq->rrset_skip);
        switch(subtype) {
                case VAL_CLASS_POSITIVE:
                        verbose(VERB_ALGO, "Validating a positive response");