1From f22cc01039b6473b736d3bf438f56a2654cdf2b2 Mon Sep 17 00:00:00 2001 2From: Brad House <brad@brad-house.com> 3Date: Mon, 22 May 2023 06:51:34 -0400 4Subject: [PATCH] Merge pull request from GHSA-x6mf-cxr9-8q6v 5 6* Merged latest OpenBSD changes for inet_net_pton_ipv6() into c-ares. 7* Always use our own IP conversion functions now, do not delegate to OS 8 so we can have consistency in testing and fuzzing. 9* Removed bogus test cases that never should have passed. 10* Add new test case for crash bug found. 11 12Fix By: Brad House (@bradh352) 13--- 14 src/lib/inet_net_pton.c | 155 ++++++++++++++++++++----------------- 15 test/ares-test-internal.cc | 7 +- 16 2 files changed, 86 insertions(+), 76 deletions(-) 17 18diff --git a/src/lib/inet_net_pton.c b/src/lib/inet_net_pton.c 19index 840de50..fc50425 100644 20--- a/src/lib/inet_net_pton.c 21+++ b/src/lib/inet_net_pton.c 22@@ -1,19 +1,20 @@ 23 24 /* 25- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 26+ * Copyright (c) 2012 by Gilles Chehade <gilles@openbsd.org> 27 * Copyright (c) 1996,1999 by Internet Software Consortium. 28 * 29 * Permission to use, copy, modify, and distribute this software for any 30 * purpose with or without fee is hereby granted, provided that the above 31 * copyright notice and this permission notice appear in all copies. 32 * 33- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 34- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 35- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 36- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 37- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 38- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 39- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 40+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 41+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 42+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 43+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 44+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 47+ * SOFTWARE. 48 */ 49 50 #include "ares_setup.h" 51@@ -35,9 +36,6 @@ 52 53 const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; 54 55- 56-#ifndef HAVE_INET_NET_PTON 57- 58 /* 59 * static int 60 * inet_net_pton_ipv4(src, dst, size) 61@@ -60,7 +58,7 @@ const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0, 62 * Paul Vixie (ISC), June 1996 63 */ 64 static int 65-inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size) 66+ares_inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size) 67 { 68 static const char xdigits[] = "0123456789abcdef"; 69 static const char digits[] = "0123456789"; 70@@ -261,19 +259,14 @@ getv4(const char *src, unsigned char *dst, int *bitsp) 71 } 72 73 static int 74-inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size) 75+ares_inet_pton6(const char *src, unsigned char *dst) 76 { 77 static const char xdigits_l[] = "0123456789abcdef", 78- xdigits_u[] = "0123456789ABCDEF"; 79+ xdigits_u[] = "0123456789ABCDEF"; 80 unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; 81 const char *xdigits, *curtok; 82- int ch, saw_xdigit; 83+ int ch, saw_xdigit, count_xdigit; 84 unsigned int val; 85- int digits; 86- int bits; 87- size_t bytes; 88- int words; 89- int ipv4; 90 91 memset((tp = tmp), '\0', NS_IN6ADDRSZ); 92 endp = tp + NS_IN6ADDRSZ; 93@@ -283,22 +276,22 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size) 94 if (*++src != ':') 95 goto enoent; 96 curtok = src; 97- saw_xdigit = 0; 98+ saw_xdigit = count_xdigit = 0; 99 val = 0; 100- digits = 0; 101- bits = -1; 102- ipv4 = 0; 103 while ((ch = *src++) != '\0') { 104 const char *pch; 105 106 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) 107 pch = strchr((xdigits = xdigits_u), ch); 108 if (pch != NULL) { 109+ if (count_xdigit >= 4) 110+ goto enoent; 111 val <<= 4; 112- val |= aresx_sztoui(pch - xdigits); 113- if (++digits > 4) 114+ val |= (pch - xdigits); 115+ if (val > 0xffff) 116 goto enoent; 117 saw_xdigit = 1; 118+ count_xdigit++; 119 continue; 120 } 121 if (ch == ':') { 122@@ -308,78 +301,107 @@ inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size) 123 goto enoent; 124 colonp = tp; 125 continue; 126- } else if (*src == '\0') 127+ } else if (*src == '\0') { 128 goto enoent; 129+ } 130 if (tp + NS_INT16SZ > endp) 131- return (0); 132- *tp++ = (unsigned char)((val >> 8) & 0xff); 133- *tp++ = (unsigned char)(val & 0xff); 134+ goto enoent; 135+ *tp++ = (unsigned char) (val >> 8) & 0xff; 136+ *tp++ = (unsigned char) val & 0xff; 137 saw_xdigit = 0; 138- digits = 0; 139+ count_xdigit = 0; 140 val = 0; 141 continue; 142 } 143 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && 144- getv4(curtok, tp, &bits) > 0) { 145- tp += NS_INADDRSZ; 146+ ares_inet_net_pton_ipv4(curtok, tp, INADDRSZ) > 0) { 147+ tp += INADDRSZ; 148 saw_xdigit = 0; 149- ipv4 = 1; 150+ count_xdigit = 0; 151 break; /* '\0' was seen by inet_pton4(). */ 152 } 153- if (ch == '/' && getbits(src, &bits) > 0) 154- break; 155 goto enoent; 156 } 157 if (saw_xdigit) { 158 if (tp + NS_INT16SZ > endp) 159 goto enoent; 160- *tp++ = (unsigned char)((val >> 8) & 0xff); 161- *tp++ = (unsigned char)(val & 0xff); 162+ *tp++ = (unsigned char) (val >> 8) & 0xff; 163+ *tp++ = (unsigned char) val & 0xff; 164 } 165- if (bits == -1) 166- bits = 128; 167- 168- words = (bits + 15) / 16; 169- if (words < 2) 170- words = 2; 171- if (ipv4) 172- words = 8; 173- endp = tmp + 2 * words; 174- 175 if (colonp != NULL) { 176 /* 177 * Since some memmove()'s erroneously fail to handle 178 * overlapping regions, we'll do the shift by hand. 179 */ 180- const ares_ssize_t n = tp - colonp; 181- ares_ssize_t i; 182+ const int n = tp - colonp; 183+ int i; 184 185 if (tp == endp) 186 goto enoent; 187 for (i = 1; i <= n; i++) { 188- *(endp - i) = *(colonp + n - i); 189- *(colonp + n - i) = 0; 190+ endp[- i] = colonp[n - i]; 191+ colonp[n - i] = 0; 192 } 193 tp = endp; 194 } 195 if (tp != endp) 196 goto enoent; 197 198- bytes = (bits + 7) / 8; 199- if (bytes > size) 200- goto emsgsize; 201- memcpy(dst, tmp, bytes); 202- return (bits); 203+ memcpy(dst, tmp, NS_IN6ADDRSZ); 204+ return (1); 205 206- enoent: 207+enoent: 208 SET_ERRNO(ENOENT); 209 return (-1); 210 211- emsgsize: 212+emsgsize: 213 SET_ERRNO(EMSGSIZE); 214 return (-1); 215 } 216 217+static int 218+ares_inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size) 219+{ 220+ struct ares_in6_addr in6; 221+ int ret; 222+ int bits; 223+ size_t bytes; 224+ char buf[INET6_ADDRSTRLEN + sizeof("/128")]; 225+ char *sep; 226+ const char *errstr; 227+ 228+ if (strlen(src) >= sizeof buf) { 229+ SET_ERRNO(EMSGSIZE); 230+ return (-1); 231+ } 232+ strncpy(buf, src, sizeof buf); 233+ 234+ sep = strchr(buf, '/'); 235+ if (sep != NULL) 236+ *sep++ = '\0'; 237+ 238+ ret = ares_inet_pton6(buf, (unsigned char *)&in6); 239+ if (ret != 1) 240+ return (-1); 241+ 242+ if (sep == NULL) 243+ bits = 128; 244+ else { 245+ if (!getbits(sep, &bits)) { 246+ SET_ERRNO(ENOENT); 247+ return (-1); 248+ } 249+ } 250+ 251+ bytes = (bits + 7) / 8; 252+ if (bytes > size) { 253+ SET_ERRNO(EMSGSIZE); 254+ return (-1); 255+ } 256+ memcpy(dst, &in6, bytes); 257+ return (bits); 258+} 259+ 260 /* 261 * int 262 * inet_net_pton(af, src, dst, size) 263@@ -403,18 +425,15 @@ ares_inet_net_pton(int af, const char *src, void *dst, size_t size) 264 { 265 switch (af) { 266 case AF_INET: 267- return (inet_net_pton_ipv4(src, dst, size)); 268+ return (ares_inet_net_pton_ipv4(src, dst, size)); 269 case AF_INET6: 270- return (inet_net_pton_ipv6(src, dst, size)); 271+ return (ares_inet_net_pton_ipv6(src, dst, size)); 272 default: 273 SET_ERRNO(EAFNOSUPPORT); 274 return (-1); 275 } 276 } 277 278-#endif /* HAVE_INET_NET_PTON */ 279- 280-#ifndef HAVE_INET_PTON 281 int ares_inet_pton(int af, const char *src, void *dst) 282 { 283 int result; 284@@ -434,11 +453,3 @@ int ares_inet_pton(int af, const char *src, void *dst) 285 return 0; 286 return (result > -1 ? 1 : -1); 287 } 288-#else /* HAVE_INET_PTON */ 289-int ares_inet_pton(int af, const char *src, void *dst) 290-{ 291- /* just relay this to the underlying function */ 292- return inet_pton(af, src, dst); 293-} 294- 295-#endif 296diff --git a/test/ares-test-internal.cc b/test/ares-test-internal.cc 297index 1cb7e42..40cc82b 100644 298--- a/test/ares-test-internal.cc 299+++ b/test/ares-test-internal.cc 300@@ -123,6 +123,7 @@ TEST_F(LibraryTest, InetPtoN) { 301 EXPECT_EQ(0, ares_inet_net_pton(AF_INET6, "12:34::ff/0", &a6, sizeof(a6))); 302 EXPECT_EQ(16 * 8, ares_inet_net_pton(AF_INET6, "12:34::ffff:0.2", &a6, sizeof(a6))); 303 EXPECT_EQ(16 * 8, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234", &a6, sizeof(a6))); 304+ EXPECT_EQ(2, ares_inet_net_pton(AF_INET6, "0::00:00:00/2", &a6, sizeof(a6))); 305 306 // Various malformed versions 307 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET, "", &a4, sizeof(a4))); 308@@ -160,11 +161,9 @@ TEST_F(LibraryTest, InetPtoN) { 309 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, ":1234:1234:1234:1234:1234:1234:1234:1234", &a6, sizeof(a6))); 310 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, ":1234:1234:1234:1234:1234:1234:1234:1234:", &a6, sizeof(a6))); 311 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678", &a6, sizeof(a6))); 312- // TODO(drysdale): check whether the next two tests should give -1. 313- EXPECT_EQ(0, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678", &a6, sizeof(a6))); 314- EXPECT_EQ(0, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678:5678", &a6, sizeof(a6))); 315+ EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678", &a6, sizeof(a6))); 316+ EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "1234:1234:1234:1234:1234:1234:1234:1234:5678:5678:5678", &a6, sizeof(a6))); 317 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:257.2.3.4", &a6, sizeof(a6))); 318- EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:002.2.3.4", &a6, sizeof(a6))); 319 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:1.2.3.4.5.6", &a6, sizeof(a6))); 320 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:1.2.3.4.5", &a6, sizeof(a6))); 321 EXPECT_EQ(-1, ares_inet_net_pton(AF_INET6, "12:34::ffff:1.2.3.z", &a6, sizeof(a6))); 322-- 3232.27.0 324 325