about summary refs log tree commit diff
path: root/resolv/inet_addr.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2019-01-21 21:26:03 +0100
committerFlorian Weimer <fweimer@redhat.com>2019-01-21 21:26:03 +0100
commit108bc4049f8ae82710aec26a92ffdb4b439c83fd (patch)
tree8028ac534476871bac578df4435bf0bf7388f672 /resolv/inet_addr.c
parent5165de69c0908e28a380cbd4bb054e55ea4abc95 (diff)
downloadglibc-108bc4049f8ae82710aec26a92ffdb4b439c83fd.tar.gz
glibc-108bc4049f8ae82710aec26a92ffdb4b439c83fd.tar.xz
glibc-108bc4049f8ae82710aec26a92ffdb4b439c83fd.zip
CVE-2016-10739: getaddrinfo: Fully parse IPv4 address strings [BZ #20018]
The IPv4 address parser in the getaddrinfo function is changed so that
it does not ignore trailing whitespace and all characters after it.
For backwards compatibility, the getaddrinfo function still recognizes
legacy name syntax, such as 192.000.002.010 interpreted as 192.0.2.8
(octal).

This commit does not change the behavior of inet_addr and inet_aton.
gethostbyname already had additional sanity checks (but is switched
over to the new __inet_aton_exact function for completeness as well).

To avoid sending the problematic query names over DNS, commit
6ca53a2453598804a2559a548a08424fca96434a ("resolv: Do not send queries
for non-host-names in nss_dns [BZ #24112]") is needed.
Diffstat (limited to 'resolv/inet_addr.c')
-rw-r--r--resolv/inet_addr.c62
1 files changed, 43 insertions, 19 deletions
diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c
index 32f58b0e13..41b6166a5b 100644
--- a/resolv/inet_addr.c
+++ b/resolv/inet_addr.c
@@ -96,26 +96,14 @@
 #include <limits.h>
 #include <errno.h>
 
-/* ASCII IPv4 Internet address interpretation routine.  The value
-   returned is in network order.  */
-in_addr_t
-__inet_addr (const char *cp)
-{
-  struct in_addr val;
-
-  if (__inet_aton (cp, &val))
-    return val.s_addr;
-  return INADDR_NONE;
-}
-weak_alias (__inet_addr, inet_addr)
-
 /* Check whether "cp" is a valid ASCII representation of an IPv4
    Internet address and convert it to a binary address.  Returns 1 if
    the address is valid, 0 if not.  This replaces inet_addr, the
    return value from which cannot distinguish between failure and a
-   local broadcast address.  */
-int
-__inet_aton (const char *cp, struct in_addr *addr)
+   local broadcast address.  Write a pointer to the first
+   non-converted character to *endp.  */
+static int
+inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
 {
   static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
   in_addr_t val;
@@ -180,6 +168,7 @@ __inet_aton (const char *cp, struct in_addr *addr)
 
   if (addr != NULL)
     addr->s_addr = res.word | htonl (val);
+  *endp = cp;
 
   __set_errno (saved_errno);
   return 1;
@@ -188,6 +177,41 @@ __inet_aton (const char *cp, struct in_addr *addr)
   __set_errno (saved_errno);
   return 0;
 }
-weak_alias (__inet_aton, inet_aton)
-libc_hidden_def (__inet_aton)
-libc_hidden_weak (inet_aton)
+
+int
+__inet_aton_exact (const char *cp, struct in_addr *addr)
+{
+  struct in_addr val;
+  const char *endp;
+  /* Check that inet_aton_end parsed the entire string.  */
+  if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0)
+    {
+      *addr = val;
+      return 1;
+    }
+  else
+    return 0;
+}
+libc_hidden_def (__inet_aton_exact)
+
+/* inet_aton ignores trailing garbage.  */
+int
+__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr)
+{
+  const char *endp;
+  return  inet_aton_end (cp, addr, &endp);
+}
+weak_alias (__inet_aton_ignore_trailing, inet_aton)
+
+/* ASCII IPv4 Internet address interpretation routine.  The value
+   returned is in network order.  */
+in_addr_t
+__inet_addr (const char *cp)
+{
+  struct in_addr val;
+  const char *endp;
+  if (inet_aton_end (cp, &val, &endp))
+    return val.s_addr;
+  return INADDR_NONE;
+}
+weak_alias (__inet_addr, inet_addr)