]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/BaseCryptLib/SysCall/inet_pton.c
CryptoPkg/Crt: import "inet_pton.c" (CVE-2019-14553)
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / SysCall / inet_pton.c
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/inet_pton.c b/CryptoPkg/Library/BaseCryptLib/SysCall/inet_pton.c
new file mode 100644 (file)
index 0000000..32e1ab8
--- /dev/null
@@ -0,0 +1,257 @@
+/* Copyright (c) 1996 by Internet Software Consortium.\r
+ *\r
+ * Permission to use, copy, modify, and distribute this software for any\r
+ * purpose with or without fee is hereby granted, provided that the above\r
+ * copyright notice and this permission notice appear in all copies.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS\r
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES\r
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE\r
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\r
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\r
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS\r
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
+ * SOFTWARE.\r
+ */\r
+\r
+/*\r
+ * Portions copyright (c) 1999, 2000\r
+ * Intel Corporation.\r
+ * All rights reserved.\r
+ * \r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ * \r
+ * 1. Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ * \r
+ * 2. Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ * \r
+ * 3. All advertising materials mentioning features or use of this software\r
+ *    must display the following acknowledgement:\r
+ * \r
+ *    This product includes software developed by Intel Corporation and\r
+ *    its contributors.\r
+ * \r
+ * 4. Neither the name of Intel Corporation or its contributors may be\r
+ *    used to endorse or promote products derived from this software\r
+ *    without specific prior written permission.\r
+ * \r
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ * ARE DISCLAIMED.  IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE\r
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r
+ * THE POSSIBILITY OF SUCH DAMAGE.\r
+ * \r
+ */\r
+\r
+#if defined(LIBC_SCCS) && !defined(lint)\r
+static char rcsid[] = "$Id: inet_pton.c,v 1.1.1.1 2003/11/19 01:51:30 kyu3 Exp $";\r
+#endif /* LIBC_SCCS and not lint */\r
+\r
+#include <sys/param.h>\r
+#include <sys/types.h>\r
+#include <sys/socket.h>\r
+#include <netinet/in.h>\r
+#include <arpa/inet.h>\r
+#include <arpa/nameser.h>\r
+#include <string.h>\r
+#include <errno.h>\r
+\r
+/*\r
+ * WARNING: Don't even consider trying to compile this on a system where\r
+ * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.\r
+ */\r
+\r
+static int     inet_pton4 (const char *src, u_char *dst);\r
+static int     inet_pton6 (const char *src, u_char *dst);\r
+\r
+/* int\r
+ * inet_pton(af, src, dst)\r
+ *     convert from presentation format (which usually means ASCII printable)\r
+ *     to network format (which is usually some kind of binary format).\r
+ * return:\r
+ *     1 if the address was valid for the specified address family\r
+ *     0 if the address wasn't valid (`dst' is untouched in this case)\r
+ *     -1 if some other error occurred (`dst' is untouched in this case, too)\r
+ * author:\r
+ *     Paul Vixie, 1996.\r
+ */\r
+int\r
+inet_pton(\r
+       int af,\r
+       const char *src,\r
+       void *dst\r
+       )\r
+{\r
+       switch (af) {\r
+       case AF_INET:\r
+               return (inet_pton4(src, dst));\r
+       case AF_INET6:\r
+               return (inet_pton6(src, dst));\r
+       default:\r
+               errno = EAFNOSUPPORT;\r
+               return (-1);\r
+       }\r
+       /* NOTREACHED */\r
+}\r
+\r
+/* int\r
+ * inet_pton4(src, dst)\r
+ *     like inet_aton() but without all the hexadecimal and shorthand.\r
+ * return:\r
+ *     1 if `src' is a valid dotted quad, else 0.\r
+ * notice:\r
+ *     does not touch `dst' unless it's returning 1.\r
+ * author:\r
+ *     Paul Vixie, 1996.\r
+ */\r
+static int\r
+inet_pton4(\r
+       const char *src,\r
+       u_char *dst\r
+       )\r
+{\r
+       static const char digits[] = "0123456789";\r
+       int saw_digit, octets, ch;\r
+       u_char tmp[NS_INADDRSZ], *tp;\r
+\r
+       saw_digit = 0;\r
+       octets = 0;\r
+       *(tp = tmp) = 0;\r
+       while ((ch = *src++) != '\0') {\r
+               const char *pch;\r
+\r
+               if ((pch = strchr(digits, ch)) != NULL) {\r
+                       u_int new = *tp * 10 + (u_int)(pch - digits);\r
+\r
+                       if (new > 255)\r
+                               return (0);\r
+                       *tp = (u_char)new;\r
+                       if (! saw_digit) {\r
+                               if (++octets > 4)\r
+                                       return (0);\r
+                               saw_digit = 1;\r
+                       }\r
+               } else if (ch == '.' && saw_digit) {\r
+                       if (octets == 4)\r
+                               return (0);\r
+                       *++tp = 0;\r
+                       saw_digit = 0;\r
+               } else\r
+                       return (0);\r
+       }\r
+       if (octets < 4)\r
+               return (0);\r
+\r
+       memcpy(dst, tmp, NS_INADDRSZ);\r
+       return (1);\r
+}\r
+\r
+/* int\r
+ * inet_pton6(src, dst)\r
+ *     convert presentation level address to network order binary form.\r
+ * return:\r
+ *     1 if `src' is a valid [RFC1884 2.2] address, else 0.\r
+ * notice:\r
+ *     (1) does not touch `dst' unless it's returning 1.\r
+ *     (2) :: in a full address is silently ignored.\r
+ * credit:\r
+ *     inspired by Mark Andrews.\r
+ * author:\r
+ *     Paul Vixie, 1996.\r
+ */\r
+static int\r
+inet_pton6(\r
+       const char *src,\r
+       u_char *dst\r
+       )\r
+{\r
+       static const char xdigits_l[] = "0123456789abcdef",\r
+                         xdigits_u[] = "0123456789ABCDEF";\r
+       u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;\r
+       const char *xdigits, *curtok;\r
+       int ch, saw_xdigit;\r
+       u_int val;\r
+\r
+       memset((tp = tmp), '\0', NS_IN6ADDRSZ);\r
+       endp = tp + NS_IN6ADDRSZ;\r
+       colonp = NULL;\r
+       /* Leading :: requires some special handling. */\r
+       if (*src == ':')\r
+               if (*++src != ':')\r
+                       return (0);\r
+       curtok = src;\r
+       saw_xdigit = 0;\r
+       val = 0;\r
+       while ((ch = *src++) != '\0') {\r
+               const char *pch;\r
+\r
+               if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)\r
+                       pch = strchr((xdigits = xdigits_u), ch);\r
+               if (pch != NULL) {\r
+                       val <<= 4;\r
+                       val |= (pch - xdigits);\r
+                       if (val > 0xffff)\r
+                               return (0);\r
+                       saw_xdigit = 1;\r
+                       continue;\r
+               }\r
+               if (ch == ':') {\r
+                       curtok = src;\r
+                       if (!saw_xdigit) {\r
+                               if (colonp)\r
+                                       return (0);\r
+                               colonp = tp;\r
+                               continue;\r
+                       }\r
+                       if (tp + NS_INT16SZ > endp)\r
+                               return (0);\r
+                       *tp++ = (u_char) (val >> 8) & 0xff;\r
+                       *tp++ = (u_char) val & 0xff;\r
+                       saw_xdigit = 0;\r
+                       val = 0;\r
+                       continue;\r
+               }\r
+               if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&\r
+                   inet_pton4(curtok, tp) > 0) {\r
+                       tp += NS_INADDRSZ;\r
+                       saw_xdigit = 0;\r
+                       break;  /* '\0' was seen by inet_pton4(). */\r
+               }\r
+               return (0);\r
+       }\r
+       if (saw_xdigit) {\r
+               if (tp + NS_INT16SZ > endp)\r
+                       return (0);\r
+               *tp++ = (u_char) (val >> 8) & 0xff;\r
+               *tp++ = (u_char) val & 0xff;\r
+       }\r
+       if (colonp != NULL) {\r
+               /*\r
+                * Since some memmove()'s erroneously fail to handle\r
+                * overlapping regions, we'll do the shift by hand.\r
+                */\r
+               const int n = (int)(tp - colonp);\r
+               int i;\r
+\r
+               for (i = 1; i <= n; i++) {\r
+                       endp[- i] = colonp[n - i];\r
+                       colonp[n - i] = 0;\r
+               }\r
+               tp = endp;\r
+       }\r
+       if (tp != endp)\r
+               return (0);\r
+       memcpy(dst, tmp, NS_IN6ADDRSZ);\r
+       return (1);\r
+}\r