]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Tweaks to EDNS0 handling in DNS replies.
authorSimon Kelley <simon@thekelleys.org.uk>
Thu, 17 Dec 2015 10:44:58 +0000 (10:44 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Thu, 17 Dec 2015 10:44:58 +0000 (10:44 +0000)
src/dnssec.c
src/rfc1035.c

index dc563e0148aac52f06bb46b31d21594d6d8c4199..012b2a663d3865c020de437e10372ad47b172316 100644 (file)
@@ -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)
index def8fa0269452beaed5f578c81b95cb8355be915..188d05f17b9983e789b8f98a09b6116c1b52b8b5 100644 (file)
@@ -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 
                        {