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 a66dfa9..2aa12bc 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 9683ef5..a3ed69e 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 7731249..a34a307 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 32d3af4..95400dd 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 9315df7..4935366 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 553f253..d331e67 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 b505b92..df21e40 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 9f61f19..0739c27 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 dcc6473..3a43d6a 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)