diff --git a/.gitignore b/.gitignore index be9af01..e1f3801 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,8 @@ include/openssl/*.h /apps/ocspcheck/*.h /apps/ocspcheck/*.c /apps/ocspcheck/ocspcheck* +/apps/ocspcheck/compat/inet_ntop.c +/apps/ocspcheck/compat/memmem.c /apps/nc/*.h /apps/nc/*.c diff --git a/apps/ocspcheck/CMakeLists.txt b/apps/ocspcheck/CMakeLists.txt index 87a22d2..5e4639f 100644 --- a/apps/ocspcheck/CMakeLists.txt +++ b/apps/ocspcheck/CMakeLists.txt @@ -11,6 +11,20 @@ set( ocspcheck.c ) +check_function_exists(inet_ntop HAVE_INET_NTOP) +if(HAVE_INET_NTOP) + add_definitions(-DHAVE_INET_NTOP) +else() + set(OCSPCHECK_SRC ${OCSPCHECK_SRC} compat/inet_ntop.c) +endif() + +check_function_exists(inet_ntop HAVE_MEMMEM) +if(HAVE_MEMMEM) + add_definitions(-DHAVE_MEMMEM) +else() + set(OCSPCHECK_SRC ${OCSPCHECK_SRC} compat/memmem.c) +endif() + if(NOT "${OPENSSLDIR}" STREQUAL "") add_definitions(-DDEFAULT_CA_FILE=\"${OPENSSLDIR}/cert.pem\") else() diff --git a/apps/ocspcheck/Makefile.am b/apps/ocspcheck/Makefile.am index 2f6540d..f7eb131 100644 --- a/apps/ocspcheck/Makefile.am +++ b/apps/ocspcheck/Makefile.am @@ -13,3 +13,11 @@ ocspcheck_LDADD += $(PLATFORM_LDADD) $(PROG_LDADD) ocspcheck_SOURCES = http.c ocspcheck_SOURCES += ocspcheck.c noinst_HEADERS = http.h + +if !HAVE_INET_NTOP +ocspcheck_SOURCES += compat/inet_ntop.c +endif + +if !HAVE_MEMMEM +ocspcheck_SOURCES += compat/memmem.c +endif diff --git a/apps/ocspcheck/compat/inet_ntop.c b/apps/ocspcheck/compat/inet_ntop.c new file mode 100644 index 0000000..016d3d7 --- /dev/null +++ b/apps/ocspcheck/compat/inet_ntop.c @@ -0,0 +1,204 @@ +/* $OpenBSD: inet_ntop.c,v 1.12 2015/09/13 21:36:08 guenther Exp $ */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const u_char *src, char *dst, size_t size); +static const char *inet_ntop6(const u_char *src, char *dst, size_t size); + +/* const char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(int af, const void *src, char *dst, socklen_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const u_char *src, char *dst, size_t size) +{ + char tmp[sizeof "255.255.255.255"]; + int l; + + l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u", + src[0], src[1], src[2], src[3]); + if (l <= 0 || l >= size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(const u_char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; + char *tp, *ep; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + int advance; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + ep = tmp + sizeof(tmp); + for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) { + if (tp + 1 >= ep) { + errno = ENOSPC; + return (NULL); + } + *tp++ = ':'; + } + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) { + if (tp + 1 >= ep) { + errno = ENOSPC; + return (NULL); + } + *tp++ = ':'; + } + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, ep - tp)) + return (NULL); + tp += strlen(tp); + break; + } + advance = snprintf(tp, ep - tp, "%x", words[i]); + if (advance <= 0 || advance >= ep - tp) { + errno = ENOSPC; + return (NULL); + } + tp += advance; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { + if (tp + 1 >= ep) { + errno = ENOSPC; + return (NULL); + } + *tp++ = ':'; + } + if (tp + 1 >= ep) { + errno = ENOSPC; + return (NULL); + } + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strlcpy(dst, tmp, size); + return (dst); +} diff --git a/apps/ocspcheck/compat/memmem.c b/apps/ocspcheck/compat/memmem.c new file mode 100644 index 0000000..5793a7d --- /dev/null +++ b/apps/ocspcheck/compat/memmem.c @@ -0,0 +1,63 @@ +/* $OpenBSD: memmem.c,v 1.3 2013/05/30 01:10:45 ajacoutot Exp $ */ +/*- + * Copyright (c) 2005 Pascal Gloor + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* + * Find the first occurrence of the byte string s in byte string l. + */ + +void * +memmem(const void *l, size_t l_len, const void *s, size_t s_len) +{ + const char *cur, *last; + const char *cl = l; + const char *cs = s; + + /* a zero length needle should just return the haystack */ + if (s_len == 0) + return (void *)cl; + + /* "s" must be smaller or equal to "l" */ + if (l_len < s_len) + return NULL; + + /* special case where s_len == 1 */ + if (s_len == 1) + return memchr(l, *cs, l_len); + + /* the last position where its possible to find "s" in "l" */ + last = cl + l_len - s_len; + + for (cur = cl; cur <= last; cur++) + if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) + return (void *)cur; + + return NULL; +} diff --git a/include/compat/arpa/inet.h b/include/compat/arpa/inet.h index 0cea8c4..f14ffde 100644 --- a/include/compat/arpa/inet.h +++ b/include/compat/arpa/inet.h @@ -14,6 +14,10 @@ #endif +#ifndef HAVE_INET_NTOP +const char * inet_ntop(int af, const void *src, char *dst, socklen_t size); +#endif + #ifndef HAVE_INET_PTON int inet_pton(int af, const char * src, void * dst); #endif diff --git a/m4/check-libc.m4 b/m4/check-libc.m4 index 73ff4e6..c66364e 100644 --- a/m4/check-libc.m4 +++ b/m4/check-libc.m4 @@ -2,10 +2,11 @@ AC_DEFUN([CHECK_LIBC_COMPAT], [ # Check for libc headers AC_CHECK_HEADERS([err.h readpassphrase.h]) # Check for general libc functions -AC_CHECK_FUNCS([asprintf inet_pton memmem readpassphrase reallocarray]) -AC_CHECK_FUNCS([strlcat strlcpy strndup strnlen strsep strtonum]) +AC_CHECK_FUNCS([asprintf inet_ntop inet_pton memmem readpassphrase]) +AC_CHECK_FUNCS([reallocarray strlcat strlcpy strndup strnlen strsep strtonum]) AC_CHECK_FUNCS([timegm _mkgmtime]) AM_CONDITIONAL([HAVE_ASPRINTF], [test "x$ac_cv_func_asprintf" = xyes]) +AM_CONDITIONAL([HAVE_INET_NTOP], [test "x$ac_cv_func_inet_ntop" = xyes]) AM_CONDITIONAL([HAVE_INET_PTON], [test "x$ac_cv_func_inet_pton" = xyes]) AM_CONDITIONAL([HAVE_MEMMEM], [test "x$ac_cv_func_memmem" = xyes]) AM_CONDITIONAL([HAVE_READPASSPHRASE], [test "x$ac_cv_func_readpassphrase" = xyes]) diff --git a/update.sh b/update.sh index 0c51b43..dcc7548 100755 --- a/update.sh +++ b/update.sh @@ -228,6 +228,8 @@ done echo "copying ocspcheck(1) source" $CP $sbin_src/ocspcheck/ocspcheck.8 apps/ocspcheck rm -f apps/ocspcheck/*.c apps/ocspcheck/*.h +$CP_LIBC $libc_src/net/inet_ntop.c apps/ocspcheck/compat +$CP_LIBC $libc_src/string/memmem.c apps/ocspcheck/compat for i in `awk '/SOURCES|HEADERS|MANS/ { print $3 }' apps/ocspcheck/Makefile.am` ; do if [ -e $sbin_src/ocspcheck/$i ]; then $CP $sbin_src/ocspcheck/$i apps/ocspcheck