]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Disable DNSSEC for server=/domain/.. servers unless trust-anchor provided.
authorSimon Kelley <simon@thekelleys.org.uk>
Tue, 12 Jan 2016 15:58:23 +0000 (15:58 +0000)
committerSimon Kelley <simon@thekelleys.org.uk>
Tue, 12 Jan 2016 15:58:23 +0000 (15:58 +0000)
src/dnsmasq.h
src/dnssec.c
src/forward.c
src/network.c

index b2d1c5e0219730ef0c655ee3e0a00e1b3522e425..543481c20573d6b6e2900c3c3688b3ffabcbf56a 100644 (file)
@@ -477,6 +477,7 @@ union mysockaddr {
 #define SERV_NO_REBIND      2048  /* inhibit dns-rebind protection */
 #define SERV_FROM_FILE      4096  /* read from --servers-file */
 #define SERV_LOOP           8192  /* server causes forwarding loop */
+#define SERV_DO_DNSSEC     16384  /* Validate DNSSEC when using this server */
 
 struct serverfd {
   int fd;
index 18efa5978d268aa288fef5d40190fd2c4e0592fe..ebb9c93d10908eee625beea88b73f422265de9ca 100644 (file)
@@ -1892,7 +1892,7 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
          break;
        }
     }
-  
+
   /* Now work away from the trust anchor */
   while (1)
     {
index 14585782b844a86421242ae9b1240d8aca73e272..11c0d45f441ecd1e3a582f12ad1e2882cc9afe2f 100644 (file)
@@ -106,8 +106,8 @@ int send_from(int fd, int nowild, char *packet, size_t len,
   return 1;
 }
           
-static unsigned int search_servers(time_t now, struct all_addr **addrpp, 
-                                    unsigned int qtype, char *qdomain, int *type, char **domain, int *norebind)
+static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigned int qtype,
+                                  char *qdomain, int *type, char **domain, int *norebind)
                              
 {
   /* If the query ends in the domain in one of our servers, set
@@ -175,7 +175,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp,
                
                if (domainlen >= matchlen)
                  {
-                   *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND);
+                   *type = serv->flags & (SERV_HAS_DOMAIN | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_DO_DNSSEC);
                    *domain = serv->domain;
                    matchlen = domainlen;
                    if (serv->flags & SERV_NO_ADDR)
@@ -233,12 +233,13 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
                         struct frec *forward, int ad_reqd, int do_bit)
 {
   char *domain = NULL;
-  int type = 0, norebind = 0;
+  int type = SERV_DO_DNSSEC, norebind = 0;
   struct all_addr *addrp = NULL;
   unsigned int flags = 0;
   struct server *start = NULL;
 #ifdef HAVE_DNSSEC
   void *hash = hash_questions(header, plen, daemon->namebuff);
+  int do_dnssec = 0;
 #else
   unsigned int crc = questions_crc(header, plen, daemon->namebuff);
   void *hash = &crc;
@@ -315,6 +316,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
          daemon->last_server = NULL;
        }
       type = forward->sentto->flags & SERV_TYPE;
+#ifdef HAVE_DNSSEC
+      do_dnssec = forward->sentto->flags & SERV_DO_DNSSEC;
+#endif
+
       if (!(start = forward->sentto->next))
        start = daemon->servers; /* at end of list, recycle */
       header->id = htons(forward->new_id);
@@ -324,6 +329,11 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
       if (gotname)
        flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
       
+#ifdef HAVE_DNSSEC
+      do_dnssec = type & SERV_DO_DNSSEC;
+      type &= ~SERV_DO_DNSSEC;
+#endif      
+
       if (!flags && !(forward = get_new_frec(now, NULL, 0)))
        /* table full - server failure. */
        flags = F_NEG;
@@ -406,7 +416,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
        }
       
 #ifdef HAVE_DNSSEC
-      if (option_bool(OPT_DNSSEC_VALID) && !(type & SERV_HAS_DOMAIN))
+      if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
        {
          size_t new = add_do_bit(header, plen, ((unsigned char *) header) + PACKETSZ);
         
@@ -858,7 +868,7 @@ void reply_query(int fd, int family, time_t now)
        no_cache_dnssec = 1;
       
 #ifdef HAVE_DNSSEC
-      if (server && !(server->flags & SERV_HAS_DOMAIN) && 
+      if (server && (server->flags & SERV_DO_DNSSEC) && 
          option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
        {
          int status = 0;
@@ -1640,6 +1650,10 @@ unsigned char *tcp_request(int confd, time_t now,
              if (gotname)
                flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
              
+#ifdef HAVE_DNSSEC
+             type &= ~SERV_DO_DNSSEC;
+#endif
+             
              if (type != 0  || option_bool(OPT_ORDER) || !daemon->last_server)
                last_server = daemon->servers;
              else
@@ -1711,7 +1725,7 @@ unsigned char *tcp_request(int confd, time_t now,
                            }
                          
 #ifdef HAVE_DNSSEC
-                         if (option_bool(OPT_DNSSEC_VALID))
+                         if (option_bool(OPT_DNSSEC_VALID) && (last_server->flags & SERV_DO_DNSSEC))
                            {
                              new_size = add_do_bit(header, size, ((unsigned char *) header) + 65536);
                              
@@ -1757,7 +1771,7 @@ unsigned char *tcp_request(int confd, time_t now,
 #endif 
 
 #ifdef HAVE_DNSSEC
-                     if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled)
+                     if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
                        {
                          int keycount = DNSSEC_WORK; /* Limit to number of DNSSEC questions, to catch loops and avoid filling cache. */
                          int status = tcp_key_recurse(now, STAT_OK, header, m, 0, daemon->namebuff, daemon->keyname, last_server, &keycount);
index 66b91add6d5dc0d05480fb9a30a781f3c0c83d5b..303ae50745474dcc6883c3ec9e17a389b9f8ad47 100644 (file)
@@ -1430,12 +1430,38 @@ void check_servers(void)
   if (!option_bool(OPT_NOWILD))
     enumerate_interfaces(0);
   
+#ifdef HAVE_DNSSEC
+ /* Disable DNSSEC validation when using server=/domain/.... servers
+    unless there's a configured trust anchor. */
+  for (serv = daemon->servers; serv; serv = serv->next)
+    serv->flags |= SERV_DO_DNSSEC;
+#endif
+
   for (serv = daemon->servers; serv; serv = serv->next)
     {
-       if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
+      if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
        {
-         port = prettyprint_addr(&serv->addr, daemon->namebuff);
+#ifdef HAVE_DNSSEC
+         if (option_bool(OPT_DNSSEC_VALID) && (serv->flags & SERV_HAS_DOMAIN))
+           {
+             struct ds_config *ds;
+             char *domain = serv->domain;
+
+             /* .example.com is valid */
+             while (*domain == '.')
+               domain++;
+             
+             for (ds = daemon->ds; ds; ds = ds->next)
+               if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
+                 break;
 
+             if (!ds)
+               serv->flags &= ~SERV_DO_DNSSEC;
+           }
+#endif
+
+         port = prettyprint_addr(&serv->addr, daemon->namebuff);
+         
          /* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
          if (serv->addr.sa.sa_family == AF_INET &&
              serv->addr.in.sin_addr.s_addr == 0)
@@ -1471,7 +1497,11 @@ void check_servers(void)
        {
          if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
            {
-             char *s1, *s2;
+             char *s1, *s2, *s3 = "";
+#ifdef HAVE_DNSSEC
+             if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
+               s3 = _("(no DNSSEC)");
+#endif
              if (!(serv->flags & SERV_HAS_DOMAIN))
                s1 = _("unqualified"), s2 = _("names");
              else if (strlen(serv->domain) == 0)
@@ -1484,7 +1514,7 @@ void check_servers(void)
              else if (serv->flags & SERV_USE_RESOLV)
                my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
              else 
-               my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
+               my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
            }
 #ifdef HAVE_LOOP
          else if (serv->flags & SERV_LOOP)