From 0af7f64094c65cba7ee45bd2679e6826bcf598cb Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Iniesta Date: Wed, 16 Apr 2014 17:32:08 +0200 Subject: Imported Upstream version 2.3.3 --- ChangeLog | 84 +++++++++ INSTALL | 2 - config.h.in | 11 +- configure | 88 +++------ configure.ac | 22 +-- distro/rpm/openvpn.spec | 2 +- doc/openvpn.8 | 78 +++++++- include/openvpn-plugin.h | 25 ++- ltmain.sh | 4 +- m4/libtool.m4 | 28 +-- sample/sample-plugins/log/build | 2 +- sample/sample-plugins/log/log_v3.c | 5 + src/openvpn/buffer.c | 29 ++- src/openvpn/init.c | 4 +- src/openvpn/misc.c | 27 +-- src/openvpn/openvpn.c | 2 +- src/openvpn/options.c | 206 +++++++++++++++++---- src/openvpn/options.h | 3 + src/openvpn/pkcs11_openssl.c | 14 +- src/openvpn/plugin.c | 5 +- src/openvpn/push.c | 4 +- src/openvpn/route.c | 131 ++------------ src/openvpn/route.h | 10 +- src/openvpn/socket.c | 14 +- src/openvpn/ssl.c | 69 ++++--- src/openvpn/ssl_backend.h | 66 ++++--- src/openvpn/ssl_common.h | 4 +- src/openvpn/ssl_openssl.c | 143 ++++++++++++--- src/openvpn/ssl_openssl.h | 12 ++ src/openvpn/ssl_polarssl.c | 242 ++++++++++++++++++++++--- src/openvpn/ssl_polarssl.h | 5 + src/openvpn/ssl_verify.c | 2 - src/openvpn/syshead.h | 2 +- src/openvpn/tun.c | 361 +++++++++++++++++++++++++++++-------- src/openvpn/tun.h | 3 + src/openvpn/win32.c | 34 ++-- tests/t_client.sh | 8 +- tests/t_client.sh.in | 2 +- version.m4 | 4 +- 39 files changed, 1260 insertions(+), 497 deletions(-) diff --git a/ChangeLog b/ChangeLog index d451877..112a3b2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,90 @@ OpenVPN Change Log Copyright (C) 2002-2012 OpenVPN Technologies, Inc. +2014.04.08 -- Version 2.3.3 +Alon Bar-Lev (1): + pkcs11: use generic evp key instead of rsa + +Arne Schwabe (8): + Add support of utun devices under Mac OS X + Add support to ignore specific options. + Add a note what setenv opt does for OpenVPN < 2.3.3 + Add reporting of UI version to basic push-peer-info set. + Fix compile error in ssl_openssl introduced by polar external-management patch + Fix assertion when SIGUSR1 is received while getaddrinfo is successful + Add warning for using connection block variables after connection blocks + Introduce safety check for http proxy options + +David Sommerseth (5): + man page: Update man page about the tls_digest_{n} environment variable + Remove the --disable-eurephia configure option + plugin: Extend the plug-in v3 API to identify the SSL implementation used + autoconf: Fix typo + Fix file checks when --chroot is being used + +Davide Brini (1): + Document authfile for socks server + +Gert Doering (9): + Fix IPv6 examples in t_client.rc-sample + Fix slow memory drain on each client renegotiation. + t_client.sh: ignore fields from "ip -6 route show" output that distort results. + Make code and documentation for --remote-random-hostname consistent. + Reduce IV_OPENVPN_GUI_VERSION= to IV_GUI_VER= + Document issue with --chroot, /dev/urandom and PolarSSL. + Rename 'struct route' to 'struct route_ipv4' + Replace copied structure elements with including + Workaround missing SSL_OP_NO_TICKET in earlier OpenSSL versions + +Heikki Hannikainen (1): + Always load intermediate certificates from a PKCS#12 file + +Heiko Hund (2): + Support non-ASCII TAP adapter names on Windows + Support non-ASCII characters in Windows tmp path + +James Yonan (3): + TLS version negotiation + Added "setenv opt" directive prefix. + Set SSL_OP_NO_TICKET flag in SSL context for OpenSSL builds, to disable TLS stateless session resumption. + +Jens Wagner (1): + Fix spurious ignoring of pushed config options (trac#349). + +Joachim Schipper (3): + Refactor tls_ctx_use_external_private_key() + --management-external-key for PolarSSL + external_pkcs1_sign: Support non-RSA_SIG_RAW hash_ids + +Josh Cepek (2): + Correct error text when no Windows TAP device is present + Require a 1.2.x PolarSSL version + +Klee Dienes (1): + tls_ctx_load_ca: Improve certificate error messages + +Max Muster (1): + Remove duplicate cipher entries from TLS translation table. + +Peter Sagerson (1): + Fix configure interaction with static OpenSSL libraries + +Steffan Karger (7): + Do not pass struct tls_session* as void* in key_state_ssl_init(). + Require polarssl >= 1.2.10 for polarssl-builds, which fixes CVE-2013-5915. + Use RSA_generate_key_ex() instead of deprecated, RSA_generate_key() + Also update TLSv1_method() calls in support code to SSLv23_method() calls. + Update TLSv1 error messages to SSLv23 to reflect changes from commit 4b67f98 + If --tls-cipher is supplied, make --show-tls parse the list. + Add openssl-specific common cipher list names to ssl.c. + +Tamas TEVESZ (1): + Add support for client-cert-not-required for PolarSSL. + +Thomas Veerman (1): + Fix "." in description of utun. + + 2013.05.31 -- Version 2.3.2 Arne Schwabe (3): Only print script warnings when a script is used. Remove stray mention of script-security system. diff --git a/INSTALL b/INSTALL index ed69667..61dc975 100644 --- a/INSTALL +++ b/INSTALL @@ -169,8 +169,6 @@ OPTIONS for ./configure: --disable-server disable server support only (but retain client support) [default=yes] --disable-plugins disable plug-in support [default=yes] - --disable-eurephia disable support for the eurephia plug-in - [default=yes] --disable-management disable management server support [default=yes] --enable-pkcs11 enable pkcs11 support [default=no] --disable-socks disable Socks support [default=yes] diff --git a/config.h.in b/config.h.in index 68fec17..1817b2b 100644 --- a/config.h.in +++ b/config.h.in @@ -36,9 +36,6 @@ /* Enable deferred authentication */ #undef ENABLE_DEF_AUTH -/* Enable support for the eurephia plug-in */ -#undef ENABLE_EUREPHIA - /* We have persist tun capability */ #undef ENABLE_FEATURE_TUN_PERSIST @@ -72,7 +69,7 @@ /* Enable PKCS11 */ #undef ENABLE_PKCS11 -/* Enable systemd support */ +/* Enable plug-in support */ #undef ENABLE_PLUGIN /* Enable TCP Server port sharing */ @@ -355,6 +352,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_TUN_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_UTUN_H + /* Define to 1 if you have the header file. */ #undef HAVE_NET_TUN_IF_TUN_H @@ -481,6 +481,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_KERN_CONTROL_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MMAN_H diff --git a/configure b/configure index e1f1c8e..0cb3262 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for OpenVPN 2.3.2. +# Generated by GNU Autoconf 2.69 for OpenVPN 2.3.3. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='OpenVPN' PACKAGE_TARNAME='openvpn' -PACKAGE_VERSION='2.3.2' -PACKAGE_STRING='OpenVPN 2.3.2' +PACKAGE_VERSION='2.3.3' +PACKAGE_STRING='OpenVPN 2.3.3' PACKAGE_BUGREPORT='openvpn-users@lists.sourceforge.net' PACKAGE_URL='' @@ -806,7 +806,6 @@ enable_x509_alt_username enable_multi enable_server enable_plugins -enable_eurephia enable_management enable_pkcs11 enable_socks @@ -1411,7 +1410,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures OpenVPN 2.3.2 to adapt to many kinds of systems. +\`configure' configures OpenVPN 2.3.3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1481,7 +1480,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OpenVPN 2.3.2:";; + short | recursive ) echo "Configuration of OpenVPN 2.3.3:";; esac cat <<\_ACEOF @@ -1506,8 +1505,6 @@ Optional Features: --disable-server disable server support only (but retain client support) [default=yes] --disable-plugins disable plug-in support [default=yes] - --disable-eurephia disable support for the eurephia plug-in - [default=yes] --disable-management disable management server support [default=yes] --enable-pkcs11 enable pkcs11 support [default=no] --disable-socks disable Socks support [default=yes] @@ -1672,7 +1669,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OpenVPN configure 2.3.2 +OpenVPN configure 2.3.3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2454,7 +2451,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by OpenVPN $as_me 2.3.2, which was +It was created by OpenVPN $as_me 2.3.3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2818,7 +2815,7 @@ if test -z "${htmldir}"; then fi -$as_echo "#define OPENVPN_VERSION_RESOURCE 2,3,2,0" >>confdefs.h +$as_echo "#define OPENVPN_VERSION_RESOURCE 2,3,3,0" >>confdefs.h ac_aux_dir= @@ -3292,7 +3289,7 @@ fi # Define the identity of the package. PACKAGE='openvpn' - VERSION='2.3.2' + VERSION='2.3.3' cat >>confdefs.h <<_ACEOF @@ -4915,15 +4912,6 @@ else fi -# Check whether --enable-eurephia was given. -if test "${enable_eurephia+set}" = set; then : - enableval=$enable_eurephia; -else - enable_eurephia="yes" - -fi - - # Check whether --enable-management was given. if test "${enable_management+set}" = set; then : enableval=$enable_management; @@ -7011,10 +6999,6 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -7053,7 +7037,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -10007,7 +9991,7 @@ lt_prog_compiler_static= lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) @@ -12177,17 +12161,6 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no @@ -12304,7 +12277,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no @@ -14228,7 +14201,7 @@ SOCKET_INCLUDES=" #endif " -for ac_header in net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h +for ac_header in net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h net/if_utun.h sys/kern_control.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "${SOCKET_INCLUDES} @@ -15249,12 +15222,12 @@ if test -n "$PKCS11_HELPER_CFLAGS"; then pkg_cv_PKCS11_HELPER_CFLAGS="$PKCS11_HELPER_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpkcs11-helper-1 >= 1.02\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libpkcs11-helper-1 >= 1.02") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpkcs11-helper-1 >= 1.11\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpkcs11-helper-1 >= 1.11") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_PKCS11_HELPER_CFLAGS=`$PKG_CONFIG --cflags "libpkcs11-helper-1 >= 1.02" 2>/dev/null` + pkg_cv_PKCS11_HELPER_CFLAGS=`$PKG_CONFIG --cflags "libpkcs11-helper-1 >= 1.11" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15266,12 +15239,12 @@ if test -n "$PKCS11_HELPER_LIBS"; then pkg_cv_PKCS11_HELPER_LIBS="$PKCS11_HELPER_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpkcs11-helper-1 >= 1.02\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libpkcs11-helper-1 >= 1.02") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpkcs11-helper-1 >= 1.11\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libpkcs11-helper-1 >= 1.11") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_PKCS11_HELPER_LIBS=`$PKG_CONFIG --libs "libpkcs11-helper-1 >= 1.02" 2>/dev/null` + pkg_cv_PKCS11_HELPER_LIBS=`$PKG_CONFIG --libs "libpkcs11-helper-1 >= 1.11" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -15292,9 +15265,9 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - PKCS11_HELPER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpkcs11-helper-1 >= 1.02" 2>&1` + PKCS11_HELPER_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpkcs11-helper-1 >= 1.11" 2>&1` else - PKCS11_HELPER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpkcs11-helper-1 >= 1.02" 2>&1` + PKCS11_HELPER_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpkcs11-helper-1 >= 1.11" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$PKCS11_HELPER_PKG_ERRORS" >&5 @@ -15539,7 +15512,8 @@ if ${ac_cv_lib_ssl_SSL_CTX_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lssl $LIBS" +LIBS="-lssl -lcrypto + $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15574,7 +15548,6 @@ if test "x$ac_cv_lib_ssl_SSL_CTX_new" = xyes; then : have_openssl_ssl="yes" OPENSSL_SSL_LIBS="-lssl" - fi @@ -15587,7 +15560,8 @@ if ${ac_cv_lib_ssl_SSL_CTX_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lssl $LIBS" +LIBS="-lssl -lcrypto + $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -15622,7 +15596,6 @@ if test "x$ac_cv_lib_ssl_SSL_CTX_new" = xyes; then : have_openssl_ssl="yes" OPENSSL_SSL_LIBS="-lssl" - fi @@ -15789,7 +15762,7 @@ int main () { -#if POLARSSL_VERSION_NUMBER < 0x01020500 +#if POLARSSL_VERSION_NUMBER < 0x01020A00 || POLARSSL_VERSION_NUMBER >= 0x01030000 #error invalid version #endif @@ -15802,7 +15775,7 @@ if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else - as_fn_error $? "PolarSSL 1.2.5 or newer required" "$LINENO" 5 + as_fn_error $? "PolarSSL 1.2.x required and must be 1.2.10 or later" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext @@ -16151,9 +16124,6 @@ if test "${enable_plugins}" = "yes"; then $as_echo "#define ENABLE_PLUGIN 1" >>confdefs.h - test "${enable_eurephia}" = "yes" && -$as_echo "#define ENABLE_EUREPHIA 1" >>confdefs.h - else enable_plugin_auth_pam="no" enable_plugin_down_root="no" @@ -16854,7 +16824,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by OpenVPN $as_me 2.3.2, which was +This file was extended by OpenVPN $as_me 2.3.3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16920,7 +16890,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -OpenVPN config.status 2.3.2 +OpenVPN config.status 2.3.3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 7b35e50..6ad8ff4 100644 --- a/configure.ac +++ b/configure.ac @@ -95,13 +95,6 @@ AC_ARG_ENABLE( [enable_plugins="yes"] ) -AC_ARG_ENABLE( - [eurephia], - [AS_HELP_STRING([--disable-eurephia], [disable support for the eurephia plug-in @<:@default=yes@:>@])], - , - [enable_eurephia="yes"] -) - AC_ARG_ENABLE( [management], [AS_HELP_STRING([--disable-management], [disable management server support @<:@default=yes@:>@])], @@ -454,7 +447,7 @@ SOCKET_INCLUDES=" " AC_CHECK_HEADERS( - [net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h], + [net/if.h netinet/ip.h netinet/if_ether.h resolv.h sys/un.h net/if_utun.h sys/kern_control.h], , , [[${SOCKET_INCLUDES}]] @@ -727,7 +720,7 @@ esac PKG_CHECK_MODULES( [PKCS11_HELPER], - [libpkcs11-helper-1 >= 1.02], + [libpkcs11-helper-1 >= 1.11], [have_pkcs11_helper="yes"], [] ) @@ -756,7 +749,9 @@ PKG_CHECK_MODULES( [ have_openssl_ssl="yes" OPENSSL_SSL_LIBS="-lssl" - ] + ], + [], + [-lcrypto] )] ) @@ -814,13 +809,13 @@ if test "${with_crypto_library}" = "polarssl" ; then #include ]], [[ -#if POLARSSL_VERSION_NUMBER < 0x01020500 +#if POLARSSL_VERSION_NUMBER < 0x01020A00 || POLARSSL_VERSION_NUMBER >= 0x01030000 #error invalid version #endif ]] )], [AC_MSG_RESULT([ok])], - [AC_MSG_ERROR([PolarSSL 1.2.5 or newer required])] + [AC_MSG_ERROR([PolarSSL 1.2.x required and must be 1.2.10 or later])] ) polarssl_with_pkcs11="no" @@ -974,8 +969,7 @@ fi if test "${enable_plugins}" = "yes"; then OPTIONAL_DL_LIBS="${DL_LIBS}" - AC_DEFINE([ENABLE_PLUGIN], [1], [Enable systemd support]) - test "${enable_eurephia}" = "yes" && AC_DEFINE([ENABLE_EUREPHIA], [1], [Enable support for the eurephia plug-in]) + AC_DEFINE([ENABLE_PLUGIN], [1], [Enable plug-in support]) else enable_plugin_auth_pam="no" enable_plugin_down_root="no" diff --git a/distro/rpm/openvpn.spec b/distro/rpm/openvpn.spec index 5d70164..6af9d26 100644 --- a/distro/rpm/openvpn.spec +++ b/distro/rpm/openvpn.spec @@ -13,7 +13,7 @@ Summary: OpenVPN is a robust and highly flexible VPN daemon by James Yonan. Name: openvpn -Version: 2.3.2 +Version: 2.3.3 Release: 1 URL: http://openvpn.net/ Source0: http://prdownloads.sourceforge.net/openvpn/%{name}-%{version}.tar.gz diff --git a/doc/openvpn.8 b/doc/openvpn.8 index d590714..5f3939b 100644 --- a/doc/openvpn.8 +++ b/doc/openvpn.8 @@ -271,7 +271,7 @@ failover capability. .\"********************************************************* .TP .B \-\-remote-random-hostname -Add a random string (6 characters) to first DNS label of hostname to prevent +Prepend a random string (6 bytes, 12 hex characters) to hostname to prevent DNS caching. For example, "foo.bar.gov" would be modified to ".foo.bar.gov". .\"********************************************************* @@ -554,12 +554,15 @@ Set HTTP "User-Agent" string to .B user-agent. .\"********************************************************* .TP -.B \-\-socks-proxy server [port] +.B \-\-socks-proxy server [port] [authfile] Connect to remote host through a Socks5 proxy at address .B server and port .B port (default=1080). +.B authfile +(optional) is a file containing a username and password on 2 lines, or +"stdin" to prompt from console. .\"********************************************************* .TP .B \-\-socks-proxy-retry @@ -805,6 +808,17 @@ also specify or .B \-\-dev-type tap. +Under Mac OS X this option can be used to specify the default tun +implementation. Using +.B \-\-dev\-node utun +forces usage of the native Darwin tun kernel support. Use +.B \-\-dev\-node utunN +to select a specific utun instance. To force using the tun.kext (/dev/tunX) use +.B \-\-dev\-node tun\fR. +When not specifying a +.B \-\-dev\-node +option openvpn will first try to open utun, and fall back to tun.kext. + On Windows systems, select the TAP-Win32 adapter which is named .B node @@ -1880,6 +1894,18 @@ reasons for having OpenVPN fail if it detects problems in a config file. Having said that, there are valid reasons for wanting new software features to gracefully degrade when encountered by older software versions. + +It is also possible to tag a single directive so as not to trigger +a fatal error if the directive isn't recognized. To do this, +prepend the following before the directive: +.B setenv opt + +Versions prior to OpenVPN 2.3.3 will always ignore options set with the +.B setenv opt +directive. + +See also +.B \-\-ignore-unknown-option .\"********************************************************* .TP .B \-\-setenv-safe name value @@ -1893,6 +1919,25 @@ is a safety precaution to prevent a LD_PRELOAD style attack from a malicious or compromised server. .\"********************************************************* .TP +.B \-\-ignore-unknown-option opt1 opt2 opt3 ... optN +When one of options +.B opt1 ... optN +is encountered in the configuration file the configuration +file parsing does not fail if this OpenVPN version does not +support the option. Multiple +.B \-\-ignore-unknown-option +options can be given to support a larger number of options to ignore. + +This option should be used with caution, as there are good security +reasons for having OpenVPN fail if it detects problems in a +config file. Having said that, there are valid reasons for wanting +new software features to gracefully degrade when encountered by +older software versions. + +.B \-\-ignore-unknown-option +is available since OpenVPN 2.3.3. +.\"********************************************************* +.TP .B \-\-script-security level This directive offers policy-level control over OpenVPN's usage of external programs and scripts. Lower @@ -2037,6 +2082,16 @@ In many cases, the parameter can point to an empty directory, however complications can result when scripts or restarts are executed after the chroot operation. + +Note: if OpenVPN is built using the PolarSSL SSL +library, +.B \-\-chroot +will only work if a /dev/urandom device node is available +inside the chroot directory +.B dir. +This is due to the way PolarSSL works (it wants to open +/dev/urandom every time randomness is needed, not just once +at startup) and nothing OpenVPN can influence. .\"********************************************************* .TP .B \-\-setcon context @@ -4214,6 +4269,15 @@ when you built your peer's certificate (see above). .\"********************************************************* .TP +.B \-\-tls-version-min version ['or-highest'] +Sets the minimum +TLS version we will accept from the peer (default is "1.0"). +Examples for version +include "1.0", "1.1", or "1.2". If 'or-highest' is specified +and version is not recognized, we will only accept the highest TLS +version supported by the local SSL implementation. +.\"********************************************************* +.TP .B \-\-pkcs12 file Specify a PKCS #12 file containing local private key, local certificate, and root CA certificate. @@ -5941,6 +6005,16 @@ Set prior to execution of the script. .\"********************************************************* .TP +.B tls_digest_{n} +Contains the certificate SHA1 fingerprint/digest hash value, +where +.B n +is the verification level. Only set for TLS connections. Set prior +to execution of +.B \-\-tls-verify +script. +.\"********************************************************* +.TP .B tls_id_{n} A series of certificate fields from the remote peer, where diff --git a/include/openvpn-plugin.h b/include/openvpn-plugin.h index 0879f49..03da92a 100644 --- a/include/openvpn-plugin.h +++ b/include/openvpn-plugin.h @@ -201,10 +201,15 @@ struct openvpn_plugin_string_list * * Version Comment * 1 Initial plugin v3 structures providing the same API as - * the v2 plugin interface + X509 certificate information. + * the v2 plugin interface, X509 certificate information + + * a logging API for plug-ins. + * + * 2 Added ssl_api member in struct openvpn_plugin_args_open_in + * which identifies the SSL implementation OpenVPN is compiled + * against. * */ -#define OPENVPN_PLUGINv3_STRUCTVER 1 +#define OPENVPN_PLUGINv3_STRUCTVER 2 /** * Definitions needed for the plug-in callback functions. @@ -259,6 +264,18 @@ struct openvpn_plugin_callbacks plugin_vlog_t plugin_vlog; }; +/** + * Used by the openvpn_plugin_open_v3() function to indicate to the + * plug-in what kind of SSL implementation OpenVPN uses. This is + * to avoid SEGV issues when OpenVPN is complied against PolarSSL + * and the plug-in against OpenSSL. + */ +typedef enum { + SSLAPI_NONE, + SSLAPI_OPENSSL, + SSLAPI_POLARSSL +} ovpnSSLAPI; + /** * Arguments used to transport variables to the plug-in. * The struct openvpn_plugin_args_open_in is only used @@ -286,6 +303,7 @@ struct openvpn_plugin_args_open_in const char ** const argv; const char ** const envp; struct openvpn_plugin_callbacks *callbacks; + const ovpnSSLAPI ssl_api; }; @@ -557,7 +575,8 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v2) * ARGUMENTS * * version : fixed value, defines the API version of the OpenVPN plug-in API. The plug-in - * should validate that this value is matching the OPENVPN_PLUGIN_VERSION value. + * should validate that this value is matching the OPENVPN_PLUGINv3_STRUCTVER + * value. * * arguments : Structure with all arguments available to the plug-in. * diff --git a/ltmain.sh b/ltmain.sh index 0096fe6..33f642a 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -70,7 +70,7 @@ # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu2 +# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.1 # automake: $automake_version # autoconf: $autoconf_version # @@ -80,7 +80,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.2 Debian-2.4.2-1ubuntu2" +VERSION="2.4.2 Debian-2.4.2-1.1" TIMESTAMP="" package_revision=1.3337 diff --git a/m4/libtool.m4 b/m4/libtool.m4 index 828104c..534d1cc 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -2512,17 +2512,6 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no @@ -2639,7 +2628,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no @@ -3255,10 +3244,6 @@ freebsd* | dragonfly*) fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -3297,7 +3282,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -4049,7 +4034,7 @@ m4_if([$1], [CXX], [ ;; esac ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler @@ -4348,7 +4333,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) @@ -6241,9 +6226,6 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(ld_shlibs, $1)=yes ;; - gnu*) - ;; - haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes @@ -6405,7 +6387,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(inherit_rpath, $1)=yes ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler diff --git a/sample/sample-plugins/log/build b/sample/sample-plugins/log/build index bbb05f7..c07ec40 100755 --- a/sample/sample-plugins/log/build +++ b/sample/sample-plugins/log/build @@ -6,7 +6,7 @@ # # This directory is where we will look for openvpn-plugin.h -CPPFLAGS="${CPPFLAGS:--I../../..}" +CPPFLAGS="${CPPFLAGS:--I../../../include}" CC="${CC:-gcc}" CFLAGS="${CFLAGS:--O2 -Wall -g}" diff --git a/sample/sample-plugins/log/log_v3.c b/sample/sample-plugins/log/log_v3.c index 742c756..4d3af91 100644 --- a/sample/sample-plugins/log/log_v3.c +++ b/sample/sample-plugins/log/log_v3.c @@ -85,6 +85,11 @@ openvpn_plugin_open_v3 (const int v3structver, return OPENVPN_PLUGIN_FUNC_ERROR; } + if( args->ssl_api != SSLAPI_OPENSSL ) { + printf("This plug-in can only be used against OpenVPN with OpenSSL\n"); + return OPENVPN_PLUGIN_FUNC_ERROR; + } + /* Which callbacks to intercept. */ ret->type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) | diff --git a/src/openvpn/buffer.c b/src/openvpn/buffer.c index 56d14b1..fb3b52d 100644 --- a/src/openvpn/buffer.c +++ b/src/openvpn/buffer.c @@ -327,19 +327,28 @@ gc_malloc (size_t size, bool clear, struct gc_arena *a) #endif { void *ret; - struct gc_entry *e; - ASSERT (NULL != a); - + if (a) + { + struct gc_entry *e; #ifdef DMALLOC - e = (struct gc_entry *) openvpn_dmalloc (file, line, size + sizeof (struct gc_entry)); + e = (struct gc_entry *) openvpn_dmalloc (file, line, size + sizeof (struct gc_entry)); #else - e = (struct gc_entry *) malloc (size + sizeof (struct gc_entry)); + e = (struct gc_entry *) malloc (size + sizeof (struct gc_entry)); #endif - check_malloc_return (e); - ret = (char *) e + sizeof (struct gc_entry); - e->next = a->list; - a->list = e; - + check_malloc_return (e); + ret = (char *) e + sizeof (struct gc_entry); + e->next = a->list; + a->list = e; + } + else + { +#ifdef DMALLOC + ret = openvpn_dmalloc (file, line, size); +#else + ret = malloc (size); +#endif + check_malloc_return (ret); + } #ifndef ZERO_BUFFER_ON_ALLOC if (clear) #endif diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 2420216..52d370b 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -866,7 +866,7 @@ print_openssl_info (const struct options *options) show_available_engines (); #ifdef ENABLE_SSL if (options->show_tls_ciphers) - show_available_tls_ciphers (); + show_available_tls_ciphers (options->cipher_list); #endif return true; } @@ -2973,7 +2973,7 @@ do_close_ifconfig_pool_persist (struct context *c) static void do_inherit_env (struct context *c, const struct env_set *src) { - c->c2.es = env_set_create (&c->c2.gc); + c->c2.es = env_set_create (NULL); c->c2.es_owned = true; env_set_inherit (c->c2.es, src); } diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index fa327f8..56a01a6 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -934,32 +934,23 @@ create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc } /* - * Add a random string to first DNS label of hostname to prevent DNS caching. + * Prepend a random string to hostname to prevent DNS caching. * For example, foo.bar.gov would be modified to .foo.bar.gov. - * Of course, this requires explicit support in the DNS server. + * Of course, this requires explicit support in the DNS server (wildcard). */ const char * hostname_randomize(const char *hostname, struct gc_arena *gc) { # define n_rnd_bytes 6 - char *hst = string_alloc(hostname, gc); - char *dot = strchr(hst, '.'); + uint8_t rnd_bytes[n_rnd_bytes]; + const char *rnd_str; + struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc); - if (dot) - { - uint8_t rnd_bytes[n_rnd_bytes]; - const char *rnd_str; - struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc); - - *dot++ = '\0'; - prng_bytes (rnd_bytes, sizeof (rnd_bytes)); - rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc); - buf_printf(&hname, "%s-0x%s.%s", hst, rnd_str, dot); - return BSTR(&hname); - } - else - return hostname; + prng_bytes (rnd_bytes, sizeof (rnd_bytes)); + rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc); + buf_printf(&hname, "%s.%s", rnd_str, hostname); + return BSTR(&hname); # undef n_rnd_bytes } diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c index 104c9e9..5125eae 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -171,7 +171,7 @@ openvpn_main (int argc, char *argv[]) gc_init (&c.gc); /* initialize environmental variable store */ - c.es = env_set_create (&c.gc); + c.es = env_set_create (NULL); #ifdef WIN32 set_win_sys_path_via_env (c.es); #endif diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 23af272..7741dbf 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -5,10 +5,8 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. - * - * Additions for eurephia plugin done by: - * David Sommerseth Copyright (C) 2009 + * Copyright (C) 2002-2013 OpenVPN Technologies, Inc. + * Copyright (C) 2008-2013 David Sommerseth * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -100,9 +98,6 @@ const char title_string[] = #ifdef ENABLE_PKCS11 " [PKCS11]" #endif -#ifdef ENABLE_EUREPHIA - " [eurephia]" -#endif #if ENABLE_IP_PKTINFO " [MH]" #endif @@ -248,6 +243,8 @@ static const char usage_message[] = "--setenv name value : Set a custom environmental variable to pass to script.\n" "--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n" " directives for future OpenVPN versions to be ignored.\n" + "--ignore-unkown-option opt1 opt2 ...: Relax config file syntax. Allow\n" + " these options to be ignored when unknown\n" "--script-security level: Where level can be:\n" " 0 -- strictly no calling of external programs\n" " 1 -- (default) only call built-ins such as ifconfig\n" @@ -572,6 +569,9 @@ static const char usage_message[] = " by a Certificate Authority in --ca file.\n" "--extra-certs file : one or more PEM certs that complete the cert chain.\n" "--key file : Local private key in .pem format.\n" + "--tls-version-min ['or-highest'] : sets the minimum TLS version we\n" + " will accept from the peer. If version is unrecognized and 'or-highest'\n" + " is specified, require max TLS version supported by SSL implementation.\n" #ifndef ENABLE_CRYPTO_POLARSSL "--pkcs12 file : PKCS#12 file containing local private key, local certificate\n" " and optionally the root CA certificate.\n" @@ -1979,6 +1979,8 @@ options_postprocess_verify_ce (const struct options *options, const struct conne #ifdef ENABLE_HTTP_PROXY if ((ce->http_proxy_options) && ce->proto != PROTO_TCPv4_CLIENT) msg (M_USAGE, "--http-proxy MUST be used in TCP Client mode (i.e. --proto tcp-client)"); + if ((ce->http_proxy_options) && !ce->http_proxy_options->server) + msg (M_USAGE, "--http-proxy not specified but other http proxy options present"); #endif #if defined(ENABLE_HTTP_PROXY) && defined(ENABLE_SOCKS) @@ -2603,6 +2605,44 @@ check_file_access(const int type, const char *file, const int mode, const char * return (errcode != 0 ? true : false); } +/* A wrapper for check_file_access() which also takes a chroot directory. + * If chroot is NULL, behaviour is exactly the same as calling check_file_access() directly, + * otherwise it will look for the file inside the given chroot directory instead. + */ +static bool +check_file_access_chroot(const char *chroot, const int type, const char *file, const int mode, const char *opt) +{ + bool ret = false; + + /* If no file configured, no errors to look for */ + if (!file) + return false; + + /* If chroot is set, look for the file/directory inside the chroot */ + if( chroot ) + { + struct gc_arena gc = gc_new(); + struct buffer chroot_file; + int len = 0; + + /* Build up a new full path including chroot directory */ + len = strlen(chroot) + strlen(PATH_SEPARATOR_STR) + strlen(file) + 1; + chroot_file = alloc_buf_gc(len, &gc); + buf_printf(&chroot_file, "%s%s%s", chroot, PATH_SEPARATOR_STR, file); + ASSERT (chroot_file.len > 0); + + ret = check_file_access(type, BSTR(&chroot_file), mode, opt); + gc_free(&gc); + } + else + { + /* No chroot in play, just call core file check function */ + ret = check_file_access(type, file, mode, opt); + } + return ret; +} + + /* * Verifies that the path in the "command" that comes after certain script options (e.g., --up) is a * valid file with appropriate permissions. @@ -2620,7 +2660,7 @@ check_file_access(const int type, const char *file, const int mode, const char * * check_file_access() arguments. */ static bool -check_cmd_access(const char *command, const char *opt) +check_cmd_access(const char *command, const char *opt, const char *chroot) { struct argv argv; bool return_code; @@ -2639,7 +2679,7 @@ check_cmd_access(const char *command, const char *opt) * only requires X_OK to function on Unix - a scenario not unlikely to * be seen on suid binaries. */ - return_code = check_file_access(CHKACC_FILE, argv.argv[0], X_OK, opt); + return_code = check_file_access_chroot(chroot, CHKACC_FILE, argv.argv[0], X_OK, opt); else { msg (M_NOPREFIX|M_OPTERR, "%s fails with '%s': No path to executable.", @@ -2665,7 +2705,7 @@ options_postprocess_filechecks (struct options *options) #ifdef ENABLE_SSL errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->dh_file, R_OK, "--dh"); errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->ca_file, R_OK, "--ca"); - errs |= check_file_access (CHKACC_FILE, options->ca_path, R_OK, "--capath"); + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->ca_path, R_OK, "--capath"); errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->cert_file, R_OK, "--cert"); errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->extra_certs_file, R_OK, "--extra-certs"); @@ -2678,10 +2718,10 @@ options_postprocess_filechecks (struct options *options) "--pkcs12"); if (options->ssl_flags & SSLF_CRL_VERIFY_DIR) - errs |= check_file_access (CHKACC_FILE, options->crl_file, R_OK|X_OK, + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->crl_file, R_OK|X_OK, "--crl-verify directory"); else - errs |= check_file_access (CHKACC_FILE, options->crl_file, R_OK, + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->crl_file, R_OK, "--crl-verify"); errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->tls_auth_file, R_OK, @@ -2723,13 +2763,13 @@ options_postprocess_filechecks (struct options *options) /* ** Config related ** */ #ifdef ENABLE_SSL - errs |= check_file_access (CHKACC_FILE, options->tls_export_cert, + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->tls_export_cert, R_OK|W_OK|X_OK, "--tls-export-cert"); #endif /* ENABLE_SSL */ #if P2MP_SERVER - errs |= check_file_access (CHKACC_FILE, options->client_config_dir, + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->client_config_dir, R_OK|X_OK, "--client-config-dir"); - errs |= check_file_access (CHKACC_FILE, options->tmp_dir, + errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->tmp_dir, R_OK|W_OK|X_OK, "Temporary directory (--tmp-dir)"); #endif /* P2MP_SERVER */ @@ -2829,6 +2869,7 @@ pre_pull_restore (struct options *o) } o->push_continuation = 0; + o->push_option_types_found = 0; } #endif @@ -3806,7 +3847,7 @@ read_config_string (const char *prefix, { bypass_doubledash (&p[0]); check_inline_file_via_buf (&multiline, p, &options->gc); - add_option (options, p, NULL, line_num, 0, msglevel, permission_mask, option_types_found, es); + add_option (options, p, prefix, line_num, 0, msglevel, permission_mask, option_types_found, es); } CLEAR (p); } @@ -3926,27 +3967,43 @@ void options_string_import (struct options *options, #if P2MP -#define VERIFY_PERMISSION(mask) { if (!verify_permission(p[0], file, (mask), permission_mask, option_types_found, msglevel)) goto err; } +#define VERIFY_PERMISSION(mask) { if (!verify_permission(p[0], file, line, (mask), permission_mask, option_types_found, msglevel, options)) goto err; } static bool verify_permission (const char *name, const char* file, + int line, const unsigned int type, const unsigned int allowed, unsigned int *found, - const int msglevel) + const int msglevel, + struct options* options) { if (!(type & allowed)) { msg (msglevel, "option '%s' cannot be used in this context (%s)", name, file); return false; } - else + + if (found) + *found |= type; + +#ifndef ENABLE_SMALL + /* Check if this options is allowed in connection block, + * but we are currently not in a connection block + * Parsing a connection block uses a temporary options struct without + * connection_list + */ + + if ((type & OPT_P_CONNECTION) && options->connection_list) { - if (found) - *found |= type; - return true; + if (file) + msg (M_WARN, "Option '%s' in %s:%d is ignored by previous blocks ", name, file, line); + else + msg (M_WARN, "Option '%s' is ignored by previous blocks", name); } +#endif + return true; } #else @@ -3996,7 +4053,8 @@ static void set_user_script (struct options *options, const char **script, const char *new_script, - const char *type) + const char *type, + bool in_chroot) { if (*script) { msg (M_WARN, "Multiple --%s scripts defined. " @@ -4011,8 +4069,9 @@ set_user_script (struct options *options, openvpn_snprintf (script_name, sizeof(script_name), "--%s script", type); - if (check_cmd_access (*script, script_name)) + if (check_cmd_access (*script, script_name, (in_chroot ? options->chroot_dir : NULL))) msg (M_USAGE, "Please correct this error."); + } #endif } @@ -4033,7 +4092,18 @@ add_option (struct options *options, const bool pull_mode = BOOL_CAST (permission_mask & OPT_P_PULL_MODE); int msglevel_fc = msglevel_forward_compatible (options, msglevel); - ASSERT (MAX_PARMS >= 5); + ASSERT (MAX_PARMS >= 7); + + /* + * If directive begins with "setenv opt" prefix, don't raise an error if + * directive is unrecognized. + */ + if (streq (p[0], "setenv") && p[1] && streq (p[1], "opt") && !(permission_mask & OPT_P_PULL_MODE)) + { + p += 2; + msglevel_fc = M_WARN; + } + if (!file) { file = "[CMD-LINE]"; @@ -4394,6 +4464,43 @@ add_option (struct options *options, uninit_options (&sub); } } + else if (streq (p[0], "ignore-unknown-option") && p[1]) + { + int i; + int j; + int numignored=0; + const char **ignore; + + VERIFY_PERMISSION (OPT_P_GENERAL); + /* Find out how many options to be ignored */ + for (i=1;p[i];i++) + numignored++; + + /* add number of options already ignored */ + for (i=0;options->ignore_unknown_option && + options->ignore_unknown_option[i]; i++) + numignored++; + + /* Allocate array */ + ALLOC_ARRAY_GC (ignore, const char*, numignored+1, &options->gc); + for (i=0;options->ignore_unknown_option && + options->ignore_unknown_option[i]; i++) + ignore[i]=options->ignore_unknown_option[i]; + + options->ignore_unknown_option=ignore; + + for (j=1;p[j];j++) + { + /* Allow the user to specify ignore-unknown-option --opt too */ + if (p[j][0]=='-' && p[j][1]=='-') + options->ignore_unknown_option[i] = (p[j]+2); + else + options->ignore_unknown_option[i] = p[j]; + i++; + } + + options->ignore_unknown_option[i] = NULL; + } else if (streq (p[0], "remote-ip-hint") && p[1]) { VERIFY_PERMISSION (OPT_P_GENERAL); @@ -4482,7 +4589,7 @@ add_option (struct options *options, set_user_script (options, &options->ipchange, string_substitute (p[1], ',', ' ', &options->gc), - "ipchange"); + "ipchange", true); } else if (streq (p[0], "float")) { @@ -4528,14 +4635,14 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_SCRIPT); if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) goto err; - set_user_script (options, &options->up_script, p[1], "up"); + set_user_script (options, &options->up_script, p[1], "up", false); } else if (streq (p[0], "down") && p[1]) { VERIFY_PERMISSION (OPT_P_SCRIPT); if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) goto err; - set_user_script (options, &options->down_script, p[1], "down"); + set_user_script (options, &options->down_script, p[1], "down", true); } else if (streq (p[0], "down-pre")) { @@ -5216,7 +5323,7 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_SCRIPT); if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) goto err; - set_user_script (options, &options->route_script, p[1], "route-up"); + set_user_script (options, &options->route_script, p[1], "route-up", false); } else if (streq (p[0], "route-pre-down") && p[1]) { @@ -5226,7 +5333,7 @@ add_option (struct options *options, set_user_script (options, &options->route_predown_script, p[1], - "route-pre-down"); + "route-pre-down", true); } else if (streq (p[0], "route-noexec")) { @@ -5595,7 +5702,7 @@ add_option (struct options *options, } set_user_script (options, &options->auth_user_pass_verify_script, - p[1], "auth-user-pass-verify"); + p[1], "auth-user-pass-verify", true); } else if (streq (p[0], "client-connect") && p[1]) { @@ -5603,7 +5710,7 @@ add_option (struct options *options, if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) goto err; set_user_script (options, &options->client_connect_script, - p[1], "client-connect"); + p[1], "client-connect", true); } else if (streq (p[0], "client-disconnect") && p[1]) { @@ -5611,7 +5718,7 @@ add_option (struct options *options, if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) goto err; set_user_script (options, &options->client_disconnect_script, - p[1], "client-disconnect"); + p[1], "client-disconnect", true); } else if (streq (p[0], "learn-address") && p[1]) { @@ -5619,7 +5726,7 @@ add_option (struct options *options, if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT)) goto err; set_user_script (options, &options->learn_address_script, - p[1], "learn-address"); + p[1], "learn-address", true); } else if (streq (p[0], "tmp-dir") && p[1]) { @@ -6438,6 +6545,19 @@ add_option (struct options *options, options->priv_key_file_inline = p[2]; } } + else if (streq (p[0], "tls-version-min") && p[1]) + { + int ver; + VERIFY_PERMISSION (OPT_P_GENERAL); + ver = tls_version_min_parse(p[1], p[2]); + if (ver == TLS_VER_BAD) + { + msg (msglevel, "unknown tls-version-min parameter: %s", p[1]); + goto err; + } + options->ssl_flags &= ~(SSLF_TLS_VERSION_MASK << SSLF_TLS_VERSION_SHIFT); + options->ssl_flags |= (ver << SSLF_TLS_VERSION_SHIFT); + } #ifndef ENABLE_CRYPTO_POLARSSL else if (streq (p[0], "pkcs12") && p[1]) { @@ -6509,7 +6629,7 @@ add_option (struct options *options, goto err; set_user_script (options, &options->tls_verify, string_substitute (p[1], ',', ' ', &options->gc), - "tls-verify"); + "tls-verify", true); } #ifndef ENABLE_CRYPTO_POLARSSL else if (streq (p[0], "tls-export-cert") && p[1]) @@ -6823,10 +6943,22 @@ add_option (struct options *options, #endif else { + int i; + int msglevel= msglevel_fc; + /* Check if an option is in --ignore-unknown-option and + set warning level to non fatal */ + for(i=0; options->ignore_unknown_option && options->ignore_unknown_option[i]; i++) + { + if (streq(p[0], options->ignore_unknown_option[i])) + { + msglevel = M_WARN; + break; + } + } if (file) - msg (msglevel_fc, "Unrecognized option or missing parameter(s) in %s:%d: %s (%s)", file, line, p[0], PACKAGE_VERSION); + msg (msglevel, "Unrecognized option or missing parameter(s) in %s:%d: %s (%s)", file, line, p[0], PACKAGE_VERSION); else - msg (msglevel_fc, "Unrecognized option or missing parameter(s): --%s (%s)", p[0], PACKAGE_VERSION); + msg (msglevel, "Unrecognized option or missing parameter(s): --%s (%s)", p[0], PACKAGE_VERSION); } err: gc_free (&gc); diff --git a/src/openvpn/options.h b/src/openvpn/options.h index f80532c..8cbb85a 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -186,6 +186,8 @@ struct options /* enable forward compatibility for post-2.1 features */ bool forward_compatible; + /* list of options that should be ignored even if unkown */ + const char ** ignore_unknown_option; /* persist parms */ bool persist_config; @@ -458,6 +460,7 @@ struct options bool client; bool pull; /* client pull of config options from server */ int push_continuation; + unsigned int push_option_types_found; const char *auth_user_pass_file; struct options_pre_pull *pre_pull; diff --git a/src/openvpn/pkcs11_openssl.c b/src/openvpn/pkcs11_openssl.c index af843b7..87eb166 100644 --- a/src/openvpn/pkcs11_openssl.c +++ b/src/openvpn/pkcs11_openssl.c @@ -49,7 +49,7 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate, int ret = 1; X509 *x509 = NULL; - RSA *rsa = NULL; + EVP_PKEY *evp = NULL; pkcs11h_openssl_session_t openssl_session = NULL; if ((openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL) @@ -63,9 +63,9 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate, */ certificate = NULL; - if ((rsa = pkcs11h_openssl_session_getRSA (openssl_session)) == NULL) + if ((evp = pkcs11h_openssl_session_getEVP (openssl_session)) == NULL) { - msg (M_WARN, "PKCS#11: Unable get rsa object"); + msg (M_WARN, "PKCS#11: Unable get evp object"); goto cleanup; } @@ -75,7 +75,7 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate, goto cleanup; } - if (!SSL_CTX_use_RSAPrivateKey (ssl_ctx->ctx, rsa)) + if (!SSL_CTX_use_PrivateKey (ssl_ctx->ctx, evp)) { msg (M_WARN, "PKCS#11: Cannot set private key for openssl"); goto cleanup; @@ -108,10 +108,10 @@ cleanup: x509 = NULL; } - if (rsa != NULL) + if (evp != NULL) { - RSA_free (rsa); - rsa = NULL; + EVP_PKEY_free (evp); + evp = NULL; } if (openssl_session != NULL) diff --git a/src/openvpn/plugin.c b/src/openvpn/plugin.c index c96c121..0948f23 100644 --- a/src/openvpn/plugin.c +++ b/src/openvpn/plugin.c @@ -40,8 +40,8 @@ #include "error.h" #include "misc.h" #include "plugin.h" +#include "ssl_backend.h" #include "win32.h" - #include "memdbg.h" #define PLUGIN_SYMBOL_REQUIRED (1<<0) @@ -374,7 +374,8 @@ plugin_open_item (struct plugin *p, struct openvpn_plugin_args_open_in args = { p->plugin_type_mask, (const char ** const) o->argv, (const char ** const) envp, - &callbacks }; + &callbacks, + SSLAPI }; struct openvpn_plugin_args_open_return retargs; CLEAR(retargs); diff --git a/src/openvpn/push.c b/src/openvpn/push.c index be50bef..11505cb 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -202,8 +202,10 @@ incoming_push_message (struct context *c, const struct buffer *buffer) msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", sanitize_control_message(BSTR(buffer), &gc)); else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION) { + c->options.push_option_types_found |= option_types_found; + if (status == PUSH_MSG_REPLY) - do_up (c, true, option_types_found); /* delay bringing tun/tap up until --push parms received from remote */ + do_up (c, true, c->options.push_option_types_found ); /* delay bringing tun/tap up until --push parms received from remote */ event_timeout_clear (&c->c2.push_request_interval); } diff --git a/src/openvpn/route.c b/src/openvpn/route.c index 044e6ac..6333ee7 100644 --- a/src/openvpn/route.c +++ b/src/openvpn/route.c @@ -49,7 +49,7 @@ #define METRIC_NOT_USED ((DWORD)-1) #endif -static void delete_route (struct route *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es); +static void delete_route (struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, const struct env_set *es); static void get_bypass_addresses (struct route_bypass *rb, const unsigned int flags); @@ -150,7 +150,7 @@ struct route_list * new_route_list (const int max_routes, struct gc_arena *a) { struct route_list *ret; - ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route, max_routes, a); + ALLOC_VAR_ARRAY_CLEAR_GC (ret, struct route_list, struct route_ipv4, max_routes, a); ret->capacity = max_routes; return ret; } @@ -165,7 +165,7 @@ new_route_ipv6_list (const int max_routes, struct gc_arena *a) } static const char * -route_string (const struct route *r, struct gc_arena *gc) +route_string (const struct route_ipv4 *r, struct gc_arena *gc) { struct buffer out = alloc_buf_gc (256, gc); buf_printf (&out, "ROUTE network %s netmask %s gateway %s", @@ -267,7 +267,7 @@ is_special_addr (const char *addr_str) } static bool -init_route (struct route *r, +init_route (struct route_ipv4 *r, struct addrinfo **network_list, const struct route_option *ro, const struct route_list *rl) @@ -484,7 +484,7 @@ void clear_route_list (struct route_list *rl) { const int capacity = rl->capacity; - const size_t rl_size = array_mult_safe (sizeof(struct route), capacity, sizeof(struct route_list)); + const size_t rl_size = array_mult_safe (sizeof(struct route_ipv4), capacity, sizeof(struct route_list)); memset(rl, 0, rl_size); rl->capacity = capacity; } @@ -519,7 +519,7 @@ add_block_local_item (struct route_list *rl, && rl->rgi.gateway.netmask < 0xFFFFFFFF && (rl->n)+2 <= rl->capacity) { - struct route r; + struct route_ipv4 r; unsigned int l2; /* split a route into two smaller blocking routes, and direct them to target */ @@ -649,7 +649,7 @@ init_route_list (struct route_list *rl, for (i = 0; i < opt->n; ++i) { struct addrinfo* netlist; - struct route r; + struct route_ipv4 r; if (!init_route (&r, &netlist, @@ -760,7 +760,7 @@ add_route3 (in_addr_t network, const struct route_gateway_info *rgi, const struct env_set *es) { - struct route r; + struct route_ipv4 r; CLEAR (r); r.flags = RT_DEFINED; r.network = network; @@ -778,7 +778,7 @@ del_route3 (in_addr_t network, const struct route_gateway_info *rgi, const struct env_set *es) { - struct route r; + struct route_ipv4 r; CLEAR (r); r.flags = RT_DEFINED|RT_ADDED; r.network = network; @@ -1028,7 +1028,7 @@ add_routes (struct route_list *rl, struct route_ipv6_list *rl6, const struct tun for (i = 0; i < rl->n; ++i) { - struct route *r = &rl->routes[i]; + struct route_ipv4 *r = &rl->routes[i]; check_subnet_conflict (r->network, r->netmask, "route"); if (flags & ROUTE_DELETE_FIRST) delete_route (r, tt, flags, &rl->rgi, es); @@ -1060,7 +1060,7 @@ delete_routes (struct route_list *rl, struct route_ipv6_list *rl6, int i; for (i = rl->n - 1; i >= 0; --i) { - struct route * r = &rl->routes[i]; + struct route_ipv4 * r = &rl->routes[i]; delete_route (r, tt, flags, &rl->rgi, es); } rl->iflags &= ~RL_ROUTES_ADDED; @@ -1154,7 +1154,7 @@ print_default_gateway(const int msglevel, const struct route_gateway_info *rgi) #endif static void -print_route (const struct route *r, int level) +print_route (const struct route_ipv4 *r, int level) { struct gc_arena gc = gc_new (); if (r->flags & RT_DEFINED) @@ -1171,7 +1171,7 @@ print_routes (const struct route_list *rl, int level) } static void -setenv_route (struct env_set *es, const struct route *r, int i) +setenv_route (struct env_set *es, const struct route_ipv4 *r, int i) { struct gc_arena gc = gc_new (); if (r->flags & RT_DEFINED) @@ -1288,7 +1288,7 @@ is_on_link (const int is_local_route, const unsigned int flags, const struct rou } void -add_route (struct route *r, +add_route (struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, /* may be NULL */ @@ -1728,7 +1728,7 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla } static void -delete_route (struct route *r, +delete_route (struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, @@ -2232,7 +2232,7 @@ get_default_gateway (struct route_gateway_info *rgi) } static DWORD -windows_route_find_if_index (const struct route *r, const struct tuntap *tt) +windows_route_find_if_index (const struct route_ipv4 *r, const struct tuntap *tt) { struct gc_arena gc = gc_new (); DWORD ret = TUN_ADAPTER_INDEX_INVALID; @@ -2277,7 +2277,7 @@ windows_route_find_if_index (const struct route *r, const struct tuntap *tt) } bool -add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_index) +add_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index) { struct gc_arena gc = gc_new (); bool ret = false; @@ -2351,7 +2351,7 @@ add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_i } bool -del_route_ipapi (const struct route *r, const struct tuntap *tt) +del_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt) { struct gc_arena gc = gc_new (); bool ret = false; @@ -2597,53 +2597,7 @@ get_default_gateway (struct route_gateway_info *rgi) #include #include #include - -/* all of this is taken from in FreeBSD */ -#define RTA_DST 0x1 -#define RTA_GATEWAY 0x2 -#define RTA_NETMASK 0x4 - -#define RTM_GET 0x4 -#define RTM_VERSION 5 - -#define RTF_UP 0x1 -#define RTF_GATEWAY 0x2 - -/* - * These numbers are used by reliable protocols for determining - * retransmission behavior and are included in the routing structure. - */ -struct rt_metrics { - u_long rmx_locks; /* Kernel must leave these values alone */ - u_long rmx_mtu; /* MTU for this path */ - u_long rmx_hopcount; /* max hops expected */ - u_long rmx_expire; /* lifetime for route, e.g. redirect */ - u_long rmx_recvpipe; /* inbound delay-bandwidth product */ - u_long rmx_sendpipe; /* outbound delay-bandwidth product */ - u_long rmx_ssthresh; /* outbound gateway buffer limit */ - u_long rmx_rtt; /* estimated round trip time */ - u_long rmx_rttvar; /* estimated rtt variance */ - u_long rmx_pksent; /* packets sent using this route */ - u_long rmx_filler[4]; /* will be used for T/TCP later */ -}; - -/* - * Structures for routing messages. - */ -struct rt_msghdr { - u_short rtm_msglen; /* to skip over non-understood messages */ - u_char rtm_version; /* future binary compatibility */ - u_char rtm_type; /* message type */ - u_short rtm_index; /* index for associated ifp */ - int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ - int rtm_addrs; /* bitmask identifying sockaddrs in msg */ - pid_t rtm_pid; /* identify sender */ - int rtm_seq; /* for sender to identify action */ - int rtm_errno; /* why failed */ - int rtm_use; /* from rtentry */ - u_long rtm_inits; /* which metrics we are initializing */ - struct rt_metrics rtm_rmx; /* metrics themselves */ -}; +#include struct { struct rt_msghdr m_rtm; @@ -2963,52 +2917,7 @@ get_default_gateway (struct route_gateway_info *rgi) #include #include #include - -/* all of this is taken from in OpenBSD 3.6 */ -#define RTA_DST 0x1 /* destination sockaddr present */ -#define RTA_GATEWAY 0x2 /* gateway sockaddr present */ -#define RTA_NETMASK 0x4 /* netmask sockaddr present */ - -#define RTM_GET 0x4 /* Report Metrics */ - -#define RTM_VERSION 3 /* Up the ante and ignore older versions */ - -#define RTF_UP 0x1 /* route usable */ -#define RTF_GATEWAY 0x2 /* destination is a gateway */ - -/* - * Huge version for userland compatibility. - */ -struct rt_metrics { - u_long rmx_locks; /* Kernel must leave these values alone */ - u_long rmx_mtu; /* MTU for this path */ - u_long rmx_hopcount; /* max hops expected */ - u_long rmx_expire; /* lifetime for route, e.g. redirect */ - u_long rmx_recvpipe; /* inbound delay-bandwidth product */ - u_long rmx_sendpipe; /* outbound delay-bandwidth product */ - u_long rmx_ssthresh; /* outbound gateway buffer limit */ - u_long rmx_rtt; /* estimated round trip time */ - u_long rmx_rttvar; /* estimated rtt variance */ - u_long rmx_pksent; /* packets sent using this route */ -}; - -/* - * Structures for routing messages. - */ -struct rt_msghdr { - u_short rtm_msglen; /* to skip over non-understood messages */ - u_char rtm_version; /* future binary compatibility */ - u_char rtm_type; /* message type */ - u_short rtm_index; /* index for associated ifp */ - int rtm_flags; /* flags, incl. kern & message, e.g. DONE */ - int rtm_addrs; /* bitmask identifying sockaddrs in msg */ - pid_t rtm_pid; /* identify sender */ - int rtm_seq; /* for sender to identify action */ - int rtm_errno; /* why failed */ - int rtm_use; /* from rtentry */ - u_long rtm_inits; /* which metrics we are initializing */ - struct rt_metrics rtm_rmx; /* metrics themselves */ -}; +#include struct { struct rt_msghdr m_rtm; diff --git a/src/openvpn/route.h b/src/openvpn/route.h index a40de32..fe9b461 100644 --- a/src/openvpn/route.h +++ b/src/openvpn/route.h @@ -110,7 +110,7 @@ struct route_ipv6_option_list { struct route_ipv6_option routes_ipv6[EMPTY_ARRAY_SIZE]; }; -struct route { +struct route_ipv4 { # define RT_DEFINED (1<<0) # define RT_ADDED (1<<1) # define RT_METRIC_DEFINED (1<<2) @@ -190,7 +190,7 @@ struct route_list { unsigned int flags; /* RG_x flags */ int capacity; int n; - struct route routes[EMPTY_ARRAY_SIZE]; + struct route_ipv4 routes[EMPTY_ARRAY_SIZE]; }; #if P2MP @@ -223,7 +223,7 @@ struct route_ipv6_list *new_route_ipv6_list (const int max_routes, struct gc_are void add_route_ipv6 (struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es); void delete_route_ipv6 (const struct route_ipv6 *r, const struct tuntap *tt, unsigned int flags, const struct env_set *es); -void add_route (struct route *r, +void add_route (struct route_ipv4 *r, const struct tuntap *tt, unsigned int flags, const struct route_gateway_info *rgi, @@ -301,8 +301,8 @@ void print_routes (const struct route_list *rl, int level); void show_routes (int msglev); bool test_routes (const struct route_list *rl, const struct tuntap *tt); -bool add_route_ipapi (const struct route *r, const struct tuntap *tt, DWORD adapter_index); -bool del_route_ipapi (const struct route *r, const struct tuntap *tt); +bool add_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt, DWORD adapter_index); +bool del_route_ipapi (const struct route_ipv4 *r, const struct tuntap *tt); #else static inline bool test_routes (const struct route_list *rl, const struct tuntap *tt) { return true; } diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 85f783a..708903c 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -208,18 +208,20 @@ openvpn_getaddrinfo (unsigned int flags, get_signal (signal_received); if (*signal_received) /* were we interrupted by a signal? */ { - if (0 == status) { - ASSERT(res); - freeaddrinfo(*res); - res = NULL; - } if (*signal_received == SIGUSR1) /* ignore SIGUSR1 */ { msg (level, "RESOLVE: Ignored SIGUSR1 signal received during DNS resolution attempt"); *signal_received = 0; } else - goto done; + { + if (0 == status) { + ASSERT(res); + freeaddrinfo(*res); + res = NULL; + } + goto done; + } } } diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 8b864c8..800fcba 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -7,10 +7,7 @@ * * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. * Copyright (C) 2010 Fox Crypto B.V. - * - * Additions for eurephia plugin done by: - * David Sommerseth Copyright (C) 2008-2009 - * + * Copyright (C) 2008-2013 David Sommerseth * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -141,8 +138,6 @@ static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { {"DHE-DSS-CAMELLIA128-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-128-CBC-SHA"}, {"DHE-DSS-CAMELLIA256-SHA256", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA256"}, {"DHE-DSS-CAMELLIA256-SHA", "TLS-DHE-DSS-WITH-CAMELLIA-256-CBC-SHA"}, - {"DHE-DSS-DES-CBC3-SHA", "TLS-DHE-DSS-WITH-3DES-EDE-CBC-SHA"}, - {"DHE-DSS-DES-CBC-SHA", "TLS-DHE-DSS-WITH-DES-CBC-SHA"}, {"DHE-DSS-SEED-SHA", "TLS-DHE-DSS-WITH-SEED-CBC-SHA"}, {"DHE-RSA-AES128-GCM-SHA256", "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256"}, {"DHE-RSA-AES128-SHA256", "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256"}, @@ -154,8 +149,6 @@ static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { {"DHE-RSA-CAMELLIA128-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA"}, {"DHE-RSA-CAMELLIA256-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, {"DHE-RSA-CAMELLIA256-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA"}, - {"DHE-RSA-DES-CBC3-SHA", "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA"}, - {"DHE-RSA-DES-CBC-SHA", "TLS-DHE-RSA-WITH-DES-CBC-SHA"}, {"DHE-RSA-SEED-SHA", "TLS-DHE-RSA-WITH-SEED-CBC-SHA"}, {"DH-RSA-SEED-SHA", "TLS-DH-RSA-WITH-SEED-CBC-SHA"}, {"ECDH-ECDSA-AES128-GCM-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256"}, @@ -242,6 +235,19 @@ static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { {"SRP-RSA-3DES-EDE-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-3DES-EDE-CBC-SHA"}, {"SRP-RSA-AES-128-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-128-CBC-SHA"}, {"SRP-RSA-AES-256-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-256-CBC-SHA"}, +#ifdef ENABLE_CRYPTO_OPENSSL + {"DEFAULT", "DEFAULT"}, + {"ALL", "ALL"}, + {"HIGH", "HIGH"}, + {"MEDIUM", "MEDIUM"}, + {"LOW", "LOW"}, + {"ECDH", "ECDH"}, + {"ECDSA", "ECDSA"}, + {"EDH", "EDH"}, + {"EXP", "EXP"}, + {"RSA", "RSA"}, + {"SRP", "SRP"}, +#endif {NULL, NULL} }; @@ -446,6 +452,27 @@ ssl_put_auth_challenge (const char *cr_str) #endif +/* + * Parse a TLS version string, returning a TLS_VER_x constant. + * If version string is not recognized and extra == "or-highest", + * return tls_version_max(). + */ +int +tls_version_min_parse(const char *vstr, const char *extra) +{ + const int max_version = tls_version_max(); + if (!strcmp(vstr, "1.0") && TLS_VER_1_0 <= max_version) + return TLS_VER_1_0; + else if (!strcmp(vstr, "1.1") && TLS_VER_1_1 <= max_version) + return TLS_VER_1_1; + else if (!strcmp(vstr, "1.2") && TLS_VER_1_2 <= max_version) + return TLS_VER_1_2; + else if (extra && !strcmp(extra, "or-highest")) + return max_version; + else + return TLS_VER_BAD; +} + /* * Initialize SSL context. * All files are in PEM format. @@ -495,12 +522,8 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) #ifdef MANAGMENT_EXTERNAL_KEY else if ((options->management_flags & MF_EXTERNAL_KEY) && options->cert_file) { - openvpn_x509_cert_t *my_cert = NULL; - tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline, - &my_cert); - tls_ctx_use_external_private_key(new_ctx, my_cert); - - tls_ctx_free_cert_file(my_cert); + tls_ctx_use_external_private_key(new_ctx, options->cert_file, + options->cert_file_inline); } #endif else @@ -508,7 +531,7 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) /* Load Certificate */ if (options->cert_file) { - tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline, NULL); + tls_ctx_load_cert_file(new_ctx, options->cert_file, options->cert_file_inline); } /* Load Private Key */ @@ -1813,15 +1836,17 @@ push_peer_info(struct buffer *buf, struct tls_session *session) get_default_gateway (&rgi); if (rgi.flags & RGI_HWADDR_DEFINED) buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc)); + } - /* push env vars that begin with UV_ */ - for (e=es->list; e != NULL; e=e->next) + /* push env vars that begin with UV_ and IV_GUI_VER */ + for (e=es->list; e != NULL; e=e->next) + { + if (e->string) { - if (e->string) - { - if (!strncmp(e->string, "UV_", 3) && buf_safe(&out, strlen(e->string)+1)) - buf_printf (&out, "%s\n", e->string); - } + if (((strncmp(e->string, "UV_", 3)==0 && session->opt->push_peer_info_detail >= 2) + || (strncmp(e->string,"IV_GUI_VER=",sizeof("IV_GUI_VER=")-1)==0)) + && buf_safe(&out, strlen(e->string)+1)) + buf_printf (&out, "%s\n", e->string); } } diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index f61580c..54383fe 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -36,12 +36,23 @@ #ifdef ENABLE_CRYPTO_OPENSSL #include "ssl_openssl.h" #include "ssl_verify_openssl.h" +#define SSLAPI SSLAPI_OPENSSL #endif #ifdef ENABLE_CRYPTO_POLARSSL #include "ssl_polarssl.h" #include "ssl_verify_polarssl.h" +#define SSLAPI SSLAPI_POLARSSL #endif +/* Ensure that SSLAPI got a sane value if SSL is disabled or unknown */ +#ifndef SSLAPI +#define SSLAPI SSLAPI_NONE +#endif + +/** + * prototype for struct tls_session from ssl_common.h + */ +struct tls_session; /** * Get a tls_cipher_name_pair containing OpenSSL and IANA names for supplied TLS cipher name @@ -89,6 +100,29 @@ void tls_free_lib(); */ void tls_clear_error(); +/** + * Parse a TLS version specifier + * + * @param vstr The TLS version string + * @param extra An optional extra parameter, may be NULL + * + * @return One of the TLS_VER_x constants or TLS_VER_BAD + * if a parse error should be flagged. + */ +#define TLS_VER_BAD -1 +#define TLS_VER_1_0 0 /* default */ +#define TLS_VER_1_1 1 +#define TLS_VER_1_2 2 +int tls_version_min_parse(const char *vstr, const char *extra); + +/** + * Return the maximum TLS version (as a TLS_VER_x constant) + * supported by current SSL implementation + * + * @return One of the TLS_VER_x constants (but not TLS_VER_BAD). + */ +int tls_version_max(void); + /** * Initialise a library-specific TLS context for a server. * @@ -181,27 +215,13 @@ void tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert * Load certificate file into the given TLS context. If the given certificate * file contains a certificate chain, load the whole chain. * - * If the x509 parameter is not NULL, the certificate will be returned in it. - * * @param ctx TLS context to use * @param cert_file The file name to load the certificate from, or * "[[INLINE]]" in the case of inline files. * @param cert_file_inline A string containing the certificate - * @param x509 An optional certificate, if x509 is NULL, - * do nothing, if x509 is not NULL, *x509 will be - * allocated and filled with the loaded certificate. - * *x509 must be NULL. */ void tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, - const char *cert_file_inline, openvpn_x509_cert_t **x509 - ); - -/** - * Free the given certificate - * - * @param x509 certificate to free - */ -void tls_ctx_free_cert_file (openvpn_x509_cert_t *x509); + const char *cert_file_inline); /** * Load private key file into the given TLS context. @@ -221,17 +241,19 @@ int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, #ifdef MANAGMENT_EXTERNAL_KEY /** - * Tell the management interface to load the external private key matching - * the given certificate. + * Tell the management interface to load the given certificate and the external + * private key matching the given certificate. * * @param ctx TLS context to use - * @param cert The certificate file to load the private key for + * @param cert_file The file name to load the certificate from, or * "[[INLINE]]" in the case of inline files. + * @param cert_file_inline A string containing the certificate * * @return 1 if an error occurred, 0 if parsing was * successful. */ -int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, openvpn_x509_cert_t *cert); +int tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, + const char *cert_file, const char *cert_file_inline); #endif @@ -291,7 +313,7 @@ void tls_ctx_personalise_random(struct tls_root_ctx *ctx); * @param session The session associated with the given key_state */ void key_state_ssl_init(struct key_state_ssl *ks_ssl, - const struct tls_root_ctx *ssl_ctx, bool is_server, void *session); + const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session); /** * Free the SSL channel part of the given key state. @@ -432,8 +454,10 @@ void print_details (struct key_state_ssl * ks_ssl, const char *prefix); /* * Show the TLS ciphers that are available for us to use in the OpenSSL * library. + * + * @param - list of allowed TLS cipher, or NULL. */ -void show_available_tls_ciphers (); +void show_available_tls_ciphers (const char *tls_ciphers); /* * The OpenSSL library has a notion of preference in TLS ciphers. Higher diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 0d818ab..66b6492 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -285,12 +285,14 @@ struct tls_options struct env_set *es; const struct plugin_list *plugins; - /* configuration file boolean options */ + /* configuration file SSL-related boolean and low-permutation options */ # define SSLF_CLIENT_CERT_NOT_REQUIRED (1<<0) # define SSLF_USERNAME_AS_COMMON_NAME (1<<1) # define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2) # define SSLF_OPT_VERIFY (1<<4) # define SSLF_CRL_VERIFY_DIR (1<<5) +# define SSLF_TLS_VERSION_SHIFT 6 +# define SSLF_TLS_VERSION_MASK 0xF /* (uses bit positions 6 to 9) */ unsigned int ssl_flags; #ifdef MANAGEMENT_DEF_AUTH diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index 79cc056..5689e7c 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -103,8 +103,17 @@ tmp_rsa_cb (SSL * s, int is_export, int keylength) static RSA *rsa_tmp = NULL; if (rsa_tmp == NULL) { + int ret = -1; + BIGNUM *bn = BN_new(); + rsa_tmp = RSA_new(); + msg (D_HANDSHAKE, "Generating temp (%d bit) RSA key", keylength); - rsa_tmp = RSA_generate_key (keylength, RSA_F4, NULL, NULL); + + if(!bn || !BN_set_word(bn, RSA_F4) || + !RSA_generate_key_ex(rsa_tmp, keylength, bn, NULL)) + msg(M_SSLERR, "Failed to generate temp RSA key"); + + if (bn) BN_free( bn ); } return (rsa_tmp); } @@ -114,10 +123,10 @@ tls_ctx_server_new(struct tls_root_ctx *ctx) { ASSERT(NULL != ctx); - ctx->ctx = SSL_CTX_new (TLSv1_server_method ()); + ctx->ctx = SSL_CTX_new (SSLv23_server_method ()); if (ctx->ctx == NULL) - msg (M_SSLERR, "SSL_CTX_new TLSv1_server_method"); + msg (M_SSLERR, "SSL_CTX_new SSLv23_server_method"); SSL_CTX_set_tmp_rsa_callback (ctx->ctx, tmp_rsa_cb); } @@ -127,10 +136,10 @@ tls_ctx_client_new(struct tls_root_ctx *ctx) { ASSERT(NULL != ctx); - ctx->ctx = SSL_CTX_new (TLSv1_client_method ()); + ctx->ctx = SSL_CTX_new (SSLv23_client_method ()); if (ctx->ctx == NULL) - msg (M_SSLERR, "SSL_CTX_new TLSv1_client_method"); + msg (M_SSLERR, "SSL_CTX_new SSLv23_client_method"); } void @@ -174,13 +183,46 @@ info_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret) } } +/* + * Return maximum TLS version supported by local OpenSSL library. + * Assume that presence of SSL_OP_NO_TLSvX macro indicates that + * TLSvX is supported. + */ +int +tls_version_max(void) +{ +#if defined(SSL_OP_NO_TLSv1_2) + return TLS_VER_1_2; +#elif defined(SSL_OP_NO_TLSv1_1) + return TLS_VER_1_1; +#else + return TLS_VER_1_0; +#endif +} + void tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags) { ASSERT(NULL != ctx); + /* process SSL options including minimum TLS version we will accept from peer */ + { + long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; + if (tls_version_min > TLS_VER_1_0) + sslopt |= SSL_OP_NO_TLSv1; +#ifdef SSL_OP_NO_TLSv1_1 + if (tls_version_min > TLS_VER_1_1) + sslopt |= SSL_OP_NO_TLSv1_1; +#endif +#ifdef SSL_OP_NO_TLSv1_2 + if (tls_version_min > TLS_VER_1_2) + sslopt |= SSL_OP_NO_TLSv1_2; +#endif + SSL_CTX_set_options (ctx->ctx, sslopt); + } + SSL_CTX_set_session_cache_mode (ctx->ctx, SSL_SESS_CACHE_OFF); - SSL_CTX_set_options (ctx->ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_set_default_passwd_cb (ctx->ctx, pem_password_callback); /* Require peer certificate verification */ @@ -380,16 +422,34 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, /* Set Certificate Verification chain */ if (load_ca_file) { + /* Add CAs from PKCS12 to the cert store and mark them as trusted. + * They're also used to fill in the chain of intermediate certs as + * necessary. + */ if (ca && sk_X509_num(ca)) { for (i = 0; i < sk_X509_num(ca); i++) { - if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) + if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); } } + } else { + /* If trusted CA certs were loaded from a PEM file, and we ignore the + * ones in PKCS12, do load PKCS12-provided certs to the client extra + * certs chain just in case they include intermediate CAs needed to + * prove my identity to the other end. This does not make them trusted. + */ + if (ca && sk_X509_num(ca)) + { + for (i = 0; i < sk_X509_num(ca); i++) + { + if (!SSL_CTX_add_extra_chain_cert(ctx->ctx,sk_X509_value(ca, i))) + msg (M_SSLERR, "Cannot add extra certificate to chain (SSL_CTX_add_extra_chain_cert)"); + } + } } return 0; } @@ -423,9 +483,10 @@ tls_ctx_add_extra_certs (struct tls_root_ctx *ctx, BIO *bio) } } -void -tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, - const char *cert_file_inline, X509 **x509 +/* Like tls_ctx_load_cert, but returns a copy of the certificate in **X509 */ +static void +tls_ctx_load_cert_file_and_copy (struct tls_root_ctx *ctx, + const char *cert_file, const char *cert_file_inline, X509 **x509 ) { BIO *in = NULL; @@ -479,6 +540,13 @@ end: X509_free (x); } +void +tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, + const char *cert_file_inline) +{ + tls_ctx_load_cert_file_and_copy (ctx, cert_file, cert_file_inline, NULL); +} + void tls_ctx_free_cert_file (X509 *x509) { @@ -616,15 +684,19 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i } int -tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert) +tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, + const char *cert_file, const char *cert_file_inline) { RSA *rsa = NULL; RSA *pub_rsa; RSA_METHOD *rsa_meth; + X509 *cert = NULL; ASSERT (NULL != ctx); ASSERT (NULL != cert); + tls_ctx_load_cert_file_and_copy (ctx, cert_file, cert_file_inline, &cert); + /* allocate custom RSA method object */ ALLOC_OBJ_CLEAR (rsa_meth, RSA_METHOD); rsa_meth->name = "OpenVPN external private key RSA Method"; @@ -659,10 +731,13 @@ tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, X509 *cert) if (!SSL_CTX_use_RSAPrivateKey(ctx->ctx, rsa)) goto err; + X509_free(cert); RSA_free(rsa); /* doesn't necessarily free, just decrements refcount */ return 1; err: + if (cert) + X509_free(cert); if (rsa) RSA_free(rsa); else @@ -694,7 +769,7 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, X509_STORE *store = NULL; X509_NAME *xn = NULL; BIO *in = NULL; - int i, added = 0; + int i, added = 0, prev = 0; ASSERT(NULL != ctx); @@ -721,6 +796,11 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, if (info->crl) X509_STORE_add_crl (store, info->crl); + if (tls_server && !info->x509) + { + msg (M_SSLERR, "X509 name was missing in TLS mode"); + } + if (info->x509) { X509_STORE_add_cert (store, info->x509); @@ -750,6 +830,15 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, sk_X509_NAME_push (cert_names, xn); } } + + if (tls_server) { + int cnum = sk_X509_NAME_num (cert_names); + if (cnum != (prev + 1)) { + msg (M_WARN, "Cannot load CA certificate file %s (entry %d did not validate)", np(ca_file), added); + } + prev = cnum; + } + } sk_X509_INFO_pop_free (info_stack, X509_INFO_free); } @@ -757,8 +846,15 @@ tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, if (tls_server) SSL_CTX_set_client_CA_list (ctx->ctx, cert_names); - if (!added || (tls_server && sk_X509_NAME_num (cert_names) != added)) - msg (M_SSLERR, "Cannot load CA certificate file %s", np(ca_file)); + if (!added) + msg (M_SSLERR, "Cannot load CA certificate file %s (no entries were read)", np(ca_file)); + + if (tls_server) { + int cnum = sk_X509_NAME_num (cert_names); + if (cnum != added) + msg (M_SSLERR, "Cannot load CA certificate file %s (only %d of %d entries were valid X509 names)", np(ca_file), cnum, added); + } + if (in) BIO_free (in); } @@ -1015,7 +1111,7 @@ bio_read (BIO *bio, struct buffer *buf, int maxlen, const char *desc) } void -key_state_ssl_init(struct key_state_ssl *ks_ssl, const struct tls_root_ctx *ssl_ctx, bool is_server, void *session) +key_state_ssl_init(struct key_state_ssl *ks_ssl, const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session) { ASSERT(NULL != ssl_ctx); ASSERT(ks_ssl); @@ -1188,23 +1284,26 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix) } void -show_available_tls_ciphers () +show_available_tls_ciphers (const char *cipher_list) { - SSL_CTX *ctx; + struct tls_root_ctx tls_ctx; SSL *ssl; const char *cipher_name; const char *print_name; const tls_cipher_name_pair *pair; int priority = 0; - ctx = SSL_CTX_new (TLSv1_method ()); - if (!ctx) + tls_ctx.ctx = SSL_CTX_new (SSLv23_method ()); + if (!tls_ctx.ctx) msg (M_SSLERR, "Cannot create SSL_CTX object"); - ssl = SSL_new (ctx); + ssl = SSL_new (tls_ctx.ctx); if (!ssl) msg (M_SSLERR, "Cannot create SSL object"); + if (cipher_list) + tls_ctx_restrict_ciphers(&tls_ctx, cipher_list); + printf ("Available TLS Ciphers,\n"); printf ("listed in order of preference:\n\n"); while ((cipher_name = SSL_get_cipher_list (ssl, priority++))) @@ -1222,7 +1321,7 @@ show_available_tls_ciphers () printf ("\n"); SSL_free (ssl); - SSL_CTX_free (ctx); + SSL_CTX_free (tls_ctx.ctx); } void @@ -1232,7 +1331,7 @@ get_highest_preference_tls_cipher (char *buf, int size) SSL *ssl; const char *cipher_name; - ctx = SSL_CTX_new (TLSv1_method ()); + ctx = SSL_CTX_new (SSLv23_method ()); if (!ctx) msg (M_SSLERR, "Cannot create SSL_CTX object"); ssl = SSL_new (ctx); diff --git a/src/openvpn/ssl_openssl.h b/src/openvpn/ssl_openssl.h index fc2052c..73a6c49 100644 --- a/src/openvpn/ssl_openssl.h +++ b/src/openvpn/ssl_openssl.h @@ -32,6 +32,18 @@ #include +/** + * SSL_OP_NO_TICKET tells OpenSSL to disable "stateless session resumption", + * as this is something we do not want nor need, but could potentially be + * used for a future attack. For compatibility reasons, in the 2.3.x + * series, we keep building if the OpenSSL version is too old to support + * this. 2.4 requires it and will fail configure if not present. + */ +#ifndef SSL_OP_NO_TICKET +# define SSL_OP_NO_TICKET 0 +#endif + + /** * Structure that wraps the TLS context. Contents differ depending on the * SSL library used. diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c index 2b5b37b..551c352 100644 --- a/src/openvpn/ssl_polarssl.c +++ b/src/openvpn/ssl_polarssl.c @@ -7,6 +7,7 @@ * * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. * Copyright (C) 2010 Fox Crypto B.V. + * Copyright (C) 2006-2010, Brainspark B.V. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -121,6 +122,10 @@ tls_ctx_free(struct tls_root_ctx *ctx) free(ctx->priv_key_pkcs11); } #endif +#if defined(MANAGMENT_EXTERNAL_KEY) + if (ctx->external_key != NULL) + free(ctx->external_key); +#endif if (ctx->allowed_ciphers) free(ctx->allowed_ciphers); @@ -237,13 +242,10 @@ tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert) void tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, - const char *cert_file_inline, - openvpn_x509_cert_t **x509 + const char *cert_file_inline ) { ASSERT(NULL != ctx); - if (NULL != x509) - ASSERT(NULL == *x509); if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_file_inline) { @@ -256,16 +258,6 @@ tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, if (0 != x509parse_crtfile(ctx->crt_chain, cert_file)) msg (M_FATAL, "Cannot load certificate file %s", cert_file); } - if (x509) - { - *x509 = ctx->crt_chain; - } -} - -void -tls_ctx_free_cert_file (openvpn_x509_cert_t *x509) -{ - x509_free(x509); } int @@ -322,13 +314,156 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, #ifdef MANAGMENT_EXTERNAL_KEY + +struct external_context { + size_t signature_length; +}; + int -tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, openvpn_x509_cert_t *cert) +tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, + const char *cert_file, const char *cert_file_inline) { - msg(M_FATAL, "Use of management external keys not yet supported for PolarSSL."); - return false; + ASSERT(NULL != ctx); + + tls_ctx_load_cert_file(ctx, cert_file, cert_file_inline); + + if (ctx->crt_chain == NULL) + return 0; + + /* Most of the initialization happens in key_state_ssl_init() */ + ALLOC_OBJ_CLEAR (ctx->external_key, struct external_context); + ctx->external_key->signature_length = ctx->crt_chain->rsa.len; + + return 1; } +static inline int external_pkcs1_sign( void *ctx_voidptr, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode, + int hash_id, unsigned int hashlen, const unsigned char *hash, + unsigned char *sig ) +{ + struct external_context * const ctx = ctx_voidptr; + char *in_b64 = NULL; + char *out_b64 = NULL; + int rv; + unsigned char * const p = sig; + size_t asn_len; + + ASSERT(NULL != ctx); + + if (RSA_PRIVATE != mode) + { + rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA; + goto done; + } + + /* + * Support a wide range of hashes. TLSv1.1 and before only need SIG_RSA_RAW, + * but TLSv1.2 needs the full suite of hashes. + * + * This code has been taken from PolarSSL pkcs11_sign(), under the GPLv2.0+. + */ + switch( hash_id ) + { + case SIG_RSA_RAW: + asn_len = 0; + memcpy( p, hash, hashlen ); + break; + + case SIG_RSA_MD2: + asn_len = OID_SIZE(ASN1_HASH_MDX); + memcpy( p, ASN1_HASH_MDX, asn_len ); + memcpy( p + asn_len, hash, hashlen ); + p[13] = 2; break; + + case SIG_RSA_MD4: + asn_len = OID_SIZE(ASN1_HASH_MDX); + memcpy( p, ASN1_HASH_MDX, asn_len ); + memcpy( p + asn_len, hash, hashlen ); + p[13] = 4; break; + + case SIG_RSA_MD5: + asn_len = OID_SIZE(ASN1_HASH_MDX); + memcpy( p, ASN1_HASH_MDX, asn_len ); + memcpy( p + asn_len, hash, hashlen ); + p[13] = 5; break; + + case SIG_RSA_SHA1: + asn_len = OID_SIZE(ASN1_HASH_SHA1); + memcpy( p, ASN1_HASH_SHA1, asn_len ); + memcpy( p + 15, hash, hashlen ); + break; + + case SIG_RSA_SHA224: + asn_len = OID_SIZE(ASN1_HASH_SHA2X); + memcpy( p, ASN1_HASH_SHA2X, asn_len ); + memcpy( p + asn_len, hash, hashlen ); + p[1] += hashlen; p[14] = 4; p[18] += hashlen; break; + + case SIG_RSA_SHA256: + asn_len = OID_SIZE(ASN1_HASH_SHA2X); + memcpy( p, ASN1_HASH_SHA2X, asn_len ); + memcpy( p + asn_len, hash, hashlen ); + p[1] += hashlen; p[14] = 1; p[18] += hashlen; break; + + case SIG_RSA_SHA384: + asn_len = OID_SIZE(ASN1_HASH_SHA2X); + memcpy( p, ASN1_HASH_SHA2X, asn_len ); + memcpy( p + asn_len, hash, hashlen ); + p[1] += hashlen; p[14] = 2; p[18] += hashlen; break; + + case SIG_RSA_SHA512: + asn_len = OID_SIZE(ASN1_HASH_SHA2X); + memcpy( p, ASN1_HASH_SHA2X, asn_len ); + memcpy( p + asn_len, hash, hashlen ); + p[1] += hashlen; p[14] = 3; p[18] += hashlen; break; + + /* End of copy */ + default: + rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA; + goto done; + } + + /* convert 'from' to base64 */ + if (openvpn_base64_encode (sig, asn_len + hashlen, &in_b64) <= 0) + { + rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA; + goto done; + } + + /* call MI for signature */ + if (management) + out_b64 = management_query_rsa_sig (management, in_b64); + if (!out_b64) + { + rv = POLARSSL_ERR_RSA_PRIVATE_FAILED; + goto done; + } + + /* decode base64 signature to binary and verify length */ + if ( openvpn_base64_decode (out_b64, sig, ctx->signature_length) != + ctx->signature_length ) + { + rv = POLARSSL_ERR_RSA_PRIVATE_FAILED; + goto done; + } + + rv = 0; + + done: + if (in_b64) + free (in_b64); + if (out_b64) + free (out_b64); + return rv; +} + +static inline size_t external_key_len(void *vctx) +{ + struct external_context * const ctx = vctx; + + return ctx->signature_length; +} #endif void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, @@ -501,8 +636,20 @@ void tls_ctx_personalise_random(struct tls_root_ctx *ctx) } } +int +tls_version_max(void) +{ +#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3) + return TLS_VER_1_2; +#elif defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2) + return TLS_VER_1_1; +#else + return TLS_VER_1_0; +#endif +} + void key_state_ssl_init(struct key_state_ssl *ks_ssl, - const struct tls_root_ctx *ssl_ctx, bool is_server, void *session) + const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session) { ASSERT(NULL != ssl_ctx); ASSERT(ks_ssl); @@ -529,15 +676,62 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl, ssl_ctx->priv_key_pkcs11, ssl_pkcs11_decrypt, ssl_pkcs11_sign, ssl_pkcs11_key_len ); else +#endif +#if defined(MANAGMENT_EXTERNAL_KEY) + if (ssl_ctx->external_key != NULL) + ssl_set_own_cert_alt( ks_ssl->ctx, ssl_ctx->crt_chain, + ssl_ctx->external_key, NULL, external_pkcs1_sign, + external_key_len ); + else #endif ssl_set_own_cert( ks_ssl->ctx, ssl_ctx->crt_chain, ssl_ctx->priv_key ); /* Initialise SSL verification */ - ssl_set_authmode (ks_ssl->ctx, SSL_VERIFY_REQUIRED); - ssl_set_verify (ks_ssl->ctx, verify_callback, session); +#if P2MP_SERVER + if (session->opt->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED) + { + msg (M_WARN, "WARNING: POTENTIALLY DANGEROUS OPTION " + "--client-cert-not-required may accept clients which do not present " + "a certificate"); + } + else +#endif + { + ssl_set_authmode (ks_ssl->ctx, SSL_VERIFY_REQUIRED); + ssl_set_verify (ks_ssl->ctx, verify_callback, session); + } + /* TODO: PolarSSL does not currently support sending the CA chain to the client */ ssl_set_ca_chain (ks_ssl->ctx, ssl_ctx->ca_chain, NULL, NULL ); + /* Initialize minimum TLS version */ + { + const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; + int polar_major; + int polar_minor; + switch (tls_version_min) + { + case TLS_VER_1_0: + default: + polar_major = SSL_MAJOR_VERSION_3; + polar_minor = SSL_MINOR_VERSION_1; + break; +#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2) + case TLS_VER_1_1: + polar_major = SSL_MAJOR_VERSION_3; + polar_minor = SSL_MINOR_VERSION_2; + break; +#endif +#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3) + case TLS_VER_1_2: + polar_major = SSL_MAJOR_VERSION_3; + polar_minor = SSL_MINOR_VERSION_3; + break; +#endif + } + ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor); + } + /* Initialise BIOs */ ALLOC_OBJ_CLEAR (ks_ssl->ct_in, endless_buffer); ALLOC_OBJ_CLEAR (ks_ssl->ct_out, endless_buffer); @@ -839,10 +1033,16 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix) } void -show_available_tls_ciphers () +show_available_tls_ciphers (const char *cipher_list) { + struct tls_root_ctx tls_ctx; const int *ciphers = ssl_list_ciphersuites(); + if (cipher_list) { + tls_ctx_restrict_ciphers(&tls_ctx, cipher_list); + ciphers = tls_ctx.allowed_ciphers; + } + #ifndef ENABLE_SMALL printf ("Available TLS Ciphers,\n"); printf ("listed in order of preference:\n\n"); diff --git a/src/openvpn/ssl_polarssl.h b/src/openvpn/ssl_polarssl.h index da93699..fc9aa78 100644 --- a/src/openvpn/ssl_polarssl.h +++ b/src/openvpn/ssl_polarssl.h @@ -30,6 +30,8 @@ #ifndef SSL_POLARSSL_H_ #define SSL_POLARSSL_H_ +#include "syshead.h" + #include #if defined(ENABLE_PKCS11) @@ -67,6 +69,9 @@ struct tls_root_ctx { rsa_context *priv_key; /**< Local private key */ #if defined(ENABLE_PKCS11) pkcs11_context *priv_key_pkcs11; /**< PKCS11 private key */ +#endif +#ifdef MANAGMENT_EXTERNAL_KEY + struct external_context *external_key; /**< Management external key */ #endif int * allowed_ciphers; /**< List of allowed ciphers for this connection */ }; diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index e651a8e..0670f2a 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -425,7 +425,6 @@ verify_cert_set_env(struct env_set *es, openvpn_x509_cert_t *peer_cert, int cert setenv_str (es, envname, common_name); #endif -#ifdef ENABLE_EUREPHIA /* export X509 cert SHA1 fingerprint */ { unsigned char *sha1_hash = x509_get_sha1_hash(peer_cert, &gc); @@ -434,7 +433,6 @@ verify_cert_set_env(struct env_set *es, openvpn_x509_cert_t *peer_cert, int cert setenv_str (es, envname, format_hex_ex(sha1_hash, SHA_DIGEST_LENGTH, 0, 1, ":", &gc)); } -#endif /* export serial number as environmental variable */ serial = x509_get_serial(peer_cert, &gc); diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h index 4db29cc..7a7d53a 100644 --- a/src/openvpn/syshead.h +++ b/src/openvpn/syshead.h @@ -546,7 +546,7 @@ socket_defined (const socket_descriptor_t sd) /* * Enable external private key */ -#if defined(ENABLE_MANAGEMENT) && defined(ENABLE_SSL) && !defined(ENABLE_CRYPTO_POLARSSL) +#if defined(ENABLE_MANAGEMENT) && defined(ENABLE_SSL) #define MANAGMENT_EXTERNAL_KEY #endif diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index a361233..976cc52 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -73,6 +73,12 @@ static void solaris_error_close (struct tuntap *tt, const struct env_set *es, co #include #endif +#if defined(TARGET_DARWIN) && HAVE_NET_IF_UTUN_H +#include +#include +#include +#endif + static void clear_tuntap (struct tuntap *tuntap); bool @@ -867,7 +873,7 @@ do_ifconfig (struct tuntap *tt, if (!tun && tt->topology == TOP_SUBNET) { /* Add a network route for the local tun interface */ - struct route r; + struct route_ipv4 r; CLEAR (r); r.flags = RT_DEFINED | RT_METRIC_DEFINED; r.network = tt->local & tt->remote_netmask; @@ -1064,7 +1070,7 @@ do_ifconfig (struct tuntap *tt, /* Add a network route for the local tun interface */ if (!tun && tt->topology == TOP_SUBNET) { - struct route r; + struct route_ipv4 r; CLEAR (r); r.flags = RT_DEFINED; r.network = tt->local & tt->remote_netmask; @@ -1130,7 +1136,7 @@ do_ifconfig (struct tuntap *tt, /* Add a network route for the local tun interface */ if (!tun && tt->topology == TOP_SUBNET) { - struct route r; + struct route_ipv4 r; CLEAR (r); r.flags = RT_DEFINED; r.network = tt->local & tt->remote_netmask; @@ -1248,6 +1254,87 @@ open_null (struct tuntap *tt) tt->actual_name = string_alloc ("null", NULL); } + +#if defined (TARGET_OPENBSD) || (defined(TARGET_DARWIN) && HAVE_NET_IF_UTUN_H) + +/* + * OpenBSD and Mac OS X when using utun + * have a slightly incompatible TUN device from + * the rest of the world, in that it prepends a + * uint32 to the beginning of the IP header + * to designate the protocol (why not just + * look at the version field in the IP header to + * determine v4 or v6?). + * + * We strip off this field on reads and + * put it back on writes. + * + * I have not tested TAP devices on OpenBSD, + * but I have conditionalized the special + * TUN handling code described above to + * go away for TAP devices. + */ + +#include +#include + +static inline int +header_modify_read_write_return (int len) +{ + if (len > 0) + return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; + else + return len; +} + +int +write_tun_header (struct tuntap* tt, uint8_t *buf, int len) +{ + if (tt->type == DEV_TYPE_TUN) + { + u_int32_t type; + struct iovec iv[2]; + struct ip *iph; + + iph = (struct ip *) buf; + + if (tt->ipv6 && iph->ip_v == 6) + type = htonl (AF_INET6); + else + type = htonl (AF_INET); + + iv[0].iov_base = &type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = len; + + return header_modify_read_write_return (writev (tt->fd, iv, 2)); + } + else + return write (tt->fd, buf, len); +} + +int +read_tun_header (struct tuntap* tt, uint8_t *buf, int len) +{ + if (tt->type == DEV_TYPE_TUN) + { + u_int32_t type; + struct iovec iv[2]; + + iv[0].iov_base = &type; + iv[0].iov_len = sizeof (type); + iv[1].iov_base = buf; + iv[1].iov_len = len; + + return header_modify_read_write_return (readv (tt->fd, iv, 2)); + } + else + return read (tt->fd, buf, len); +} +#endif + + #ifndef WIN32 static void open_tun_generic (const char *dev, const char *dev_type, const char *dev_node, @@ -1972,23 +2059,6 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len) #elif defined(TARGET_OPENBSD) -/* - * OpenBSD has a slightly incompatible TUN device from - * the rest of the world, in that it prepends a - * uint32 to the beginning of the IP header - * to designate the protocol (why not just - * look at the version field in the IP header to - * determine v4 or v6?). - * - * We strip off this field on reads and - * put it back on writes. - * - * I have not tested TAP devices on OpenBSD, - * but I have conditionalized the special - * TUN handling code described above to - * go away for TAP devices. - */ - void open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) { @@ -2055,59 +2125,16 @@ close_tun (struct tuntap* tt) } } -static inline int -openbsd_modify_read_write_return (int len) -{ - if (len > 0) - return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; - else - return len; -} - int -write_tun (struct tuntap* tt, uint8_t *buf, int len) +write_tun(struct tuntap *tt, uint8_t *buf, int len) { - if (tt->type == DEV_TYPE_TUN) - { - u_int32_t type; - struct iovec iv[2]; - struct ip *iph; - - iph = (struct ip *) buf; - - if (tt->ipv6 && iph->ip_v == 6) - type = htonl (AF_INET6); - else - type = htonl (AF_INET); - - iv[0].iov_base = &type; - iv[0].iov_len = sizeof (type); - iv[1].iov_base = buf; - iv[1].iov_len = len; - - return openbsd_modify_read_write_return (writev (tt->fd, iv, 2)); - } - else - return write (tt->fd, buf, len); + return write_tun_header (tt, buf, len); } int -read_tun (struct tuntap* tt, uint8_t *buf, int len) +read_tun (struct tuntap *tt, uint8_t *buf, int len) { - if (tt->type == DEV_TYPE_TUN) - { - u_int32_t type; - struct iovec iv[2]; - - iv[0].iov_base = &type; - iv[0].iov_len = sizeof (type); - iv[1].iov_base = buf; - iv[1].iov_len = len; - - return openbsd_modify_read_write_return (readv (tt->fd, iv, 2)); - } - else - return read (tt->fd, buf, len); + return read_tun_header (tt, buf, len); } #elif defined(TARGET_NETBSD) @@ -2467,10 +2494,177 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len) * pointing to lo0. Need to unconfigure... (observed on 10.5) */ +/* + * utun is the native Darwin tun driver present since at least 10.7 + * Thanks goes to Jonathan Levin for providing an example how to utun + * (http://newosxbook.com/src.jl?tree=listings&file=17-15-utun.c) + */ + +#ifdef HAVE_NET_IF_UTUN_H + +/* Helper functions that tries to open utun device + return -2 on early initialization failures (utun not supported + at all (old OS X) and -1 on initlization failure of utun + device (utun works but utunX is already used */ +static +int utun_open_helper (struct ctl_info ctlInfo, int utunnum) +{ + struct sockaddr_ctl sc; + int fd; + + fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + + if (fd < 0) + { + msg (M_INFO, "Opening utun (%s): %s", "socket(SYSPROTO_CONTROL)", + strerror (errno)); + return -2; + } + + if (ioctl(fd, CTLIOCGINFO, &ctlInfo) == -1) + { + close (fd); + msg (M_INFO, "Opening utun (%s): %s", "ioctl(CTLIOCGINFO)", + strerror (errno)); + return -2; + } + + + sc.sc_id = ctlInfo.ctl_id; + sc.sc_len = sizeof(sc); + sc.sc_family = AF_SYSTEM; + sc.ss_sysaddr = AF_SYS_CONTROL; + + sc.sc_unit = utunnum+1; + + + /* If the connect is successful, a utun%d device will be created, where "%d" + * is (sc.sc_unit - 1) */ + + if (connect (fd, (struct sockaddr *)&sc, sizeof(sc)) < 0) + { + msg (M_INFO, "Opening utun (%s): %s", "connect(AF_SYS_CONTROL)", + strerror (errno)); + close(fd); + return -1; + } + + set_nonblock (fd); + set_cloexec (fd); /* don't pass fd to scripts */ + + return fd; +} + +void +open_darwin_utun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) +{ + struct ctl_info ctlInfo; + int fd; + char utunname[20]; + int utunnum =-1; + socklen_t utunname_len = sizeof(utunname); + + /* dev_node is simply utun, do the normal dynamic utun + * otherwise try to parse the utun number */ + if (dev_node && !strcmp ("utun", dev_node)==0) + { + if (!sscanf (dev_node, "utun%d", &utunnum)==1) + msg (M_FATAL, "Cannot parse 'dev-node %s' please use 'dev-node utunX'" + "to use a utun device number X", dev_node); + } + + + + CLEAR (ctlInfo); + if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name)) >= + sizeof(ctlInfo.ctl_name)) + { + msg (M_ERR, "Opening utun: UTUN_CONTROL_NAME too long"); + } + + /* try to open first available utun device if no specific utun is requested */ + if (utunnum == -1) + { + for (utunnum=0; utunnum<255; utunnum++) + { + fd = utun_open_helper (ctlInfo, utunnum); + /* Break if the fd is valid, + * or if early initalization failed (-2) */ + if (fd !=-1) + break; + } + } + else + { + fd = utun_open_helper (ctlInfo, utunnum); + } + + /* opening an utun device failed */ + tt->fd = fd; + + if (fd < 0) + return; + + /* Retrieve the assigned interface name. */ + if (getsockopt (fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len)) + msg (M_ERR | M_ERRNO, "Error retrieving utun interface name"); + + tt->actual_name = string_alloc (utunname, NULL); + + msg (M_INFO, "Opened utun device %s", utunname); + tt->is_utun = true; +} + +#endif + void open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) { - open_tun_generic (dev, dev_type, dev_node, true, true, tt); +#ifdef HAVE_NET_IF_UTUN_H + /* If dev_node does not start start with utun assume regular tun/tap */ + if ((!dev_node && tt->type==DEV_TYPE_TUN) || + (dev_node && !strncmp (dev_node, "utun", 4))) + { + + /* Check if user has specific dev_type tap and forced utun with + dev-node utun */ + if (tt->type!=DEV_TYPE_TUN) + msg (M_FATAL, "Cannot use utun devices with --dev-type %s", + dev_type_string (dev, dev_type)); + + /* Try utun first and fall back to normal tun if utun fails + and dev_node is not specified */ + open_darwin_utun(dev, dev_type, dev_node, tt); + + if (!tt->is_utun) + { + if (!dev_node) + { + /* No explicit utun and utun failed, try the generic way) */ + msg (M_INFO, "Failed to open utun device. Falling back to /dev/tun device"); + open_tun_generic (dev, dev_type, NULL, true, true, tt); + } + else + { + /* Specific utun device or generic utun request with no tun + fall back failed, consider this a fatal failure */ + msg (M_FATAL, "Cannot open utun device"); + } + } + } + else +#endif + { + + /* Use plain dev-node tun to select /dev/tun style + * Unset dev_node variable prior to passing to open_tun_generic to + * let open_tun_generic pick the first available tun device */ + + if (dev_node && strcmp (dev_node, "tun")==0) + dev_node=NULL; + + open_tun_generic (dev, dev_type, dev_node, true, true, tt); + } } void @@ -2503,13 +2697,23 @@ close_tun (struct tuntap* tt) int write_tun (struct tuntap* tt, uint8_t *buf, int len) { - return write (tt->fd, buf, len); +#ifdef HAVE_NET_IF_UTUN_H + if (tt->is_utun) + return write_tun_header (tt, buf, len); + else +#endif + return write (tt->fd, buf, len); } int read_tun (struct tuntap* tt, uint8_t *buf, int len) { - return read (tt->fd, buf, len); +#ifdef HAVE_NET_IF_UTUN_H + if (tt->is_utun) + return read_tun_header (tt, buf, len); + else +#endif + return read (tt->fd, buf, len); } #elif defined(WIN32) @@ -2854,9 +3058,9 @@ get_panel_reg (struct gc_arena *gc) char enum_name[256]; char connection_string[256]; HKEY connection_key; - char name_data[256]; + WCHAR name_data[256]; DWORD name_type; - const char name_string[] = "Name"; + const WCHAR name_string[] = L"Name"; len = sizeof (enum_name); status = RegEnumKeyEx( @@ -2890,12 +3094,12 @@ get_panel_reg (struct gc_arena *gc) else { len = sizeof (name_data); - status = RegQueryValueEx( + status = RegQueryValueExW( connection_key, name_string, NULL, &name_type, - name_data, + (LPBYTE) name_data, &len); if (status != ERROR_SUCCESS || name_type != REG_SZ) @@ -2903,10 +3107,15 @@ get_panel_reg (struct gc_arena *gc) NETWORK_CONNECTIONS_KEY, connection_string, name_string); else { + int n; + LPSTR name; struct panel_reg *reg; ALLOC_OBJ_CLEAR_GC (reg, struct panel_reg, gc); - reg->name = string_alloc (name_data, gc); + n = WideCharToMultiByte (CP_UTF8, 0, name_data, -1, NULL, 0, NULL, NULL); + name = gc_malloc (n, false, gc); + WideCharToMultiByte (CP_UTF8, 0, name_data, -1, name, n, NULL, NULL); + reg->name = name; reg->guid = string_alloc (enum_name, gc); /* link into return list */ @@ -3116,7 +3325,7 @@ static void at_least_one_tap_win (const struct tap_reg *tap_reg) { if (!tap_reg) - msg (M_FATAL, "There are no TAP-Windows adapters on this system. You should be able to create a TAP-Windows adapter by going to Start -> All Programs -> " PACKAGE_NAME " -> Add a new TAP-Windows virtual ethernet adapter."); + msg (M_FATAL, "There are no TAP-Windows adapters on this system. You should be able to create a TAP-Windows adapter by going to Start -> All Programs -> TAP-Windows -> Utilities -> Add a new TAP-Windows virtual ethernet adapter."); } /* diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index c3fc62e..085d6a3 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -181,6 +181,9 @@ struct tuntap int ip_fd; #endif +#ifdef HAVE_NET_IF_UTUN_H + bool is_utun; +#endif /* used for printing status info only */ unsigned int rwflags_debug; diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index 178e2c3..13fd881 100644 --- a/src/openvpn/win32.c +++ b/src/openvpn/win32.c @@ -996,19 +996,27 @@ set_win_sys_path_via_env (struct env_set *es) const char * win_get_tempdir() { - static char buf[MAX_PATH]; - char *tmpdir = buf; - - CLEAR(buf); - - if (!GetTempPath(sizeof(buf),buf)) { - /* Warn if we can't find a valid temporary directory, which should - * be unlikely. - */ - msg (M_WARN, "Could not find a suitable temporary directory." - " (GetTempPath() failed). Consider to use --tmp-dir"); - tmpdir = NULL; - } + static char tmpdir[MAX_PATH]; + WCHAR wtmpdir[MAX_PATH]; + + if (!GetTempPathW(_countof(wtmpdir), wtmpdir)) + { + /* Warn if we can't find a valid temporary directory, which should + * be unlikely. + */ + msg (M_WARN, "Could not find a suitable temporary directory." + " (GetTempPath() failed). Consider using --tmp-dir"); + return NULL; + } + + if (WideCharToMultiByte (CP_UTF8, 0, wtmpdir, -1, NULL, 0, NULL, NULL) > sizeof (tmpdir)) + { + msg (M_WARN, "Could not get temporary directory. Path is too long." + " Consider using --tmp-dir"); + return NULL; + } + + WideCharToMultiByte (CP_UTF8, 0, wtmpdir, -1, tmpdir, sizeof (tmpdir), NULL, NULL); return tmpdir; } #endif diff --git a/tests/t_client.sh b/tests/t_client.sh index 26df138..f34eccc 100755 --- a/tests/t_client.sh +++ b/tests/t_client.sh @@ -86,12 +86,12 @@ fail() get_ifconfig_route() { # linux / iproute2? (-> if configure got a path) - if [ -n "/sbin/ip" ] + if [ -n "/bin/ip" ] then echo "-- linux iproute2 --" - /sbin/ip addr show | grep -v valid_lft - /sbin/ip route show - /sbin/ip -o -6 route show | grep -v ' cache' | sed -e 's/expires [0-9]*sec//' + /bin/ip addr show | grep -v valid_lft + /bin/ip route show + /bin/ip -o -6 route show | grep -v ' cache' | sed -E -e 's/ expires [0-9]*sec//' -e 's/ (mtu|hoplimit|cwnd) [0-9]+//g' -e 's/ (rtt|rttvar) [0-9]+ms//g' return fi diff --git a/tests/t_client.sh.in b/tests/t_client.sh.in index 189eecc..64bb5fd 100755 --- a/tests/t_client.sh.in +++ b/tests/t_client.sh.in @@ -91,7 +91,7 @@ get_ifconfig_route() echo "-- linux iproute2 --" @IPROUTE@ addr show | grep -v valid_lft @IPROUTE@ route show - @IPROUTE@ -o -6 route show | grep -v ' cache' | sed -e 's/expires [0-9]*sec//' + @IPROUTE@ -o -6 route show | grep -v ' cache' | sed -E -e 's/ expires [0-9]*sec//' -e 's/ (mtu|hoplimit|cwnd) [0-9]+//g' -e 's/ (rtt|rttvar) [0-9]+ms//g' return fi diff --git a/version.m4 b/version.m4 index ed29b30..9c14626 100644 --- a/version.m4 +++ b/version.m4 @@ -1,9 +1,9 @@ dnl define the OpenVPN version define([PRODUCT_NAME], [OpenVPN]) define([PRODUCT_TARNAME], [openvpn]) -define([PRODUCT_VERSION], [2.3.2]) +define([PRODUCT_VERSION], [2.3.3]) define([PRODUCT_BUGREPORT], [openvpn-users@lists.sourceforge.net]) -define([PRODUCT_VERSION_RESOURCE], [2,3,2,0]) +define([PRODUCT_VERSION_RESOURCE], [2,3,3,0]) dnl define the TAP version define([PRODUCT_TAP_WIN_COMPONENT_ID], [tap0901]) define([PRODUCT_TAP_WIN_MIN_MAJOR], [9]) -- cgit v1.2.3