Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-6]: src/dist/bind/lib/inet Pull up revision 1.3 (requested by i...



details:   https://anonhg.NetBSD.org/src/rev/a1a2ab1f0969
branches:  netbsd-1-6
changeset: 528187:a1a2ab1f0969
user:      lukem <lukem%NetBSD.org@localhost>
date:      Fri Jun 28 11:44:45 2002 +0000

description:
Pull up revision 1.3 (requested by itojun in ticket #387):
Update to BIND 8.3.3.  Fixes buffer overrun in resolver code.

diffstat:

 dist/bind/lib/inet/inet_cidr_pton.c |  169 ++++++++++++++++++++++++++++++-----
 1 files changed, 145 insertions(+), 24 deletions(-)

diffs (237 lines):

diff -r 61e2397b9302 -r a1a2ab1f0969 dist/bind/lib/inet/inet_cidr_pton.c
--- a/dist/bind/lib/inet/inet_cidr_pton.c       Fri Jun 28 11:44:24 2002 +0000
+++ b/dist/bind/lib/inet/inet_cidr_pton.c       Fri Jun 28 11:44:45 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: inet_cidr_pton.c,v 1.2 2001/01/27 07:22:03 itojun Exp $        */
+/*     $NetBSD: inet_cidr_pton.c,v 1.2.2.1 2002/06/28 11:44:45 lukem Exp $     */
 
 /*
  * Copyright (c) 1998,1999 by Internet Software Consortium.
@@ -18,7 +18,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "Id: inet_cidr_pton.c,v 8.4 2000/12/23 08:14:53 vixie Exp";
+static const char rcsid[] = "Id: inet_cidr_pton.c,v 8.7 2001/09/28 04:21:28 marka Exp";
 #endif
 
 #include "port_before.h"
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <arpa/nameser.h>
 #include <arpa/inet.h>
 
 #include <isc/assertions.h>
@@ -44,8 +45,12 @@
 #endif
 
 static int     inet_cidr_pton_ipv4 __P((const char *src, u_char *dst,
+                                        int *bits, int ipv6));
+static int     inet_cidr_pton_ipv6 __P((const char *src, u_char *dst,
                                         int *bits));
 
+static int     getbits(const char *, int ipv6);
+
 /*
  * int
  * inet_cidr_pton(af, src, dst, *bits)
@@ -67,16 +72,19 @@
 inet_cidr_pton(int af, const char *src, void *dst, int *bits) {
        switch (af) {
        case AF_INET:
-               return (inet_cidr_pton_ipv4(src, dst, bits));
+               return (inet_cidr_pton_ipv4(src, dst, bits, 0));
+       case AF_INET6:
+               return (inet_cidr_pton_ipv6(src, dst, bits));
        default:
                errno = EAFNOSUPPORT;
                return (-1);
        }
 }
 
+static const char digits[] = "0123456789";
+
 static int
-inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits) {
-       static const char digits[] = "0123456789";
+inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) {
        const u_char *odst = dst;
        int n, ch, tmp, bits;
        size_t size = 4;
@@ -103,30 +111,17 @@
 
        /* Get the prefix length if any. */
        bits = -1;
-       if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) {
-               /* CIDR width specifier.  Nothing can follow it. */
-               ch = *src++;    /* Skip over the /. */
-               bits = 0;
-               do {
-                       n = strchr(digits, ch) - digits;
-                       INSIST(n >= 0 && n <= 9);
-                       bits *= 10;
-                       bits += n;
-               } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
-               if (ch != '\0')
+       if (ch == '/' && dst > odst) {
+               bits = getbits(src, ipv6);
+               if (bits == -2)
                        goto enoent;
-               if (bits > 32)
-                       goto emsgsize;
-       }
-
-       /* Firey death and destruction unless we prefetched EOS. */
-       if (ch != '\0')
+       } else if (ch != '\0')
                goto enoent;
 
        /* Prefix length can default to /32 only if all four octets spec'd. */
        if (bits == -1) {
                if (dst - odst == 4)
-                       bits = 32;
+                       bits = ipv6 ? 128 : 32;
                else
                        goto enoent;
        }
@@ -136,7 +131,7 @@
                goto enoent;
 
        /* If prefix length overspecifies mantissa, life is bad. */
-       if ((bits / 8) > (dst - odst))
+       if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst))
                goto enoent;
 
        /* Extend address to four octets. */
@@ -154,3 +149,129 @@
        errno = EMSGSIZE;
        return (-1);
 }
+
+static int
+inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) {
+       static const char xdigits_l[] = "0123456789abcdef",
+                         xdigits_u[] = "0123456789ABCDEF";
+       u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+       const char *xdigits, *curtok;
+       int ch, saw_xdigit;
+       u_int val;
+       int bits;
+
+       memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+       endp = tp + NS_IN6ADDRSZ;
+       colonp = NULL;
+       /* Leading :: requires some special handling. */
+       if (*src == ':')
+               if (*++src != ':')
+                       return (0);
+       curtok = src;
+       saw_xdigit = 0;
+       val = 0;
+       bits = -1;
+       while ((ch = *src++) != '\0') {
+               const char *pch;
+
+               if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+                       pch = strchr((xdigits = xdigits_u), ch);
+               if (pch != NULL) {
+                       val <<= 4;
+                       val |= (pch - xdigits);
+                       if (val > 0xffff)
+                               return (0);
+                       saw_xdigit = 1;
+                       continue;
+               }
+               if (ch == ':') {
+                       curtok = src;
+                       if (!saw_xdigit) {
+                               if (colonp)
+                                       return (0);
+                               colonp = tp;
+                               continue;
+                       } else if (*src == '\0') {
+                               return (0);
+                       }
+                       if (tp + NS_INT16SZ > endp)
+                               return (0);
+                       *tp++ = (u_char) (val >> 8) & 0xff;
+                       *tp++ = (u_char) val & 0xff;
+                       saw_xdigit = 0;
+                       val = 0;
+                       continue;
+               }
+               if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+                   inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) {
+                       tp += NS_INADDRSZ;
+                       saw_xdigit = 0;
+                       break;  /* '\0' was seen by inet_pton4(). */
+               }
+               if (ch == '/') {
+                       bits = getbits(src, 1);
+                       if (bits == -2)
+                               goto enoent;
+                       break;
+               }
+               goto enoent;
+       }
+       if (saw_xdigit) {
+               if (tp + NS_INT16SZ > endp)
+                       goto emsgsize;
+               *tp++ = (u_char) (val >> 8) & 0xff;
+               *tp++ = (u_char) val & 0xff;
+       }
+       if (colonp != NULL) {
+               /*
+                * Since some memmove()'s erroneously fail to handle
+                * overlapping regions, we'll do the shift by hand.
+                */
+               const int n = tp - colonp;
+               int i;
+
+               if (tp == endp)
+                       goto enoent;
+               for (i = 1; i <= n; i++) {
+                       endp[- i] = colonp[n - i];
+                       colonp[n - i] = 0;
+               }
+               tp = endp;
+       }
+
+       memcpy(dst, tmp, NS_IN6ADDRSZ);
+
+       *pbits = bits;
+       return (0);
+
+ enoent:
+       errno = ENOENT;
+       return (-1);
+
+ emsgsize:
+       errno = EMSGSIZE;
+       return (-1);
+}
+
+int
+getbits(const char *src, int ipv6) {
+       int bits = 0;
+       char *cp, ch;
+       
+       if (*src == '\0')                       /* syntax */
+               return (-2);
+       do {
+               ch = *src++;
+               cp = strchr(digits, ch);
+               if (cp == NULL)                 /* syntax */
+                       return (-2);
+               bits *= 10;
+               bits += cp - digits;
+               if (bits == 0 && *src != '\0')  /* no leading zeros */
+                       return (-2);
+               if (bits > (ipv6 ? 128 : 32))   /* range error */
+                       return (-2);
+       } while (*src != '\0');
+
+       return (bits);
+}



Home | Main Index | Thread Index | Old Index