]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Don't mark answers as DNSEC validated if DNS-doctored.
authorSimon Kelley <simon@thekelleys.org.uk>
Sun, 26 Jan 2014 22:47:39 +0000 (22:47 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Sun, 26 Jan 2014 22:47:39 +0000 (22:47 +0000)
src/dnsmasq.h
src/forward.c
src/rfc1035.c

index 68bf9d7f6b56486f713194883df167da3eab2ae9..f8cc96919c22763bc0f10ff6d492ba9ce02d2ab9 100644 (file)
@@ -1037,7 +1037,7 @@ size_t setup_reply(struct dns_header *header, size_t  qlen,
                   unsigned long local_ttl);
 int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff, 
                      time_t now, char **ipsets, int is_sign, int checkrebind,
-                     int no_cache, int secure);
+                     int no_cache, int secure, int *doctored);
 size_t answer_request(struct dns_header *header, char *limit, size_t qlen,  
                   struct in_addr local_addr, struct in_addr local_netmask, time_t now);
 int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name, 
index bec5f9531e9821046e61d133104ef97e13256c9a..c047cb4a090dbef446ecdbf95b9f93dc089e7773 100644 (file)
@@ -556,14 +556,6 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
   if (!is_sign && !option_bool(OPT_DNSSEC_PROXY))
      header->hb4 &= ~HB4_AD;
   
-#ifdef HAVE_DNSSEC
-  if (option_bool(OPT_DNSSEC_VALID))
-    header->hb4 &= ~HB4_AD;
-  
-  if (!(header->hb4 & HB4_CD) && cache_secure)
-    header->hb4 |= HB4_AD;
-#endif
-  
   if (OPCODE(header) != QUERY || (RCODE(header) != NOERROR && RCODE(header) != NXDOMAIN))
     return n;
   
@@ -583,9 +575,12 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
       munged = 1;
       SET_RCODE(header, NXDOMAIN);
       header->hb3 &= ~HB3_AA;
+      cache_secure = 0;
     }
   else 
     {
+      int doctored = 0;
+      
       if (RCODE(header) == NXDOMAIN && 
          extract_request(header, n, daemon->namebuff, NULL) &&
          check_for_local_domain(daemon->namebuff, now))
@@ -596,13 +591,18 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
          munged = 1;
          header->hb3 |= HB3_AA;
          SET_RCODE(header, NOERROR);
+         cache_secure = 0;
        }
       
-      if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure))
+      if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
        {
          my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
          munged = 1;
+         cache_secure = 0;
        }
+
+      if (doctored)
+       cache_secure = 0;
     }
   
 #ifdef HAVE_DNSSEC
@@ -615,6 +615,12 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
          munged = 1;
        }
     }
+
+  if (option_bool(OPT_DNSSEC_VALID))
+    header->hb4 &= ~HB4_AD;
+  
+  if (!(header->hb4 & HB4_CD) && cache_secure)
+    header->hb4 |= HB4_AD;
 #endif
 
   /* do this after extract_addresses. Ensure NODATA reply and remove
index 5ae6e1b34b14ccb49d65d05accb84c7a515703f1..850dd8eda1a19cc3f16362eb8448416a484ab341 100644 (file)
@@ -754,7 +754,7 @@ int private_net(struct in_addr addr, int ban_localhost)
     ((ip_addr & 0xFFFF0000) == 0xA9FE0000)  /* 169.254.0.0/16 (zeroconf) */ ;
 }
 
-static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name)
+static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *header, size_t qlen, char *name, int *doctored)
 {
   int i, qtype, qclass, rdlen;
 
@@ -799,6 +799,7 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
              addr.s_addr |= (doctor->out.s_addr & doctor->mask.s_addr);
              /* Since we munged the data, the server it came from is no longer authoritative */
              header->hb3 &= ~HB3_AA;
+             *doctored = 1;
              memcpy(p, &addr, INADDRSZ);
              break;
            }
@@ -837,7 +838,7 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
   return p; 
 }
 
-static int find_soa(struct dns_header *header, size_t qlen, char *name)
+static int find_soa(struct dns_header *header, size_t qlen, char *name, int *doctored)
 {
   unsigned char *p;
   int qtype, qclass, rdlen;
@@ -846,7 +847,7 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name)
   
   /* first move to NS section and find TTL from any SOA section */
   if (!(p = skip_questions(header, qlen)) ||
-      !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name)))
+      !(p = do_doctor(p, ntohs(header->ancount), header, qlen, name, doctored)))
     return 0;  /* bad packet */
   
   for (i = ntohs(header->nscount); i != 0; i--)
@@ -881,8 +882,8 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name)
        return 0; /* bad packet */
     }
   
-  /* rewrite addresses in additioal section too */
-  if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL))
+  /* rewrite addresses in additional section too */
+  if (!do_doctor(p, ntohs(header->arcount), header, qlen, NULL, doctored))
     return 0;
   
   if (!found_soa)
@@ -896,7 +897,7 @@ static int find_soa(struct dns_header *header, size_t qlen, char *name)
    expired and cleaned out that way. 
    Return 1 if we reject an address because it look like part of dns-rebinding attack. */
 int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now, 
-                     char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec, int secure)
+                     char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec, int secure, int *doctored)
 {
   unsigned char *p, *p1, *endrr, *namep;
   int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
@@ -911,10 +912,14 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
   cache_start_insert();
 
   /* find_soa is needed for dns_doctor and logging side-effects, so don't call it lazily if there are any. */
-  if (daemon->doctors || option_bool(OPT_LOG))
+  if (daemon->doctors || option_bool(OPT_LOG) || option_bool(OPT_DNSSEC_VALID))
     {
       searched_soa = 1;
-      ttl = find_soa(header, qlen, name);
+      ttl = find_soa(header, qlen, name, doctored);
+#ifdef HAVE_DNSSEC
+      if (*doctored)
+       secure = 0;
+#endif
     }
   
   /* go through the questions. */
@@ -1004,7 +1009,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
              if (!searched_soa)
                {
                  searched_soa = 1;
-                 ttl = find_soa(header, qlen, NULL);
+                 ttl = find_soa(header, qlen, NULL, doctored);
                }
              if (ttl)
                cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | secflag);       
@@ -1120,7 +1125,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
              if (!searched_soa)
                {
                  searched_soa = 1;
-                 ttl = find_soa(header, qlen, NULL);
+                 ttl = find_soa(header, qlen, NULL, doctored);
                }
              /* If there's no SOA to get the TTL from, but there is a CNAME 
                 pointing at this, inherit its TTL */