protocol parsing: check input data stricter
authorPatrick Valsecchi <pvalsecc@cisco.com>
Mon, 15 Apr 2013 20:28:01 +0000 (22:28 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 15 Apr 2013 20:28:01 +0000 (22:28 +0200)
... so that bad length fields aren't blindly accepted

Bug: http://c-ares.haxx.se/mail/c-ares-archive-2013-04/0016.shtml

ares_expand_name.c
ares_parse_a_reply.c
ares_parse_aaaa_reply.c
ares_parse_mx_reply.c
ares_parse_naptr_reply.c
ares_parse_ns_reply.c
ares_parse_ptr_reply.c
ares_parse_srv_reply.c
ares_parse_txt_reply.c

index a66dfa97332a604043fb511b85494ef1dccac7b3..2aa12bc0efbb2bcfafe6b0567d23016000e5a00b 100644 (file)
@@ -143,7 +143,7 @@ static int name_length(const unsigned char *encoded, const unsigned char *abuf,
   int n = 0, offset, indir = 0;
 
   /* Allow the caller to pass us abuf + alen and have us check for it. */
-  if (encoded == abuf + alen)
+  if (encoded >= abuf + alen)
     return -1;
 
   while (*encoded)
index 9683ef5e135b8798593c631cc70fe1523127d9f9..a3ed69e1e9ef8421e70ae2fa62357792efd8f6c2 100644 (file)
@@ -136,6 +136,12 @@ int ares_parse_a_reply(const unsigned char *abuf, int alen,
       rr_len = DNS_RR_LEN(aptr);
       rr_ttl = DNS_RR_TTL(aptr);
       aptr += RRFIXEDSZ;
+      if (aptr + rr_len > abuf + alen)
+        {
+          free(rr_name);
+          status = ARES_EBADRESP;
+          break;
+        }
 
       if (rr_class == C_IN && rr_type == T_A
           && rr_len == sizeof(struct in_addr)
index 77312499ada4dde4d777ecdb294b72dc7b24301a..a34a30712339e0a7d3a87be9349a37f734fd688f 100644 (file)
@@ -136,6 +136,12 @@ int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
       rr_len = DNS_RR_LEN(aptr);
       rr_ttl = DNS_RR_TTL(aptr);
       aptr += RRFIXEDSZ;
+      if (aptr + rr_len > abuf + alen)
+        {
+          free(rr_name);
+          status = ARES_EBADRESP;
+          break;
+        }
 
       if (rr_class == C_IN && rr_type == T_AAAA
           && rr_len == sizeof(struct ares_in6_addr)
index 32d3af4835e8c73bd95f281499bad5cdff35dd92..95400dd317412ea162794ebbad2be8eba5cd96d1 100644 (file)
@@ -100,6 +100,11 @@ ares_parse_mx_reply (const unsigned char *abuf, int alen,
       rr_class = DNS_RR_CLASS (aptr);
       rr_len = DNS_RR_LEN (aptr);
       aptr += RRFIXEDSZ;
+      if (aptr + rr_len > abuf + alen)
+        {
+          status = ARES_EBADRESP;
+          break;
+        }
 
       /* Check if we are really looking at a MX record */
       if (rr_class == C_IN && rr_type == T_MX)
index 9315df7297963287b65a3c3064a4f430c4fae7c1..4935366478fa2d922a05d3570239502ea4a5fc49 100644 (file)
@@ -105,6 +105,11 @@ ares_parse_naptr_reply (const unsigned char *abuf, int alen,
       rr_class = DNS_RR_CLASS (aptr);
       rr_len = DNS_RR_LEN (aptr);
       aptr += RRFIXEDSZ;
+      if (aptr + rr_len > abuf + alen)
+        {
+          status = ARES_EBADRESP;
+          break;
+        }
 
       /* Check if we are really looking at a NAPTR record */
       if (rr_class == C_IN && rr_type == T_NAPTR)
index 553f25349785b2c9cd3d0a2b9f5ebd807d64a879..d331e67d5ff86831ddad7983cb704ef7bac6f9b7 100644 (file)
@@ -105,6 +105,12 @@ int ares_parse_ns_reply( const unsigned char* abuf, int alen,
     rr_class = DNS_RR_CLASS( aptr );
     rr_len = DNS_RR_LEN( aptr );
     aptr += RRFIXEDSZ;
+    if (aptr + rr_len > abuf + alen)
+      {
+        free(rr_name);
+        status = ARES_EBADRESP;
+        break;
+      }
 
     if ( rr_class == C_IN && rr_type == T_NS )
     {
index b505b9266543b7b813b3ede57674669fd0c3784e..df21e40dc1c83dd6b9b84bcdeed365f80ab44ac6 100644 (file)
@@ -103,6 +103,12 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
       rr_class = DNS_RR_CLASS(aptr);
       rr_len = DNS_RR_LEN(aptr);
       aptr += RRFIXEDSZ;
+      if (aptr + rr_len > abuf + alen)
+        {
+          free(rr_name);
+          status = ARES_EBADRESP;
+          break;
+        }
 
       if (rr_class == C_IN && rr_type == T_PTR
           && strcasecmp(rr_name, ptrname) == 0)
@@ -203,7 +209,7 @@ int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
       status = ARES_ENOMEM;
     }
   for (i=0 ; i<aliascnt ; i++)
-    if (aliases[i]) 
+    if (aliases[i])
       free(aliases[i]);
   free(aliases);
   if (hostname)
index 9f61f19bb6397d24202dc235b7de2e54cb823054..0739c276847b5fd2bd5a97985afe36f950f88e0c 100644 (file)
@@ -105,6 +105,11 @@ ares_parse_srv_reply (const unsigned char *abuf, int alen,
       rr_class = DNS_RR_CLASS (aptr);
       rr_len = DNS_RR_LEN (aptr);
       aptr += RRFIXEDSZ;
+      if (aptr + rr_len > abuf + alen)
+        {
+          status = ARES_EBADRESP;
+          break;
+        }
 
       /* Check if we are really looking at a SRV record */
       if (rr_class == C_IN && rr_type == T_SRV)
index dcc64736f3ebd926e96adc63a288268773f9f817..3a43d6a1e9bb6dfa625384e63cf0fd1f45153fe9 100644 (file)
@@ -106,6 +106,11 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
       rr_class = DNS_RR_CLASS (aptr);
       rr_len = DNS_RR_LEN (aptr);
       aptr += RRFIXEDSZ;
+      if (aptr + rr_len > abuf + alen)
+        {
+          status = ARES_EBADRESP;
+          break;
+        }
 
       /* Check if we are really looking at a TXT record */
       if (rr_class == C_IN && rr_type == T_TXT)
@@ -144,6 +149,12 @@ ares_parse_txt_reply (const unsigned char *abuf, int alen,
               strptr += substr_len + 1;
             }
 
+          if (strptr != (aptr + rr_len))
+            {
+              status = ARES_EBADRESP;
+              break;
+            }
+
           /* Including null byte */
           txt_curr->txt = malloc (txt_curr->length + 1);
           if (txt_curr->txt == NULL)