US-CERT
Vulnerability
Notes
Database

Search Vulnerability Notes

Vulnerability Notes Help Information
 

 View Notes By
Name

ID Number

CVE Name

Date Public

Date Published

Date Updated

Severity Metric

 Other Documents
Technical Alerts

Technical Bulletins

Alerts

Security Tips

GNU glibc Information for VU#844360

Date Notified11/12/2002
Date Modified04/24/2003 12:10:01 AM
Status SummaryVulnerable

Vendor Statement

Version 2.3.1 of the GNU C Library is vulnerable. Earlier versions are also vulnerable. The following patch has been installed into the CVS sources, and should appear in the next version of the GNU C Library. This patch is also available from the following URL:

<http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/resolv/nss_dns/dns-network.c.diff?r1=1.17&r2=1.15&cvsroot=glibc>

2002-11-18  Roland McGrath  <roland@redhat.com>

        * resolv/nss_dns/dns-network.c (getanswer_r): In BYNAME case, search
        all aliases for one that matches the "<dotted-quad>.IN-ADDR.ARPA" form.
        Do the parsing inline instead of copying strings and calling
        inet_network, and properly skip all alias names not matching the form.

2002-11-14  Paul Eggert  <eggert@twinsun.com>

        * resolv/nss_dns/dns-network.c (getanswer_r): Check for buffer
        overflow when skipping the question part and when unpacking aliases.

===================================================================
RCS file: /cvs/glibc/libc/resolv/nss_dns/dns-network.c,v
retrieving revision 1.15
retrieving revision 1.17
diff -u -r1.15 -r1.17
--- libc/resolv/nss_dns/dns-network.c   2002/10/17 21:49:12     1.15
+++ libc/resolv/nss_dns/dns-network.c   2002/11/19 06:40:16     1.17
@@ -283,7 +283,15 @@

   /* Skip the question part.  */
   while (question_count-- > 0)
-    cp += __dn_skipname (cp, end_of_message) + QFIXEDSZ;
+    {
+      int n = __dn_skipname (cp, end_of_message);
+      if (n < 0 || end_of_message - (cp + n) < QFIXEDSZ)
+       {
+         __set_h_errno (NO_RECOVERY);
+         return NSS_STATUS_UNAVAIL;
+       }
+      cp += n + QFIXEDSZ;
+    }

   alias_pointer = result->n_aliases = &net_data->aliases[0];
   *alias_pointer = NULL;
@@ -344,64 +352,94 @@
              return NSS_STATUS_UNAVAIL;
            }
          cp += n;
-         *alias_pointer++ = bp;
-         n = strlen (bp) + 1;
-         bp += n;
-         linebuflen -= n;
-         result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
-         ++have_answer;
+         if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
+           {
+             *alias_pointer++ = bp;
+             n = strlen (bp) + 1;
+             bp += n;
+             linebuflen -= n;
+             result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
+             ++have_answer;
+           }
        }
     }

   if (have_answer)
     {
-      char *tmp;
-      int len;
-      char *in, *cp, *rp, *wp;
-      int cnt, first_flag;
-
       *alias_pointer = NULL;
       switch (net_i)
        {
        case BYADDR:
-         result->n_name = result->n_aliases[0];
+         result->n_name = *result->n_aliases++;
          result->n_net = 0L;
-         break;
-       case BYNAME:
-         len = strlen (result->n_aliases[0]);
-         tmp = (char *) alloca (len + 1);
-         tmp[len] = 0;
-         wp = &tmp[len - 1];
-
-         rp = in = result->n_aliases[0];
-         result->n_name = ans;
-
-         first_flag = 1;
-         for (cnt = 0; cnt < 4; ++cnt)
-           {
-             char *startp;
+         return NSS_STATUS_SUCCESS;

-             startp = rp;
-             while (*rp != '.')
-               ++rp;
-             if (rp - startp > 1 || *startp != '0' || !first_flag)
-               {
-                 first_flag = 0;
-                 if (cnt > 0)
-                   *wp-- = '.';
-                 cp = rp;
-                 while (cp > startp)
-                   *wp-- = *--cp;
-               }
-             in = rp + 1;
-           }
-
-         result->n_net = inet_network (wp);
+       case BYNAME:
+         {
+           char **ap = result->n_aliases++;
+           while (*ap != NULL)
+             {
+               /* Check each alias name for being of the forms:
+                  4.3.2.1.in-addr.arpa         = net 1.2.3.4
+                  3.2.1.in-addr.arpa           = net 0.1.2.3
+                  2.1.in-addr.arpa             = net 0.0.1.2
+                  1.in-addr.arpa               = net 0.0.0.1
+               */
+               uint32_t val = 0;       /* Accumulator for n_net value.  */
+               unsigned int shift = 0; /* Which part we are parsing now.  */
+               const char *p = *ap; /* Consuming the string.  */
+               do
+                 {
+                   /* Match the leading 0 or 0[xX] base indicator.  */
+                   unsigned int base = 10;
+                   if (*p == '0' && p[1] != '.')
+                     {
+                       base = 8;
+                       ++p;
+                       if (*p == 'x' || *p == 'X')
+                         {
+                           base = 16;
+                           ++p;
+                           if (*p == '.')
+                             break; /* No digit here.  Give up on alias.  */
+                         }
+                       if (*p == '\0')
+                         break;
+                     }
+
+                   uint32_t part = 0; /* Accumulates this part's number.  */
+                   do
+                     {
+                       if (isdigit (*p) && (*p - '0' < base))
+                         part = (part * base) + (*p - '0');
+                       else if (base == 16 && isxdigit (*p))
+                         part = (part << 4) + 10 + (tolower (*p) - 'a');
+                       ++p;
+                     } while (*p != '\0' && *p != '.');
+
+                   if (*p != '.')
+                     break;    /* Bad form.  Give up on this name.  */
+
+                   /* Install this as the next more significant byte.  */
+                   val |= part << shift;
+                   shift += 8;
+                   ++p;
+
+                   /* If we are out of digits now, there are two cases:
+                      1. We are done with digits and now see "in-addr.arpa".
+                      2. This is not the droid we are looking for.  */
+                   if (!isdigit (*p) && !strcasecmp (p, "in-addr.arpa"))
+                     {
+                       result->n_net = val;
+                       return NSS_STATUS_SUCCESS;
+                     }
+
+                   /* Keep going when we have seen fewer than 4 parts.  */
+                 } while (shift < 32);
+             }
+         }
          break;
        }
-
-      ++result->n_aliases;
-      return NSS_STATUS_SUCCESS;
     }

   __set_h_errno (TRY_AGAIN);

US-CERT Addendum

The CERT/CC has no additional comments at this time.

If you have feedback, comments, or additional information about this vulnerability, please send us email.
 

Produced 2008 by US-CERT, a government organization
Disclaimers and copyright information