]> git.ipfire.org Git - people/meitelwein/ipfire-2.x.git/blobdiff - src/patches/dnsmasq/021-Tweaks_to_EDNS0_handling_in_DNS_replies.patch
dnsmasq 2.75: latest upstream patches ;-)
[people/meitelwein/ipfire-2.x.git] / src / patches / dnsmasq / 021-Tweaks_to_EDNS0_handling_in_DNS_replies.patch
diff --git a/src/patches/dnsmasq/021-Tweaks_to_EDNS0_handling_in_DNS_replies.patch b/src/patches/dnsmasq/021-Tweaks_to_EDNS0_handling_in_DNS_replies.patch
new file mode 100644 (file)
index 0000000..c3c74cc
--- /dev/null
@@ -0,0 +1,133 @@
+From dd4ad9ac7ea6d51dcc34a1f2cd2da14efbb87714 Mon Sep 17 00:00:00 2001
+From: Simon Kelley <simon@thekelleys.org.uk>
+Date: Thu, 17 Dec 2015 10:44:58 +0000
+Subject: [PATCH] Tweaks to EDNS0 handling in DNS replies.
+
+---
+ src/dnssec.c  |   20 +++++++++-----------
+ src/rfc1035.c |   57 +++++++++++++++++++++++++++++++++------------------------
+ 2 files changed, 42 insertions(+), 35 deletions(-)
+
+diff --git a/src/dnssec.c b/src/dnssec.c
+index dc563e0..012b2a6 100644
+--- a/src/dnssec.c
++++ b/src/dnssec.c
+@@ -2129,18 +2129,16 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
+           /* Empty DS without NSECS */
+           if (qtype == T_DS)
+             return STAT_BOGUS;
+-          else
++          
++          rc = zone_status(name, qclass, keyname, now);
++          if (rc != STAT_SECURE)
+             {
+-              rc = zone_status(name, qclass, keyname, now);
+-              if (rc != STAT_SECURE)
+-                {
+-                  if (class)
+-                    *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */
+-                  return rc;
+-                } 
+-              
+-              return STAT_BOGUS; /* signed zone, no NSECs */
+-            }
++              if (class)
++                *class = qclass; /* Class for NEED_DS or NEED_DNSKEY */
++              return rc;
++            } 
++          
++          return STAT_BOGUS; /* signed zone, no NSECs */
+         }
+         if (nsec_type == T_NSEC)
+diff --git a/src/rfc1035.c b/src/rfc1035.c
+index def8fa0..188d05f 100644
+--- a/src/rfc1035.c
++++ b/src/rfc1035.c
+@@ -1539,7 +1539,13 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+   int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
+   struct mx_srv_record *rec;
+   size_t len;
+- 
++  
++  if (ntohs(header->ancount) != 0 ||
++      ntohs(header->nscount) != 0 ||
++      ntohs(header->qdcount) == 0 || 
++      OPCODE(header) != QUERY )
++    return 0;
++  
+   /* Don't return AD set if checking disabled. */
+   if (header->hb4 & HB4_CD)
+     sec_data = 0;
+@@ -1548,33 +1554,32 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+   *ad_reqd = header->hb4 & HB4_AD;
+   *do_bit = 0;
+-  /* If there is an RFC2671 pseudoheader then it will be overwritten by
++  /* If there is an  additional data section then it will be overwritten by
+      partial replies, so we have to do a dry run to see if we can answer
+-     the query. We check to see if the do bit is set, if so we always
+-     forward rather than answering from the cache, which doesn't include
+-     security information, unless we're in DNSSEC validation mode. */
++     the query. */
+-  if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
+-    { 
+-      unsigned short flags;
+-      
+-      have_pseudoheader = 1;
++  if (ntohs(header->arcount) != 0)
++    {
++      dryrun = 1;
+-      pheader += 4; /* udp size, ext_rcode */
+-      GETSHORT(flags, pheader);
+-      
+-      if ((sec_reqd = flags & 0x8000))
+-      {
+-        *do_bit = 1;/* do bit */ 
+-        *ad_reqd = 1;
++      /* If there's an additional section, there might be an EDNS(0) pseudoheader */
++      if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
++      { 
++        unsigned short flags;
++        
++        have_pseudoheader = 1;
++        
++        pheader += 4; /* udp size, ext_rcode */
++        GETSHORT(flags, pheader);
++        
++        if ((sec_reqd = flags & 0x8000))
++          {
++            *do_bit = 1;/* do bit */ 
++            *ad_reqd = 1;
++          }
+       }
+-
+-      dryrun = 1;
+     }
+-  if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
+-    return 0;
+-  
+   for (rec = daemon->mxnames; rec; rec = rec->next)
+     rec->offset = 0;
+   
+@@ -1730,8 +1735,12 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
+               }
+             else if ((crecp = cache_find_by_addr(NULL, &addr, now, is_arpa)))
+               {
+-                /* Don't use cache when DNSSEC data required. */
+-                if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !sec_reqd || !(crecp->flags & F_DNSSECOK))
++                /* Don't use cache when DNSSEC data required, unless we know that
++                   the zone is unsigned, which implies that we're doing
++                   validation. */
++                if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || 
++                    !sec_reqd || 
++                    (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
+                   {
+                     do 
+                       { 
+-- 
+1.7.10.4
+