]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Allow control characters in names in the cache, handle when logging.
authorSimon Kelley <simon@thekelleys.org.uk>
Sun, 29 Mar 2015 21:17:14 +0000 (22:17 +0100)
committerSimon Kelley <simon@thekelleys.org.uk>
Sun, 29 Mar 2015 21:17:14 +0000 (22:17 +0100)
src/cache.c
src/dnssec.c
src/rfc1035.c

index c95624c42b1c68aae94d9a1165eecb155785a247..873c5779044cf71ef94012f22d44e94f0eaf4d92 100644 (file)
@@ -1399,6 +1399,19 @@ int cache_make_stat(struct txt_record *t)
   return 1;
 }
 
+/* There can be names in the cache containing control chars, don't 
+   mess up logging or open security holes. */
+static char *sanitise(char *name)
+{
+  unsigned char *r;
+  for (r = (unsigned char *)name; *r; r++)
+    if (!isprint((int)*r))
+      return "<name unprintable>";
+
+  return name;
+}
+
+
 void dump_cache(time_t now)
 {
   struct server *serv, *serv1;
@@ -1452,9 +1465,9 @@ void dump_cache(time_t now)
            *a = 0;
            if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
              n = "<Root>";
-           p += sprintf(p, "%-30.30s ", n);
+           p += sprintf(p, "%-30.30s ", sanitise(n));
            if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
-             a = cache_get_cname_target(cache);
+             a = sanitise(cache_get_cname_target(cache));
 #ifdef HAVE_DNSSEC
            else if (cache->flags & F_DS)
              {
@@ -1587,6 +1600,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
   if (!option_bool(OPT_LOG))
     return;
 
+  name = sanitise(name);
+
   if (addr)
     {
       if (flags & F_KEYTAG)
index 8bd5294ce773f2df9761a43cb181229ff585b41b..14bae7e9bf75f9be68f7760a838f37355ff915e3 100644 (file)
@@ -552,7 +552,7 @@ static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end,
  
   (*desc)++;
   
-  if (d == 0 && extract_name(header, plen, p, buff, 2, 0))
+  if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
     /* domain-name, canonicalise */
     return to_wire(buff);
   else
@@ -811,7 +811,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
       GETLONG(sig_inception, p);
       GETSHORT(key_tag, p);
       
-      if (!extract_name(header, plen, &p, keyname, 2, 0))
+      if (!extract_name(header, plen, &p, keyname, 1, 0))
        return STAT_BOGUS;
 
       /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
@@ -866,7 +866,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
          u16 len, *dp;
          
          p = rrset[i];
-         if (!extract_name(header, plen, &p, name, 2, 10)) 
+         if (!extract_name(header, plen, &p, name, 1, 10)) 
            return STAT_BOGUS;
 
          name_start = name;
@@ -923,7 +923,7 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
       
       /* namebuff used for workspace above, restore to leave unchanged on exit */
       p = (unsigned char*)(rrset[0]);
-      extract_name(header, plen, &p, name, 2, 0);
+      extract_name(header, plen, &p, name, 1, 0);
 
       if (key)
        {
@@ -963,7 +963,7 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
   struct all_addr a;
 
   if (ntohs(header->qdcount) != 1 ||
-      !extract_name(header, plen, &p, name, 2, 4))
+      !extract_name(header, plen, &p, name, 1, 4))
     return STAT_BOGUS;
 
   GETSHORT(qtype, p);
@@ -1202,7 +1202,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
     val = STAT_BOGUS;
   
   p = (unsigned char *)(header+1);
-  extract_name(header, plen, &p, name, 2, 4);
+  extract_name(header, plen, &p, name, 1, 4);
   p += 4; /* qtype, qclass */
   
   if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
@@ -1419,12 +1419,12 @@ static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsi
   for (i = 0; i < nsec_count; i++)
     {
       p = nsecs[i];
-      if (!extract_name(header, plen, &p, workspace1, 2, 10))
+      if (!extract_name(header, plen, &p, workspace1, 1, 10))
        return STAT_BOGUS;
       p += 8; /* class, type, TTL */
       GETSHORT(rdlen, p);
       psave = p;
-      if (!extract_name(header, plen, &p, workspace2, 2, 10))
+      if (!extract_name(header, plen, &p, workspace2, 1, 10))
        return STAT_BOGUS;
       
       rc = hostname_cmp(workspace1, name);
@@ -1553,7 +1553,7 @@ static int check_nsec3_coverage(struct dns_header *header, size_t plen, int dige
   for (i = 0; i < nsec_count; i++)
     if ((p = nsecs[i]))
       {
-               if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
+               if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
            !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
          return 0;
        
@@ -1730,7 +1730,7 @@ static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, uns
       for (i = 0; i < nsec_count; i++)
        if ((p = nsecs[i]))
          {
-           if (!extract_name(header, plen, &p, workspace1, 2, 0) ||
+           if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
                !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
              return STAT_BOGUS;
          
@@ -1796,7 +1796,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
 
   qname = p1 = (unsigned char *)(header+1);
   
-  if (!extract_name(header, plen, &p1, name, 2, 4))
+  if (!extract_name(header, plen, &p1, name, 1, 4))
     return STAT_BOGUS;
 
   GETSHORT(qtype, p1);
@@ -1836,7 +1836,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
              qname = p1;
              
              /* looped CNAMES */
-             if (!cname_count-- || !extract_name(header, plen, &p1, name, 2, 0))
+             if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
                return STAT_BOGUS;
               
              p1 = ans_start;
@@ -1857,7 +1857,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
   
   for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
     {
-      if (!extract_name(header, plen, &p1, name, 2, 10))
+      if (!extract_name(header, plen, &p1, name, 1, 10))
        return STAT_BOGUS; /* bad packet */
       
       GETSHORT(type1, p1);
@@ -2039,7 +2039,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
                           an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
    
   /* Get name of missing answer */
-  if (!extract_name(header, plen, &qname, name, 2, 0))
+  if (!extract_name(header, plen, &qname, name, 1, 0))
     return STAT_BOGUS;
   
   if (nsec_type == T_NSEC)
@@ -2061,7 +2061,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
   int cname_count = CNAME_CHAIN;
 
   /* Get question */
-  if (!extract_name(header, plen, &p, name, 2, 4))
+  if (!extract_name(header, plen, &p, name, 1, 4))
     return STAT_BOGUS;
   
   p +=2; /* type */
@@ -2102,7 +2102,7 @@ int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char
 
          /* Loop down CNAME chain/ */
          if (!cname_count-- || 
-             !extract_name(header, plen, &p, name, 2, 0) ||
+             !extract_name(header, plen, &p, name, 1, 0) ||
              !(p = skip_questions(header, plen)))
            return STAT_BOGUS;
          
@@ -2419,7 +2419,7 @@ unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name
   
   for (q = ntohs(header->qdcount); q != 0; q--) 
     {
-      if (!extract_name(header, plen, &p, name, 2, 4))
+      if (!extract_name(header, plen, &p, name, 1, 4))
        break; /* bad packet */
       
       len = to_wire(name);
index 10832a3d5d2e3e81e04a5576ba705947c38bd496..7a07b0cee90655e296f57fa79f4d4a3a409b7b89 100644 (file)
@@ -16,7 +16,6 @@
 
 #include "dnsmasq.h"
 
-/* isExtract == 2 -> DNSSEC mode, no bitstrings, no ascii checks. */
 int extract_name(struct dns_header *header, size_t plen, unsigned char **pp, 
                 char *name, int isExtract, int extrabytes)
 {
@@ -87,7 +86,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
          if ((l & 0x3f) != 1)
            return 0; /* we only understand bitstrings */
 
-         if (isExtract != 1)
+         if (!isExtract)
            return 0; /* Cannot compare bitsrings */
          
          count = *p++;
@@ -129,8 +128,8 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
            if (isExtract)
              {
                unsigned char c = *p;
-               if ((isExtract == 2 || (isascii(c) && !iscntrl(c))) && c != '.')
-                 *cp++ = *p;
+               if (c != 0 && c != '.')
+                 *cp++ = c;
                else
                  return 0;
              }