diff options
author | Alberto Gonzalez Iniesta <agi@inittab.org> | 2016-01-20 12:01:07 +0100 |
---|---|---|
committer | Alberto Gonzalez Iniesta <agi@inittab.org> | 2016-01-20 12:01:07 +0100 |
commit | 19eab1fe2df20e38ea64d7a642d3e21c957082b8 (patch) | |
tree | fad602b603321d3e0e45807f8abb4f6c670a6cf2 | |
parent | 35807e5652390e8b2fd66b9051f3b41c9488302e (diff) | |
parent | 9653b1bffea4e96c1eb7c1814e8bed21fea62321 (diff) |
Merge tag 'upstream/2.3.10'
Upstream version 2.3.10
61 files changed, 1739 insertions, 569 deletions
@@ -1,6 +1,107 @@ OpenVPN Change Log Copyright (C) 2002-2015 OpenVPN Technologies, Inc. <sales@openvpn.net> +2016.01.04 -- Version 2.3.10 +Gert Doering (1): + Prepare for v2.3.10 release, list PolarSSL 1.2 to 1.3 upgrade + +Jan Just Keijser (1): + Make certificate expiry warning patch (091edd8e299686) work on OpenSSL 1.0.1 and earlier. + +Lev Stipakov (1): + Repair IPv6 netsh calls if Win XP is detected + +Phillip Smith (1): + Use bob.example.com and alice.example.com to improve clarity of documentation + +Steffan Karger (6): + Remove unused variables from ssl_verify_polarssl.c's x509_get_serial() + Upgrade OpenVPN 2.3 to PolarSSL 1.3 + Warn user if their certificate has expired + Make assert_failed() print the failed condition + cleanup: get rid of httpdigest.c type warnings + Fix regression in setups without a client certificate + +Yegor Yefremov (1): + polarssl: fix unreachable code + +2015.12.15 -- Version 2.3.9 +Arne Schwabe (7): + Show extra-certs in current parameters. + Fix commit a3160fc1bd7368395745b9cee6e40fb819f5564c + Do not set the buffer size by default but rely on the operation system default. + Remove --enable-password-save option + Reflect enable-password-save change in documentation + Also remove second instance of enable-password-save in the man page + Detect config lines that are too long and give a warning/error + +Boris Lytochkin (1): + Log serial number of revoked certificate + +Christos Trochalakis (1): + Adjust server-ipv6 documentation + +David Sommerseth (1): + Avoid partial authentication state when using --disabled in CCD configs + +Fish (1): + Make "block-outside-dns" option platform agnostic + +Gert Doering (7): + Un-break --auth-user-pass on windows + Replace unaligned 16bit access to TCP MSS value with bytewise access + Repair test_local_addr() on WIN32 + Fix possible heap overflow on read accessing getaddrinfo() result. + Fix FreeBSD-specific mishandling of gc arena pointer in create_arbitrary_remote() + remove unused gc_arena in FreeBSD close_tun() + Fix isatty() check for good. + +Heiko Hund (1): + put virtual IPv6 addresses into env + +Lev Stipakov (5): + Use adapter index instead of name for windows IPv6 interface config + Client-side part for server restart notification + Use adapter index for add/delete_route_ipv6 + Pass adapter index to up/down scripts + Fix VS2013 compilation + +Lukasz Kutyla (1): + Fix privilege drop if first connection attempt fails + +Michal Ludvig (1): + Support for username-only auth file. + +Samuli Seppänen (2): + Add CONTRIBUTING.rst + Updates to Changes.rst + +Selva Nair (4): + Fix termination when windows suspends/sleeps + Do not hard-code windows systemroot in env_block + Handle ctrl-C and ctrl-break events on Windows + Unbreak read username password from management + +Steffan Karger (11): + Replace strdup() calls for string_alloc() calls + Check return value of ms_error_text() + Increase control channel packet size for faster handshakes + hardening: add insurance to exit on a failed ASSERT() + Fix memory leak in auth-pam plugin + Fix (potential) memory leak in init_route_list() + Fix unintialized variable in plugin_vlog() + Add macro to ensure we exit on fatal errors + Fix memory leak in add_option() by simplifying get_ipv6_addr + openssl: properly check return value of RAND_bytes() + Fix rand_bytes return value checking + +ValdikSS (1): + Add Windows DNS Leak fix using WFP ('block-outside-dns') + +janjust (1): + Fix "White space before end tags can break the config parser" + + 2015.08.03 -- Version 2.3.8 Arne Schwabe (2): Report missing endtags of inline files as warnings diff --git a/README.polarssl b/README.polarssl index 06f30bf..d34d44a 100644 --- a/README.polarssl +++ b/README.polarssl @@ -7,7 +7,7 @@ To Build and Install, make make install -This version depends on PolarSSL 1.2 (and requires at least 1.2.10). +This version depends on PolarSSL 1.3 (and requires at least 1.3.8). ************************************************************************* diff --git a/config-msvc.h b/config-msvc.h index fa99384..ae43a5f 100644 --- a/config-msvc.h +++ b/config-msvc.h @@ -45,6 +45,7 @@ #define HAVE_SYS_STAT_H 1 #define HAVE_LZO_LZO1X_H 1 #define HAVE_LZO_LZOUTIL_H 1 +#define HAVE_VERSIONHELPERS_H 1 #define HAVE_ACCESS 1 #define HAVE_CHDIR 1 diff --git a/config.h.in b/config.h.in index 2c7696c..ac1517b 100644 --- a/config.h.in +++ b/config.h.in @@ -66,9 +66,6 @@ /* Enable OFB and CFB cipher modes */ #undef ENABLE_OFB_CFB_MODE -/* Allow --askpass and --auth-user-pass passwords to be read from a file */ -#undef ENABLE_PASSWORD_SAVE - /* Enable internal packet filter */ #undef ENABLE_PF @@ -538,6 +535,9 @@ /* Define to 1 if you have the `unlink' function. */ #undef HAVE_UNLINK +/* Define to 1 if you have the <versionhelpers.h> header file. */ +#undef HAVE_VERSIONHELPERS_H + /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK @@ -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.8. +# Generated by GNU Autoconf 2.69 for OpenVPN 2.3.10. # # Report bugs to <openvpn-users@lists.sourceforge.net>. # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='OpenVPN' PACKAGE_TARNAME='openvpn' -PACKAGE_VERSION='2.3.8' -PACKAGE_STRING='OpenVPN 2.3.8' +PACKAGE_VERSION='2.3.10' +PACKAGE_STRING='OpenVPN 2.3.10' PACKAGE_BUGREPORT='openvpn-users@lists.sourceforge.net' PACKAGE_URL='' @@ -827,7 +827,6 @@ enable_multihome enable_port_share enable_debug enable_small -enable_password_save enable_iproute2 enable_def_auth enable_pf @@ -1427,7 +1426,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.8 to adapt to many kinds of systems. +\`configure' configures OpenVPN 2.3.10 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1497,7 +1496,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OpenVPN 2.3.8:";; + short | recursive ) echo "Configuration of OpenVPN 2.3.10:";; esac cat <<\_ACEOF @@ -1542,8 +1541,6 @@ Optional Features: 7+ messages) [default=yes] --enable-small enable smaller executable size (disable OCC, usage message, and verb 4 parm list) [default=no] - --enable-password-save allow --askpass and --auth-user-pass passwords to be - read from a file [default=no] --enable-iproute2 enable support for iproute2 [default=no] --disable-def-auth disable deferred authentication [default=yes] --disable-pf disable internal packet filter [default=yes] @@ -1701,7 +1698,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OpenVPN configure 2.3.8 +OpenVPN configure 2.3.10 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2483,7 +2480,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.8, which was +It was created by OpenVPN $as_me 2.3.10, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2847,7 +2844,7 @@ if test -z "${htmldir}"; then fi -$as_echo "#define OPENVPN_VERSION_RESOURCE 2,3,8,0" >>confdefs.h +$as_echo "#define OPENVPN_VERSION_RESOURCE 2,3,10,0" >>confdefs.h ac_aux_dir= @@ -3371,7 +3368,7 @@ fi # Define the identity of the package. PACKAGE='openvpn' - VERSION='2.3.8' + VERSION='2.3.10' cat >>confdefs.h <<_ACEOF @@ -5194,15 +5191,6 @@ else fi -# Check whether --enable-password-save was given. -if test "${enable_password_save+set}" = set; then : - enableval=$enable_password_save; -else - enable_password_save="no" - -fi - - # Check whether --enable-iproute2 was given. if test "${enable_iproute2+set}" = set; then : enableval=$enable_iproute2; @@ -14399,6 +14387,7 @@ for ac_header in \ netinet/in.h netinet/in_systm.h \ netinet/tcp.h arpa/inet.h netdb.h \ windows.h winsock2.h ws2tcpip.h \ + versionhelpers.h \ do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -16185,7 +16174,7 @@ int main () { -#if POLARSSL_VERSION_NUMBER < 0x01020A00 || POLARSSL_VERSION_NUMBER >= 0x01030000 +#if POLARSSL_VERSION_NUMBER < 0x01030800 || POLARSSL_VERSION_NUMBER >= 0x01040000 #error invalid version #endif @@ -16198,7 +16187,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.x required and must be 1.2.10 or later" "$LINENO" 5 + as_fn_error $? "PolarSSL 1.3.x required and must be 1.3.8 or later" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext @@ -16786,9 +16775,6 @@ $as_echo "#define ENABLE_PF 1" >>confdefs.h test "${enable_strict_options}" = "yes" && $as_echo "#define ENABLE_STRICT_OPTIONS_CHECK 1" >>confdefs.h -test "${enable_password_save}" = "yes" && -$as_echo "#define ENABLE_PASSWORD_SAVE 1" >>confdefs.h - case "${with_crypto_library}" in openssl) @@ -17630,7 +17616,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.8, which was +This file was extended by OpenVPN $as_me 2.3.10, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17696,7 +17682,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.8 +OpenVPN config.status 2.3.10 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 54b01a4..773cded 100644 --- a/configure.ac +++ b/configure.ac @@ -180,13 +180,6 @@ AC_ARG_ENABLE( ) AC_ARG_ENABLE( - [password-save], - [AS_HELP_STRING([--enable-password-save], [allow --askpass and --auth-user-pass passwords to be read from a file @<:@default=no@:>@])], - , - [enable_password_save="no"] -) - -AC_ARG_ENABLE( [iproute2], [AS_HELP_STRING([--enable-iproute2], [enable support for iproute2 @<:@default=no@:>@])], , @@ -430,6 +423,7 @@ AC_CHECK_HEADERS([ \ netinet/in.h netinet/in_systm.h \ netinet/tcp.h arpa/inet.h netdb.h \ windows.h winsock2.h ws2tcpip.h \ + versionhelpers.h \ ]) AC_CHECK_HEADERS([ \ sys/time.h sys/ioctl.h sys/stat.h \ @@ -832,13 +826,13 @@ if test "${with_crypto_library}" = "polarssl" ; then #include <polarssl/version.h> ]], [[ -#if POLARSSL_VERSION_NUMBER < 0x01020A00 || POLARSSL_VERSION_NUMBER >= 0x01030000 +#if POLARSSL_VERSION_NUMBER < 0x01030800 || POLARSSL_VERSION_NUMBER >= 0x01040000 #error invalid version #endif ]] )], [AC_MSG_RESULT([ok])], - [AC_MSG_ERROR([PolarSSL 1.2.x required and must be 1.2.10 or later])] + [AC_MSG_ERROR([PolarSSL 1.3.x required and must be 1.3.8 or later])] ) polarssl_with_pkcs11="no" @@ -977,7 +971,6 @@ test "${enable_port_share}" = "yes" && AC_DEFINE([ENABLE_PORT_SHARE], [1], [Enab test "${enable_def_auth}" = "yes" && AC_DEFINE([ENABLE_DEF_AUTH], [1], [Enable deferred authentication]) test "${enable_pf}" = "yes" && AC_DEFINE([ENABLE_PF], [1], [Enable internal packet filter]) test "${enable_strict_options}" = "yes" && AC_DEFINE([ENABLE_STRICT_OPTIONS_CHECK], [1], [Enable strict options check between peers]) -test "${enable_password_save}" = "yes" && AC_DEFINE([ENABLE_PASSWORD_SAVE], [1], [Allow --askpass and --auth-user-pass passwords to be read from a file]) case "${with_crypto_library}" in openssl) diff --git a/distro/rpm/openvpn.spec b/distro/rpm/openvpn.spec index 8f7f3af..080d0a7 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.8 +Version: 2.3.10 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 203dd46..25ea9f9 100644 --- a/doc/openvpn.8 +++ b/doc/openvpn.8 @@ -1119,8 +1119,8 @@ When used with .B \-\-client or .B \-\-pull, -accept options pushed by server EXCEPT for routes and dhcp options -like DNS servers. +accept options pushed by server EXCEPT for routes, block-outside-dns and dhcp +options like DNS servers. When used on the client, this option effectively bars the server from adding routes to the client's routing table, @@ -1412,12 +1412,12 @@ connection problems) with the following options: .TP .B \-\-sndbuf size Set the TCP/UDP socket send buffer size. -Currently defaults to 65536 bytes. +Defaults to operation system default. .\"********************************************************* .TP .B \-\-rcvbuf size Set the TCP/UDP socket receive buffer size. -Currently defaults to 65536 bytes. +Defaults to operation system default. .\"********************************************************* .TP .B \-\-mark value @@ -3683,10 +3683,8 @@ over the client's routing table. .B \-\-auth\-user\-pass [up] Authenticate with server using username/password. .B up -is a file containing username/password on 2 lines (Note: OpenVPN -will only read passwords from a file if it has been built -with the \-\-enable\-password\-save configure option, or on Windows -by defining ENABLE_PASSWORD_SAVE in win/settings.in). +is a file containing username/password on 2 lines. If the +password line is missing, OpenVPN will prompt for one. If .B up @@ -4775,10 +4773,7 @@ is specified, read the password from the first line of .B file. Keep in mind that storing your password in a file to a certain extent invalidates the extra security provided by -using an encrypted key (Note: OpenVPN -will only read passwords from a file if it has been built -with the \-\-enable\-password\-save configure option, or on Windows -by defining ENABLE_PASSWORD_SAVE in win/settings.in). +using an encrypted key. .\"********************************************************* .TP .B \-\-auth\-nocache @@ -5453,6 +5448,14 @@ adapter list to the syslog or log file after the TUN/TAP adapter has been brought up and any routes have been added. .\"********************************************************* .TP +.B \-\-block\-outside\-dns +Block DNS servers on other network adapters to prevent +DNS leaks. This option prevents any application from accessing +TCP or UDP port 53 except one inside the tunnel. It uses +Windows Filtering Platform (WFP) and works on Windows Vista or +later. +.\"********************************************************* +.TP .B \-\-dhcp\-renew Ask Windows to renew the TAP adapter lease on startup. This option is normally unnecessary, as Windows automatically @@ -5818,6 +5821,17 @@ or script execution. .\"********************************************************* .TP +.B dev_idx +On Windows, the device index of the TUN/TAP adapter (to +be used in netsh.exe calls which sometimes just do not work +right with interface names). +Set prior to +.B \-\-up +or +.B \-\-down +script execution. +.\"********************************************************* +.TP .B foreign_option_{n} An option pushed via .B \-\-push @@ -6454,13 +6468,13 @@ for use with OpenVPN. .SS VPN Address Setup: For purposes of our example, our two machines will be called -.B may.kg +.B bob.example.com and -.B june.kg. +.B alice.example.com. If you are constructing a VPN over the internet, then replace -.B may.kg +.B bob.example.com and -.B june.kg +.B alice.example.com with the internet hostname or IP address that each machine will use to contact the other over the internet. @@ -6468,8 +6482,8 @@ Now we will choose the tunnel endpoints. Tunnel endpoints are private IP addresses that only have meaning in the context of the VPN. Each machine will use the tunnel endpoint of the other machine to access it over the VPN. In our example, -the tunnel endpoint for may.kg -will be 10.4.0.1 and for june.kg, 10.4.0.2. +the tunnel endpoint for bob.example.com +will be 10.4.0.1 and for alice.example.com, 10.4.0.2. Once the VPN is established, you have essentially created a secure alternate path between the two hosts @@ -6478,16 +6492,16 @@ control which network traffic passes between the hosts (a) over the VPN or (b) independently of the VPN, by choosing whether to use (a) the VPN endpoint address or (b) the public internet address, -to access the remote host. For example if you are on may.kg and you wish to connect to june.kg +to access the remote host. For example if you are on bob.example.com and you wish to connect to alice.example.com via .B ssh without using the VPN (since .B ssh has its own built-in security) you would use the command -.B ssh june.kg. +.B ssh alice.example.com. However in the same scenario, you could also use the command .B telnet 10.4.0.2 -to create a telnet session with june.kg over the VPN, that would +to create a telnet session with alice.example.com over the VPN, that would use the VPN to secure the session rather than .B ssh. @@ -6502,21 +6516,21 @@ you will get a weird feedback loop. .\"********************************************************* .SS Example 1: A simple tunnel without security .LP -On may: +On bob: .IP -.B openvpn \-\-remote june.kg \-\-dev tun1 \-\-ifconfig 10.4.0.1 10.4.0.2 \-\-verb 9 +.B openvpn \-\-remote alice.example.com \-\-dev tun1 \-\-ifconfig 10.4.0.1 10.4.0.2 \-\-verb 9 .LP -On june: +On alice: .IP -.B openvpn \-\-remote may.kg \-\-dev tun1 \-\-ifconfig 10.4.0.2 10.4.0.1 \-\-verb 9 +.B openvpn \-\-remote bob.example.com \-\-dev tun1 \-\-ifconfig 10.4.0.2 10.4.0.1 \-\-verb 9 .LP Now verify the tunnel is working by pinging across the tunnel. .LP -On may: +On bob: .IP .B ping 10.4.0.2 .LP -On june: +On alice: .IP .B ping 10.4.0.1 .LP @@ -6529,7 +6543,7 @@ program. Omit the option to have OpenVPN run quietly. .\"********************************************************* .SS Example 2: A tunnel with static-key security (i.e. using a pre-shared secret) -First build a static key on may. +First build a static key on bob. .IP .B openvpn \-\-genkey \-\-secret key .LP @@ -6538,39 +6552,39 @@ This command will build a random key file called (in ascii format). Now copy .B key -to june over a secure medium such as by +to alice over a secure medium such as by using the .BR scp (1) program. .LP -On may: +On bob: .IP -.B openvpn \-\-remote june.kg \-\-dev tun1 \-\-ifconfig 10.4.0.1 10.4.0.2 \-\-verb 5 \-\-secret key +.B openvpn \-\-remote alice.example.com \-\-dev tun1 \-\-ifconfig 10.4.0.1 10.4.0.2 \-\-verb 5 \-\-secret key .LP -On june: +On alice: .IP -.B openvpn \-\-remote may.kg \-\-dev tun1 \-\-ifconfig 10.4.0.2 10.4.0.1 \-\-verb 5 \-\-secret key +.B openvpn \-\-remote bob.example.com \-\-dev tun1 \-\-ifconfig 10.4.0.2 10.4.0.1 \-\-verb 5 \-\-secret key .LP Now verify the tunnel is working by pinging across the tunnel. .LP -On may: +On bob: .IP .B ping 10.4.0.2 .LP -On june: +On alice: .IP .B ping 10.4.0.1 .\"********************************************************* .SS Example 3: A tunnel with full TLS-based security For this test, we will designate -.B may +.B bob as the TLS client and -.B june +.B alice as the TLS server. .I Note that client or server designation only has meaning for the TLS subsystem. It has no bearing on OpenVPN's peer-to-peer, UDP-based communication model. First, build a separate certificate/key pair -for both may and june (see above where +for both bob and alice (see above where .B \-\-cert is discussed for more info). Then construct Diffie Hellman parameters (see above where @@ -6585,21 +6599,21 @@ client.crt and server.crt. For Diffie Hellman parameters you can use the included file dh1024.pem. .I Note that all client, server, and certificate authority certificates and keys included in the OpenVPN distribution are totally insecure and should be used for testing only. .LP -On may: +On bob: .IP -.B openvpn \-\-remote june.kg \-\-dev tun1 \-\-ifconfig 10.4.0.1 10.4.0.2 \-\-tls\-client \-\-ca ca.crt \-\-cert client.crt \-\-key client.key \-\-reneg\-sec 60 \-\-verb 5 +.B openvpn \-\-remote alice.example.com \-\-dev tun1 \-\-ifconfig 10.4.0.1 10.4.0.2 \-\-tls\-client \-\-ca ca.crt \-\-cert client.crt \-\-key client.key \-\-reneg\-sec 60 \-\-verb 5 .LP -On june: +On alice: .IP -.B openvpn \-\-remote may.kg \-\-dev tun1 \-\-ifconfig 10.4.0.2 10.4.0.1 \-\-tls\-server \-\-dh dh1024.pem \-\-ca ca.crt \-\-cert server.crt \-\-key server.key \-\-reneg\-sec 60 \-\-verb 5 +.B openvpn \-\-remote bob.example.com \-\-dev tun1 \-\-ifconfig 10.4.0.2 10.4.0.1 \-\-tls\-server \-\-dh dh1024.pem \-\-ca ca.crt \-\-cert server.crt \-\-key server.key \-\-reneg\-sec 60 \-\-verb 5 .LP Now verify the tunnel is working by pinging across the tunnel. .LP -On may: +On bob: .IP .B ping 10.4.0.2 .LP -On june: +On alice: .IP .B ping 10.4.0.1 .LP @@ -6619,12 +6633,12 @@ option to use OpenVPN's default key renegotiation interval of one hour. .SS Routing: Assuming you can ping across the tunnel, the next step is to route a real subnet over -the secure tunnel. Suppose that may and june have two network +the secure tunnel. Suppose that bob and alice have two network interfaces each, one connected to the internet, and the other to a private network. Our goal is to securely connect -both private networks. We will assume that may's private subnet -is 10.0.0.0/24 and june's is 10.0.1.0/24. +both private networks. We will assume that bob's private subnet +is 10.0.0.0/24 and alice's is 10.0.1.0/24. .LP First, ensure that IP forwarding is enabled on both peers. On Linux, enable routing: @@ -6635,11 +6649,11 @@ and enable TUN packet forwarding through the firewall: .IP .B iptables \-A FORWARD \-i tun+ \-j ACCEPT .LP -On may: +On bob: .IP .B route add \-net 10.0.1.0 netmask 255.255.255.0 gw 10.4.0.2 .LP -On june: +On alice: .IP .B route add \-net 10.0.0.0 netmask 255.255.255.0 gw 10.4.0.1 .LP diff --git a/include/openvpn-plugin.h b/include/openvpn-plugin.h index 03da92a..5f2d407 100644 --- a/include/openvpn-plugin.h +++ b/include/openvpn-plugin.h @@ -29,10 +29,10 @@ #ifdef ENABLE_SSL #ifdef ENABLE_CRYPTO_POLARSSL -#include <polarssl/x509.h> +#include <polarssl/x509_crt.h> #ifndef __OPENVPN_X509_CERT_T_DECLARED #define __OPENVPN_X509_CERT_T_DECLARED -typedef x509_cert openvpn_x509_cert_t; +typedef x509_crt openvpn_x509_cert_t; #endif #else #include <openssl/x509.h> diff --git a/src/compat/Makefile.am b/src/compat/Makefile.am index 7ad4452..273389e 100644 --- a/src/compat/Makefile.am +++ b/src/compat/Makefile.am @@ -26,4 +26,5 @@ libcompat_la_SOURCES = \ compat-gettimeofday.c \ compat-daemon.c \ compat-inet_ntop.c \ - compat-inet_pton.c + compat-inet_pton.c \ + compat-versionhelpers.h diff --git a/src/compat/Makefile.in b/src/compat/Makefile.in index 8c5111e..bde9236 100644 --- a/src/compat/Makefile.in +++ b/src/compat/Makefile.in @@ -355,7 +355,8 @@ libcompat_la_SOURCES = \ compat-gettimeofday.c \ compat-daemon.c \ compat-inet_ntop.c \ - compat-inet_pton.c + compat-inet_pton.c \ + compat-versionhelpers.h all: all-am diff --git a/src/compat/compat-versionhelpers.h b/src/compat/compat-versionhelpers.h new file mode 100644 index 0000000..f634091 --- /dev/null +++ b/src/compat/compat-versionhelpers.h @@ -0,0 +1,81 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#ifndef _INC_VERSIONHELPERS +#define _INC_VERSIONHELPERS + +#include <winapifamily.h> + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && !defined(__WIDL__) + +#ifdef __cplusplus +#define VERSIONHELPERAPI inline bool +#else +#define VERSIONHELPERAPI FORCEINLINE BOOL +#endif + +#define _WIN32_WINNT_WINBLUE 0x0603 + +VERSIONHELPERAPI IsWindowsVersionOrGreater(WORD major, WORD minor, WORD servpack) +{ + OSVERSIONINFOEXW vi = {sizeof(vi),major,minor,0,0,{0},servpack}; + return VerifyVersionInfoW(&vi, VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR, + VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0, + VER_MAJORVERSION,VER_GREATER_EQUAL), + VER_MINORVERSION,VER_GREATER_EQUAL), + VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)); +} + +VERSIONHELPERAPI IsWindowsXPOrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0); +} + +VERSIONHELPERAPI IsWindowsXPSP1OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1); +} + +VERSIONHELPERAPI IsWindowsXPSP2OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2); +} + +VERSIONHELPERAPI IsWindowsXPSP3OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3); +} + +VERSIONHELPERAPI IsWindowsVistaOrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0); +} + +VERSIONHELPERAPI IsWindowsVistaSP1OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1); +} + +VERSIONHELPERAPI IsWindowsVistaSP2OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2); +} + +VERSIONHELPERAPI IsWindows7OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0); +} + +VERSIONHELPERAPI IsWindows7SP1OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1); +} + +VERSIONHELPERAPI IsWindows8OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0); +} + +VERSIONHELPERAPI IsWindows8Point1OrGreater(void) { + return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0); +} + +VERSIONHELPERAPI IsWindowsServer(void) { + OSVERSIONINFOEXW vi = {sizeof(vi),0,0,0,0,{0},0,0,0,VER_NT_WORKSTATION}; + return !VerifyVersionInfoW(&vi, VER_PRODUCT_TYPE, VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL)); +} + +#endif +#endif diff --git a/src/compat/compat.vcxproj b/src/compat/compat.vcxproj index 42979c1..1dedb33 100644 --- a/src/compat/compat.vcxproj +++ b/src/compat/compat.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -20,10 +20,12 @@ <ConfigurationType>StaticLibrary</ConfigurationType> <CharacterSet>MultiByte</CharacterSet> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>StaticLibrary</ConfigurationType> <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 2e602f1..6d02fea 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -110,7 +110,7 @@ openvpn_SOURCES = \ status.c status.h \ syshead.h \ tun.c tun.h \ - win32.h win32.c \ + win32.h win32_wfp.h win32.c \ cryptoapi.h cryptoapi.c openvpn_LDADD = \ $(top_builddir)/src/compat/libcompat.la \ @@ -123,5 +123,5 @@ openvpn_LDADD = \ $(OPTIONAL_DL_LIBS) if WIN32 openvpn_SOURCES += openvpn_win32_resources.rc -openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm +openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lrpcrt4 -lwinmm endif diff --git a/src/openvpn/Makefile.in b/src/openvpn/Makefile.in index ea9547c..8519969 100644 --- a/src/openvpn/Makefile.in +++ b/src/openvpn/Makefile.in @@ -106,7 +106,7 @@ DIST_COMMON = $(top_srcdir)/build/ltrc.inc $(srcdir)/Makefile.in \ @WIN32_TRUE@am__append_1 = -municode -UUNICODE sbin_PROGRAMS = openvpn$(EXEEXT) @WIN32_TRUE@am__append_2 = openvpn_win32_resources.rc -@WIN32_TRUE@am__append_3 = -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm +@WIN32_TRUE@am__append_3 = -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lrpcrt4 -lwinmm subdir = src/openvpn ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_emptyarray.m4 \ @@ -149,8 +149,8 @@ am__openvpn_SOURCES_DIST = base64.c base64.h basic.h buffer.c buffer.h \ ssl_verify.c ssl_verify.h ssl_verify_backend.h \ ssl_verify_openssl.c ssl_verify_openssl.h \ ssl_verify_polarssl.c ssl_verify_polarssl.h status.c status.h \ - syshead.h tun.c tun.h win32.h win32.c cryptoapi.h cryptoapi.c \ - openvpn_win32_resources.rc + syshead.h tun.c tun.h win32.h win32_wfp.h win32.c cryptoapi.h \ + cryptoapi.c openvpn_win32_resources.rc @WIN32_TRUE@am__objects_1 = openvpn_win32_resources.$(OBJEXT) am_openvpn_OBJECTS = base64.$(OBJEXT) buffer.$(OBJEXT) \ clinat.$(OBJEXT) crypto.$(OBJEXT) crypto_openssl.$(OBJEXT) \ @@ -452,8 +452,8 @@ openvpn_SOURCES = base64.c base64.h basic.h buffer.c buffer.h \ ssl_verify.c ssl_verify.h ssl_verify_backend.h \ ssl_verify_openssl.c ssl_verify_openssl.h \ ssl_verify_polarssl.c ssl_verify_polarssl.h status.c status.h \ - syshead.h tun.c tun.h win32.h win32.c cryptoapi.h cryptoapi.c \ - $(am__append_2) + syshead.h tun.c tun.h win32.h win32_wfp.h win32.c cryptoapi.h \ + cryptoapi.c $(am__append_2) openvpn_LDADD = $(top_builddir)/src/compat/libcompat.la \ $(SOCKETS_LIBS) $(OPTIONAL_LZO_LIBS) \ $(OPTIONAL_PKCS11_HELPER_LIBS) $(OPTIONAL_CRYPTO_LIBS) \ diff --git a/src/openvpn/buffer.h b/src/openvpn/buffer.h index d306a04..58f0601 100644 --- a/src/openvpn/buffer.h +++ b/src/openvpn/buffer.h @@ -873,7 +873,7 @@ gc_reset (struct gc_arena *a) } static inline void -check_malloc_return (void *p) +check_malloc_return (const void *p) { if (!p) out_of_memory (); diff --git a/src/openvpn/console.c b/src/openvpn/console.c index d66d408..e1d46c4 100644 --- a/src/openvpn/console.c +++ b/src/openvpn/console.c @@ -208,6 +208,19 @@ get_console_input (const char *prompt, const bool echo, char *input, const int c #if defined(WIN32) return get_console_input_win32 (prompt, echo, input, capacity); #elif defined(HAVE_GETPASS) + + /* did we --daemon'ize before asking for passwords? + * (in which case neither stdin or stderr are connected to a tty and + * /dev/tty can not be open()ed anymore) + */ + if ( !isatty(0) && !isatty(2) ) + { + int fd = open( "/dev/tty", O_RDWR ); + if ( fd < 0 ) + { msg(M_FATAL, "neither stdin nor stderr are a tty device and you have neither a controlling tty nor systemd - can't ask for '%s'. If you used --daemon, you need to use --askpass to make passphrase-protected keys work, and you can not use --auth-nocache.", prompt ); } + close(fd); + } + if (echo) { FILE *fp; diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index c2d5c27..400bf11 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -1383,7 +1383,7 @@ prng_bytes (uint8_t *output, int len) } } else - rand_bytes (output, len); + ASSERT (rand_bytes (output, len)); } /* an analogue to the random() function, but use prng_bytes */ diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c index 348bdee..4e195ce 100644 --- a/src/openvpn/crypto_openssl.c +++ b/src/openvpn/crypto_openssl.c @@ -378,7 +378,12 @@ show_available_engines () int rand_bytes(uint8_t *output, int len) { - return RAND_bytes (output, len); + if (unlikely(1 != RAND_bytes (output, len))) + { + msg(D_CRYPT_ERRORS, "RAND_bytes() failed"); + return 0; + } + return 1; } /* diff --git a/src/openvpn/crypto_polarssl.c b/src/openvpn/crypto_polarssl.c index af79029..24712ed 100644 --- a/src/openvpn/crypto_polarssl.c +++ b/src/openvpn/crypto_polarssl.c @@ -457,7 +457,7 @@ cipher_ctx_init (cipher_context_t *ctx, uint8_t *key, int key_len, void cipher_ctx_cleanup (cipher_context_t *ctx) { - cipher_free_ctx(ctx); + cipher_free(ctx); } int cipher_ctx_iv_length (const cipher_context_t *ctx) @@ -487,7 +487,12 @@ cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) int cipher_ctx_reset (cipher_context_t *ctx, uint8_t *iv_buf) { - return 0 == cipher_reset(ctx, iv_buf); + int retval = cipher_reset(ctx); + + if (0 == retval) + retval = cipher_set_iv(ctx, iv_buf, ctx->cipher_info->iv_size); + + return 0 == retval; } int cipher_ctx_update (cipher_context_t *ctx, uint8_t *dst, int *dst_len, @@ -614,7 +619,7 @@ void md_ctx_final (md_context_t *ctx, uint8_t *dst) { ASSERT(0 == md_finish(ctx, dst)); - ASSERT(0 == md_free_ctx(ctx)); + md_free(ctx); } @@ -645,7 +650,7 @@ hmac_ctx_init (md_context_t *ctx, const uint8_t *key, int key_len, const md_info void hmac_ctx_cleanup(md_context_t *ctx) { - ASSERT(0 == md_free_ctx(ctx)); + md_free(ctx); } int diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index b7fc11e..853c07b 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -46,6 +46,8 @@ #include <ctype.h> #include <assert.h> +#include "buffer.h" + /* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while * MinGW32-w64 defines all macros used. This is a hack around that problem. */ @@ -116,7 +118,7 @@ static char *ms_error_text(DWORD ms_err) (LPTSTR) &lpMsgBuf, 0, NULL); if (lpMsgBuf) { char *p; - rv = strdup(lpMsgBuf); + rv = string_alloc(lpMsgBuf, NULL); LocalFree(lpMsgBuf); /* trim to the left */ if (rv) @@ -162,6 +164,7 @@ static void err_put_ms_error(DWORD ms_err, int func, const char *file, int line) err_map[i].ms_err = ms_err; err_map[i].err = esd->error = i + 100; esd->string = ms_error_text(ms_err); + check_malloc_return(esd->string); ERR_load_strings(ERR_LIB_CRYPTOAPI, esd); ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line); break; diff --git a/src/openvpn/error.c b/src/openvpn/error.c index 6848425..f503cf4 100644 --- a/src/openvpn/error.c +++ b/src/openvpn/error.c @@ -397,9 +397,13 @@ dont_mute (unsigned int flags) } void -assert_failed (const char *filename, int line) +assert_failed (const char *filename, int line, const char *condition) { - msg (M_FATAL, "Assertion failed at %s:%d", filename, line); + if (condition) + msg (M_FATAL, "Assertion failed at %s:%d (%s)", filename, line, condition); + else + msg (M_FATAL, "Assertion failed at %s:%d", filename, line); + _exit(1); } /* diff --git a/src/openvpn/error.h b/src/openvpn/error.h index 27c48b6..42308e8 100644 --- a/src/openvpn/error.h +++ b/src/openvpn/error.h @@ -144,19 +144,22 @@ bool dont_mute (unsigned int flags); /* check muting filter */ #define MSG_TEST(flags) (unlikely((((unsigned int)flags) & M_DEBUG_LEVEL) <= x_debug_level) && dont_mute (flags)) +/* Macro to ensure (and teach static analysis tools) we exit on fatal errors */ +#define EXIT_FATAL(flags) do { if ((flags) & M_FATAL) _exit(1); } while (false) + #if defined(HAVE_CPP_VARARG_MACRO_ISO) && !defined(__LCLINT__) # define HAVE_VARARG_MACROS -# define msg(flags, ...) do { if (MSG_TEST(flags)) x_msg((flags), __VA_ARGS__); } while (false) +# define msg(flags, ...) do { if (MSG_TEST(flags)) x_msg((flags), __VA_ARGS__); EXIT_FATAL(flags); } while (false) # ifdef ENABLE_DEBUG -# define dmsg(flags, ...) do { if (MSG_TEST(flags)) x_msg((flags), __VA_ARGS__); } while (false) +# define dmsg(flags, ...) do { if (MSG_TEST(flags)) x_msg((flags), __VA_ARGS__); EXIT_FATAL(flags); } while (false) # else # define dmsg(flags, ...) # endif #elif defined(HAVE_CPP_VARARG_MACRO_GCC) && !defined(__LCLINT__) # define HAVE_VARARG_MACROS -# define msg(flags, args...) do { if (MSG_TEST(flags)) x_msg((flags), args); } while (false) +# define msg(flags, args...) do { if (MSG_TEST(flags)) x_msg((flags), args); EXIT_FATAL(flags); } while (false) # ifdef ENABLE_DEBUG -# define dmsg(flags, args...) do { if (MSG_TEST(flags)) x_msg((flags), args); } while (false) +# define dmsg(flags, args...) do { if (MSG_TEST(flags)) x_msg((flags), args); EXIT_FATAL(flags); } while (false) # else # define dmsg(flags, args...) # endif @@ -211,9 +214,14 @@ const char *msg_flags_string (const unsigned int flags, struct gc_arena *gc); FILE *msg_fp(const unsigned int flags); /* Fatal logic errors */ -#define ASSERT(x) do { if (!(x)) assert_failed(__FILE__, __LINE__); } while (false) +#ifndef ENABLE_SMALL +#define ASSERT(x) do { if (!(x)) assert_failed(__FILE__, __LINE__, #x); } while (false) +#else +#define ASSERT(x) do { if (!(x)) assert_failed(__FILE__, __LINE__, NULL); } while (false) +#endif -void assert_failed (const char *filename, int line); +void assert_failed (const char *filename, int line, const char *condition) + __attribute__((__noreturn__)); #ifdef ENABLE_DEBUG void crash (void); /* force a segfault (debugging only) */ diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 217fbb3..d55fa3b 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -956,8 +956,9 @@ read_incoming_tun (struct context *c) /* Was TUN/TAP I/O operation aborted? */ if (tuntap_abort(c->c2.buf.len)) { - register_signal(c, SIGTERM, "tun-abort"); - msg(M_FATAL, "TUN/TAP I/O operation aborted, exiting"); + register_signal(c, SIGHUP, "tun-abort"); + c->persist.restart_sleep_seconds = 10; + msg(M_INFO, "TUN/TAP I/O operation aborted, restarting"); perf_pop(); return; } diff --git a/src/openvpn/helper.c b/src/openvpn/helper.c index 339e2ae..62f88ec 100644 --- a/src/openvpn/helper.c +++ b/src/openvpn/helper.c @@ -167,7 +167,7 @@ helper_client_server (struct options *o) * push "tun-ipv6" * ifconfig-ipv6 2001:db8::1 2001:db8::2 * if !nopool: - * ifconfig-ipv6-pool 2001:db8::1:0/64 + * ifconfig-ipv6-pool 2001:db8::1000/64 * */ if ( o->server_ipv6_defined ) diff --git a/src/openvpn/httpdigest.c b/src/openvpn/httpdigest.c index 78b8344..99bbda4 100644 --- a/src/openvpn/httpdigest.c +++ b/src/openvpn/httpdigest.c @@ -76,20 +76,20 @@ DigestCalcHA1( const md_kt_t *md5_kt = md_kt_get("MD5"); md_ctx_init(&md5_ctx, md5_kt); - md_ctx_update(&md5_ctx, pszUserName, strlen(pszUserName)); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszRealm, strlen(pszRealm)); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszPassword, strlen(pszPassword)); + md_ctx_update(&md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword)); md_ctx_final(&md5_ctx, HA1); if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0) { md_ctx_init(&md5_ctx, md5_kt); md_ctx_update(&md5_ctx, HA1, HASHLEN); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszNonce, strlen(pszNonce)); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszCNonce, strlen(pszCNonce)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); md_ctx_final(&md5_ctx, HA1); }; md_ctx_cleanup(&md5_ctx); @@ -119,12 +119,12 @@ DigestCalcResponse( /* calculate H(A2) */ md_ctx_init(&md5_ctx, md5_kt); - md_ctx_update(&md5_ctx, pszMethod, strlen(pszMethod)); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszDigestUri, strlen(pszDigestUri)); + md_ctx_update(&md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri)); if (strcasecmp(pszQop, "auth-int") == 0) { - md_ctx_update(&md5_ctx, ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); md_ctx_update(&md5_ctx, HEntity, HASHHEXLEN); }; md_ctx_final(&md5_ctx, HA2); @@ -133,17 +133,17 @@ DigestCalcResponse( /* calculate response */ md_ctx_init(&md5_ctx, md5_kt); md_ctx_update(&md5_ctx, HA1, HASHHEXLEN); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszNonce, strlen(pszNonce)); - md_ctx_update(&md5_ctx, ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); if (*pszQop) { - md_ctx_update(&md5_ctx, pszNonceCount, strlen(pszNonceCount)); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszCNonce, strlen(pszCNonce)); - md_ctx_update(&md5_ctx, ":", 1); - md_ctx_update(&md5_ctx, pszQop, strlen(pszQop)); - md_ctx_update(&md5_ctx, ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); + md_ctx_update(&md5_ctx, (const uint8_t *) pszQop, strlen(pszQop)); + md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1); }; md_ctx_update(&md5_ctx, HA2Hex, HASHHEXLEN); md_ctx_final(&md5_ctx, RespHash); diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 71c91a2..2148777 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -840,7 +840,7 @@ void init_options_dev (struct options *options) { if (!options->dev && options->dev_node) { - char *dev_node = strdup(options->dev_node); /* POSIX basename() implementaions may modify its arguments */ + char *dev_node = string_alloc(options->dev_node, NULL); /* POSIX basename() implementaions may modify its arguments */ options->dev = basename (dev_node); } } @@ -973,31 +973,30 @@ do_uid_gid_chroot (struct context *c, bool no_delay) static const char why_not[] = "will be delayed because of --client, --pull, or --up-delay"; struct context_0 *c0 = c->c0; - if (c->first_time && c0 && !c0->uid_gid_set) + if (c0 && !c0->uid_gid_chroot_set) { /* chroot if requested */ if (c->options.chroot_dir) { if (no_delay) platform_chroot (c->options.chroot_dir); - else + else if (c->first_time) msg (M_INFO, "NOTE: chroot %s", why_not); } - /* set user and/or group that we want to setuid/setgid to */ - if (no_delay) - { - platform_group_set (&c0->platform_state_group); - platform_user_set (&c0->platform_state_user); - c0->uid_gid_set = true; - } - else if (c0->uid_gid_specified) + /* set user and/or group if we want to setuid/setgid */ + if (c0->uid_gid_specified) { - msg (M_INFO, "NOTE: UID/GID downgrade %s", why_not); + if (no_delay) { + platform_group_set (&c0->platform_state_group); + platform_user_set (&c0->platform_state_user); + } + else if (c->first_time) + msg (M_INFO, "NOTE: UID/GID downgrade %s", why_not); } #ifdef ENABLE_MEMSTATS - if (c->options.memstats_fn) + if (c->first_time && c->options.memstats_fn) mstats_open(c->options.memstats_fn); #endif @@ -1016,10 +1015,16 @@ do_uid_gid_chroot (struct context *c, bool no_delay) else msg (M_INFO, "setcon to '%s' succeeded", c->options.selinux_context); } - else + else if (c->first_time) msg (M_INFO, "NOTE: setcon %s", why_not); } #endif + + /* Privileges are going to be dropped by now (if requested), be sure + * to prevent any future privilege dropping attempts from now on. + */ + if (no_delay) + c0->uid_gid_chroot_set = true; } } @@ -1453,6 +1458,9 @@ do_open_tun (struct context *c) c->plugins, OPENVPN_PLUGIN_UP, c->c1.tuntap->actual_name, +#ifdef WIN32 + c->c1.tuntap->adapter_index, +#endif dev_type_string (c->options.dev, c->options.dev_type), TUN_MTU_SIZE (&c->c2.frame), EXPANDED_SIZE (&c->c2.frame), @@ -1463,6 +1471,15 @@ do_open_tun (struct context *c) "up", c->c2.es); +#ifdef WIN32 + if (c->options.block_outside_dns) + { + dmsg (D_LOW, "Blocking outside DNS"); + if (!win_wfp_block_dns(c->c1.tuntap->adapter_index)) + msg (M_FATAL, "Blocking DNS failed!"); + } +#endif + /* possibly add routes */ if (!c->options.route_delay_defined) do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list, @@ -1493,6 +1510,9 @@ do_open_tun (struct context *c) c->plugins, OPENVPN_PLUGIN_UP, c->c1.tuntap->actual_name, +#ifdef WIN32 + c->c1.tuntap->adapter_index, +#endif dev_type_string (c->options.dev, c->options.dev_type), TUN_MTU_SIZE (&c->c2.frame), EXPANDED_SIZE (&c->c2.frame), @@ -1530,6 +1550,9 @@ do_close_tun (struct context *c, bool force) if (c->c1.tuntap && c->c1.tuntap_owned) { const char *tuntap_actual = string_alloc (c->c1.tuntap->actual_name, &gc); +#ifdef WIN32 + DWORD adapter_index = c->c1.tuntap->adapter_index; +#endif const in_addr_t local = c->c1.tuntap->local; const in_addr_t remote_netmask = c->c1.tuntap->remote_netmask; @@ -1553,6 +1576,9 @@ do_close_tun (struct context *c, bool force) c->plugins, OPENVPN_PLUGIN_ROUTE_PREDOWN, tuntap_actual, +#ifdef WIN32 + adapter_index, +#endif NULL, TUN_MTU_SIZE (&c->c2.frame), EXPANDED_SIZE (&c->c2.frame), @@ -1578,6 +1604,9 @@ do_close_tun (struct context *c, bool force) c->plugins, OPENVPN_PLUGIN_DOWN, tuntap_actual, +#ifdef WIN32 + adapter_index, +#endif NULL, TUN_MTU_SIZE (&c->c2.frame), EXPANDED_SIZE (&c->c2.frame), @@ -1589,6 +1618,14 @@ do_close_tun (struct context *c, bool force) "down", c->c2.es); +#ifdef WIN32 + if (c->options.block_outside_dns) + { + if (!win_wfp_uninit()) + msg (M_FATAL, "Uninitialising WFP failed!"); + } +#endif + /* actually close tun/tap device based on --down-pre flag */ if (c->options.down_pre) do_close_tun_simple (c); @@ -1601,6 +1638,9 @@ do_close_tun (struct context *c, bool force) c->plugins, OPENVPN_PLUGIN_DOWN, tuntap_actual, +#ifdef WIN32 + adapter_index, +#endif NULL, TUN_MTU_SIZE (&c->c2.frame), EXPANDED_SIZE (&c->c2.frame), diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index f20d059..04a5b5f 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -62,6 +62,9 @@ run_up_down (const char *command, const struct plugin_list *plugins, int plugin_type, const char *arg, +#ifdef WIN32 + DWORD adapter_index, +#endif const char *dev_type, int tun_mtu, int link_mtu, @@ -82,6 +85,9 @@ run_up_down (const char *command, setenv_str (es, "dev", arg); if (dev_type) setenv_str (es, "dev_type", dev_type); +#ifdef WIN32 + setenv_int (es, "dev_idx", adapter_index); +#endif if (!ifconfig_local) ifconfig_local = ""; @@ -1035,7 +1041,9 @@ get_user_pass_cr (struct user_pass *up, if (!up->defined) { - const bool from_stdin = (!auth_file || !strcmp (auth_file, "stdin")); + bool from_authfile = (auth_file && !streq (auth_file, "stdin")); + bool username_from_stdin = false; + bool password_from_stdin = false; if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) msg (M_WARN, "Note: previous '%s' credentials failed", prefix); @@ -1045,7 +1053,7 @@ get_user_pass_cr (struct user_pass *up, * Get username/password from management interface? */ if (management - && ((auth_file && streq (auth_file, "management")) || (from_stdin && (flags & GET_USER_PASS_MANAGEMENT))) + && ((auth_file && streq (auth_file, "management")) || (!from_authfile && (flags & GET_USER_PASS_MANAGEMENT))) && management_query_user_pass_enabled (management)) { const char *sc = NULL; @@ -1082,18 +1090,59 @@ get_user_pass_cr (struct user_pass *up, if (!strlen (up->password)) strcpy (up->password, "ok"); } - + else if (from_authfile) + { + /* + * Try to get username/password from a file. + */ + FILE *fp; + char password_buf[USER_PASS_LEN] = { '\0' }; + + warn_if_group_others_accessible (auth_file); + + fp = platform_fopen (auth_file, "r"); + if (!fp) + msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file); + + if ((flags & GET_USER_PASS_PASSWORD_ONLY) == 0) + { + /* Read username first */ + if (fgets (up->username, USER_PASS_LEN, fp) == NULL) + msg (M_FATAL, "Error reading username from %s authfile: %s", + prefix, + auth_file); + } + chomp (up->username); + + if (fgets (password_buf, USER_PASS_LEN, fp) != NULL) + { + chomp (password_buf); + } + + if (flags & GET_USER_PASS_PASSWORD_ONLY && !password_buf[0]) + msg (M_FATAL, "Error reading password from %s authfile: %s", prefix, auth_file); + + if (password_buf[0]) + strncpy(up->password, password_buf, USER_PASS_LEN); + else + password_from_stdin = 1; + + fclose (fp); + + if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen (up->username) == 0) + msg (M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix, auth_file); + } + else + { + username_from_stdin = true; + password_from_stdin = true; + } + /* * Get username/password from standard input? */ - else if (from_stdin) + if (username_from_stdin || password_from_stdin) { -#ifndef WIN32 - /* did we --daemon'ize before asking for passwords? */ - if ( !isatty(0) && !isatty(2) ) - { msg(M_FATAL, "neither stdin nor stderr are a tty device, can't ask for %s password. If you used --daemon, you need to use --askpass to make passphrase-protected keys work, and you can not use --auth-nocache.", prefix ); } -#endif - #ifdef ENABLE_CLIENT_CR if (auth_challenge && (flags & GET_USER_PASS_DYNAMIC_CHALLENGE)) { @@ -1124,7 +1173,7 @@ get_user_pass_cr (struct user_pass *up, buf_printf (&user_prompt, "Enter %s Username:", prefix); buf_printf (&pass_prompt, "Enter %s Password:", prefix); - if (!(flags & GET_USER_PASS_PASSWORD_ONLY)) + if (username_from_stdin && !(flags & GET_USER_PASS_PASSWORD_ONLY)) { if (!get_console_input (BSTR (&user_prompt), true, up->username, USER_PASS_LEN)) msg (M_FATAL, "ERROR: could not read %s username from stdin", prefix); @@ -1132,7 +1181,7 @@ get_user_pass_cr (struct user_pass *up, msg (M_FATAL, "ERROR: %s username is empty", prefix); } - if (!get_console_input (BSTR (&pass_prompt), false, up->password, USER_PASS_LEN)) + if (password_from_stdin && !get_console_input (BSTR (&pass_prompt), false, up->password, USER_PASS_LEN)) msg (M_FATAL, "ERROR: could not not read %s password from stdin", prefix); #ifdef ENABLE_CLIENT_CR @@ -1158,52 +1207,6 @@ get_user_pass_cr (struct user_pass *up, #endif } } - else - { - /* - * Get username/password from a file. - */ - FILE *fp; - -#ifndef ENABLE_PASSWORD_SAVE - /* - * Unless ENABLE_PASSWORD_SAVE is defined, don't allow sensitive passwords - * to be read from a file. - */ - if (flags & GET_USER_PASS_SENSITIVE) - msg (M_FATAL, "Sorry, '%s' password cannot be read from a file", prefix); -#endif - - warn_if_group_others_accessible (auth_file); - - fp = platform_fopen (auth_file, "r"); - if (!fp) - msg (M_ERR, "Error opening '%s' auth file: %s", prefix, auth_file); - - if (flags & GET_USER_PASS_PASSWORD_ONLY) - { - if (fgets (up->password, USER_PASS_LEN, fp) == NULL) - msg (M_FATAL, "Error reading password from %s authfile: %s", - prefix, - auth_file); - } - else - { - if (fgets (up->username, USER_PASS_LEN, fp) == NULL - || fgets (up->password, USER_PASS_LEN, fp) == NULL) - msg (M_FATAL, "Error reading username and password (must be on two consecutive lines) from %s authfile: %s", - prefix, - auth_file); - } - - fclose (fp); - - chomp (up->username); - chomp (up->password); - - if (!(flags & GET_USER_PASS_PASSWORD_ONLY) && strlen (up->username) == 0) - msg (M_FATAL, "ERROR: username from %s authfile '%s' is empty", prefix, auth_file); - } string_mod (up->username, CC_PRINT, CC_CRLF, 0); string_mod (up->password, CC_PRINT, CC_CRLF, 0); @@ -1647,7 +1650,7 @@ argv_extract_cmd_name (const char *path) { if (path) { - char *path_cp = strdup(path); /* POSIX basename() implementaions may modify its arguments */ + char *path_cp = string_alloc(path, NULL); /* POSIX basename() implementaions may modify its arguments */ const char *bn = basename (path_cp); if (bn) { diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h index e67b5e4..c1942b6 100644 --- a/src/openvpn/misc.h +++ b/src/openvpn/misc.h @@ -63,6 +63,9 @@ void run_up_down (const char *command, const struct plugin_list *plugins, int plugin_type, const char *arg, +#ifdef WIN32 + DWORD adapter_index, +#endif const char *dev_type, int tun_mtu, int link_mtu, @@ -239,7 +242,7 @@ struct static_challenge_info {}; * Flags for get_user_pass and management_query_user_pass */ #define GET_USER_PASS_MANAGEMENT (1<<0) -#define GET_USER_PASS_SENSITIVE (1<<1) +/* GET_USER_PASS_SENSITIVE (1<<1) not used anymore */ #define GET_USER_PASS_PASSWORD_ONLY (1<<2) #define GET_USER_PASS_NEED_OK (1<<3) #define GET_USER_PASS_NOFATAL (1<<4) diff --git a/src/openvpn/mss.c b/src/openvpn/mss.c index 64fd722..7298c7b 100644 --- a/src/openvpn/mss.c +++ b/src/openvpn/mss.c @@ -129,7 +129,7 @@ mss_fixup_dowork (struct buffer *buf, uint16_t maxmss) { int hlen, olen, optlen; uint8_t *opt; - uint16_t *mss; + uint16_t mssval; int accumulate; struct openvpn_tcphdr *tc; @@ -159,14 +159,13 @@ mss_fixup_dowork (struct buffer *buf, uint16_t maxmss) if (*opt == OPENVPN_TCPOPT_MAXSEG) { if (optlen != OPENVPN_TCPOLEN_MAXSEG) continue; - mss = (uint16_t *)(opt + 2); - if (ntohs (*mss) > maxmss) { - dmsg (D_MSS, "MSS: %d -> %d", - (int) ntohs (*mss), - (int) maxmss); - accumulate = *mss; - *mss = htons (maxmss); - accumulate -= *mss; + mssval = (opt[2]<<8)+opt[3]; + if (mssval > maxmss) { + dmsg (D_MSS, "MSS: %d -> %d", (int) mssval, (int) maxmss); + accumulate = htons(mssval); + opt[2] = (maxmss>>8)&0xff; + opt[3] = maxmss&0xff; + accumulate -= htons(maxmss); ADJUST_CHECKSUM (accumulate, tc->check); } } diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 374950e..577c5d3 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -1426,10 +1426,24 @@ multi_set_virtual_addr_env (struct multi_context *m, struct multi_instance *mi) } } - /* TODO: I'm not exactly sure what these environment variables are - * used for, but if we have them for IPv4, we should also have - * them for IPv6, no? - */ + setenv_del (mi->context.c2.es, "ifconfig_pool_local_ip6"); + setenv_del (mi->context.c2.es, "ifconfig_pool_remote_ip6"); + setenv_del (mi->context.c2.es, "ifconfig_pool_ip6_netbits"); + + if (mi->context.c1.tuntap->ipv6 && mi->context.c2.push_ifconfig_ipv6_defined) + { + setenv_in6_addr (mi->context.c2.es, + "ifconfig_pool_remote", + &mi->context.c2.push_ifconfig_ipv6_local, + SA_SET_IF_NONZERO); + setenv_in6_addr (mi->context.c2.es, + "ifconfig_pool_local", + &mi->context.c2.push_ifconfig_ipv6_remote, + SA_SET_IF_NONZERO); + setenv_int (mi->context.c2.es, + "ifconfig_pool_ip6_netbits", + mi->context.c2.push_ifconfig_ipv6_netbits); + } } /* @@ -1780,6 +1794,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi { msg (D_MULTI_ERRORS, "MULTI: client has been rejected due to 'disable' directive"); cc_succeeded = false; + cc_succeeded_count = 0; } if (cc_succeeded) diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c index 32e326e..823c3dd 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -220,6 +220,9 @@ openvpn_main (int argc, char *argv[]) /* print version number */ msg (M_INFO, "%s", title_string); +#ifdef WIN32 + show_windows_version(M_INFO); +#endif show_library_versions(M_INFO); /* misc stuff */ diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index 10ec859..36c3100 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -133,13 +133,15 @@ struct context_persist * * Level 0 state is initialized once at program startup, and then remains * throughout the lifetime of the OpenVPN process. This structure - * contains information related to the process's PID, user, and group. + * contains information related to the process's PID, user, group, and + * privileges. */ struct context_0 { /* workspace for --user/--group */ bool uid_gid_specified; - bool uid_gid_set; + /* helper which tells us whether we should keep trying to drop privileges */ + bool uid_gid_chroot_set; struct platform_state_user platform_state_user; struct platform_state_group platform_state_group; }; diff --git a/src/openvpn/openvpn.vcxproj b/src/openvpn/openvpn.vcxproj index 3b2340e..d691500 100755..100644 --- a/src/openvpn/openvpn.vcxproj +++ b/src/openvpn/openvpn.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -20,10 +20,12 @@ <ConfigurationType>Application</ConfigurationType> <WholeProgramOptimization>true</WholeProgramOptimization> <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <CharacterSet>Unicode</CharacterSet> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> @@ -62,7 +64,7 @@ <AdditionalIncludeDirectories>$(SOURCEBASE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ResourceCompile> <Link> - <AdditionalDependencies>libeay32.lib;ssleay32.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>libeay32.lib;ssleay32.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(OPENSSL_HOME)/lib;$(LZO_HOME)/lib;$(PKCS11H_HOME)/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <GenerateDebugInformation>true</GenerateDebugInformation> <SubSystem>Console</SubSystem> @@ -87,7 +89,7 @@ <AdditionalIncludeDirectories>$(SOURCEBASE);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> </ResourceCompile> <Link> - <AdditionalDependencies>libeay32.lib;ssleay32.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> + <AdditionalDependencies>libeay32.lib;ssleay32.lib;lzo2.lib;pkcs11-helper.dll.lib;gdi32.lib;ws2_32.lib;wininet.lib;crypt32.lib;iphlpapi.lib;winmm.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(OPENSSL_HOME)/lib;$(LZO_HOME)/lib;$(PKCS11H_HOME)/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <GenerateDebugInformation>true</GenerateDebugInformation> <SubSystem>Console</SubSystem> diff --git a/src/openvpn/openvpn.vcxproj.filters b/src/openvpn/openvpn.vcxproj.filters index 40336ba..dbed3cd 100644 --- a/src/openvpn/openvpn.vcxproj.filters +++ b/src/openvpn/openvpn.vcxproj.filters @@ -449,10 +449,13 @@ <ClInclude Include="win32.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="win32_wfp.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ResourceCompile Include="openvpn_win32_resources.rc"> <Filter>Resource Files</Filter> </ResourceCompile> </ItemGroup> -</Project>
\ No newline at end of file +</Project> diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 007bd8c..a49a4fb 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -486,8 +486,10 @@ static const char usage_message[] = "Client options (when connecting to a multi-client server):\n" "--client : Helper option to easily configure client mode.\n" "--auth-user-pass [up] : Authenticate with server using username/password.\n" - " up is a file containing username/password on 2 lines,\n" - " or omit to prompt from console.\n" + " up is a file containing the username on the first line,\n" + " and a password on the second. If either the password or both\n" + " the username and the password are omitted OpenVPN will prompt\n" + " for them from console.\n" "--pull : Accept certain config file options from the peer as if they\n" " were part of the local config file. Must be specified\n" " when connecting to a '--mode server' remote host.\n" @@ -713,6 +715,7 @@ static const char usage_message[] = " optional parameter controls the initial state of ex.\n" "--show-net-up : Show " PACKAGE_NAME "'s view of routing table and net adapter list\n" " after TAP adapter is up and routes have been added.\n" + "--block-outside-dns : Block DNS on other network adapters to prevent DNS leaks\n" "Windows Standalone Options:\n" "\n" "--show-adapters : Show all TAP-Windows adapters.\n" @@ -800,10 +803,6 @@ init_options (struct options *o, const bool init_gc) #ifdef ENABLE_FEATURE_TUN_PERSIST o->persist_mode = 1; #endif -#ifndef WIN32 - o->rcvbuf = 65536; - o->sndbuf = 65536; -#endif #ifdef TARGET_LINUX o->tuntap_options.txqueuelen = 100; #endif @@ -816,6 +815,7 @@ init_options (struct options *o, const bool init_gc) o->tuntap_options.dhcp_lease_time = 31536000; /* one year */ o->tuntap_options.dhcp_masq_offset = 0; /* use network address as internal DHCP server address */ o->route_method = ROUTE_METHOD_ADAPTIVE; + o->block_outside_dns = false; #endif #if P2MP_SERVER o->real_hash_size = 256; @@ -965,13 +965,11 @@ get_ip_addr (const char *ip_string, int msglevel, bool *error) * "/nn" is optional, default to /64 if missing * * return true if parsing succeeded, modify *network and *netbits - * return address part without "/nn" in *printable_ipv6 (if != NULL) */ bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network, - unsigned int * netbits, char ** printable_ipv6, int msglevel ) + unsigned int * netbits, int msglevel) { - int rc; char * sep, * endp; int bits; struct in6_addr t_network; @@ -998,21 +996,14 @@ get_ipv6_addr( const char * prefix_str, struct in6_addr *network, if ( sep != NULL ) *sep = '\0'; - rc = inet_pton( AF_INET6, prefix_str, &t_network ); - - if ( rc == 1 && printable_ipv6 != NULL ) - { - *printable_ipv6 = string_alloc( prefix_str, NULL ); - } - - if ( sep != NULL ) *sep = '/'; - - if ( rc != 1 ) + if ( inet_pton( AF_INET6, prefix_str, &t_network ) != 1 ) { msg (msglevel, "IPv6 prefix '%s': invalid IPv6 address", prefix_str); return false; } + if ( sep != NULL ) *sep = '/'; + if ( netbits != NULL ) { *netbits = bits; @@ -1024,12 +1015,35 @@ get_ipv6_addr( const char * prefix_str, struct in6_addr *network, return true; /* parsing OK, values set */ } +/** + * Returns newly allocated string containing address part without "/nn". + * + * If gc != NULL, the allocated memory is registered in the supplied gc. + */ +static char * +get_ipv6_addr_no_netbits (const char *addr, struct gc_arena *gc) +{ + const char *end = strchr (addr, '/'); + char *ret = NULL; + if (NULL == end) + { + ret = string_alloc (addr, gc); + } + else + { + size_t len = end - addr; + ret = gc_malloc (len + 1, true, gc); + memcpy (ret, addr, len); + } + return ret; +} + static bool ipv6_addr_safe_hexplusbits( const char * ipv6_prefix_spec ) { struct in6_addr t_addr; unsigned int t_bits; - return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, NULL, M_WARN ); + return get_ipv6_addr( ipv6_prefix_spec, &t_addr, &t_bits, M_WARN ); } static char * @@ -1271,7 +1285,7 @@ option_iroute_ipv6 (struct options *o, ALLOC_OBJ_GC (ir, struct iroute_ipv6, &o->gc); - if ( !get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel )) + if ( !get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, msglevel )) { msg (msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification", prefix_str); @@ -1585,6 +1599,7 @@ show_settings (const struct options *o) SHOW_STR (ca_path); SHOW_STR (dh_file); SHOW_STR (cert_file); + SHOW_STR (extra_certs_file); #ifdef MANAGMENT_EXTERNAL_KEY if((o->management_flags & MF_EXTERNAL_KEY)) @@ -1665,6 +1680,7 @@ show_settings (const struct options *o) #ifdef WIN32 SHOW_BOOL (show_net_up); SHOW_INT (route_method); + SHOW_BOOL (block_outside_dns); show_tuntap_options (&o->tuntap_options); #endif #endif @@ -2616,7 +2632,7 @@ check_file_access(const int type, const char *file, const int mode, const char * /* Is the directory path leading to the given file accessible? */ if (type & CHKACC_DIRPATH) { - char *fullpath = strdup(file); /* POSIX dirname() implementaion may modify its arguments */ + char *fullpath = string_alloc (file, NULL); /* POSIX dirname() implementaion may modify its arguments */ char *dirpath = dirname(fullpath); if (platform_access (dirpath, mode|X_OK) != 0) @@ -3473,6 +3489,15 @@ usage_small (void) openvpn_exit (OPENVPN_EXIT_STATUS_USAGE); /* exit point */ } +#ifdef WIN32 +void show_windows_version(const unsigned int flags) +{ + struct gc_arena gc = gc_new (); + msg (flags, "Windows version %s", win32_version_string (&gc, true)); + gc_free (&gc); +} +#endif + void show_library_versions(const unsigned int flags) { @@ -3498,6 +3523,9 @@ usage_version (void) { msg (M_INFO|M_NOPREFIX, "%s", title_string); show_library_versions( M_INFO|M_NOPREFIX ); +#ifdef WIN32 + show_windows_version( M_INFO|M_NOPREFIX ); +#endif msg (M_INFO|M_NOPREFIX, "Originally developed by James Yonan"); msg (M_INFO|M_NOPREFIX, "Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>"); #ifndef ENABLE_SMALL @@ -3761,7 +3789,10 @@ read_inline_file (struct in_src *is, const char *close_tag, struct gc_arena *gc) while (in_src_get (is, line, sizeof (line))) { - if (!strncmp (line, close_tag, strlen (close_tag))) + char *line_ptr = line; + /* Remove leading spaces */ + while (isspace(*line_ptr)) line_ptr++; + if (!strncmp (line_ptr, close_tag, strlen (close_tag))) { endtagfound = true; break; @@ -3853,7 +3884,7 @@ read_config_file (struct options *options, const int max_recursive_levels = 10; FILE *fp; int line_num; - char line[OPTION_LINE_SIZE]; + char line[OPTION_LINE_SIZE+1]; char *p[MAX_PARMS]; ++level; @@ -3871,6 +3902,10 @@ read_config_file (struct options *options, int offset = 0; CLEAR (p); ++line_num; + if (strlen(line) == OPTION_LINE_SIZE) + msg (msglevel, "In %s:%d: Maximum optione line length (%d) exceeded, line starts with %s", + file, line_num, OPTION_LINE_SIZE, line); + /* Ignore UTF-8 BOM at start of stream */ if (line_num == 1 && strncmp (line, "\xEF\xBB\xBF", 3) == 0) offset = 3; @@ -4467,10 +4502,9 @@ add_option (struct options *options, else if (streq (p[0], "ifconfig-ipv6") && p[1] && p[2] ) { unsigned int netbits; - char * ipv6_local; VERIFY_PERMISSION (OPT_P_UP); - if ( get_ipv6_addr( p[1], NULL, &netbits, &ipv6_local, msglevel ) && + if ( get_ipv6_addr( p[1], NULL, &netbits, msglevel ) && ipv6_addr_safe( p[2] ) ) { if ( netbits < 64 || netbits > 124 ) @@ -4479,11 +4513,7 @@ add_option (struct options *options, goto err; } - if (options->ifconfig_ipv6_local) - /* explicitly ignoring this is a const char */ - free ((char *) options->ifconfig_ipv6_local); - - options->ifconfig_ipv6_local = ipv6_local; + options->ifconfig_ipv6_local = get_ipv6_addr_no_netbits (p[1], &options->gc); options->ifconfig_ipv6_netbits = netbits; options->ifconfig_ipv6_remote = p[2]; } @@ -5558,7 +5588,7 @@ add_option (struct options *options, unsigned int netbits = 0; VERIFY_PERMISSION (OPT_P_GENERAL); - if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev) ) + if ( ! get_ipv6_addr (p[1], &network, &netbits, lev) ) { msg (msglevel, "error parsing --server-ipv6 parameter"); goto err; @@ -5669,7 +5699,7 @@ add_option (struct options *options, unsigned int netbits = 0; VERIFY_PERMISSION (OPT_P_GENERAL); - if ( ! get_ipv6_addr (p[1], &network, &netbits, NULL, lev ) ) + if ( ! get_ipv6_addr (p[1], &network, &netbits, lev ) ) { msg (msglevel, "error parsing --ifconfig-ipv6-pool parameters"); goto err; @@ -5930,7 +5960,7 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_INSTANCE); - if ( ! get_ipv6_addr( p[1], &local, &netbits, NULL, msglevel ) ) + if ( ! get_ipv6_addr( p[1], &local, &netbits, msglevel ) ) { msg (msglevel, "cannot parse --ifconfig-ipv6-push addresses"); goto err; @@ -5938,7 +5968,7 @@ add_option (struct options *options, if ( p[2] ) { - if ( !get_ipv6_addr( p[2], &remote, NULL, NULL, msglevel ) ) + if ( !get_ipv6_addr( p[2], &remote, NULL, msglevel ) ) { msg( msglevel, "cannot parse --ifconfig-ipv6-push addresses"); goto err; @@ -5948,7 +5978,7 @@ add_option (struct options *options, { if ( ! options->ifconfig_ipv6_local || ! get_ipv6_addr( options->ifconfig_ipv6_local, &remote, - NULL, NULL, msglevel ) ) + NULL, msglevel ) ) { msg( msglevel, "second argument to --ifconfig-ipv6-push missing and no global --ifconfig-ipv6 address set"); goto err; @@ -6230,6 +6260,22 @@ add_option (struct options *options, VERIFY_PERMISSION (OPT_P_IPWIN32); options->tuntap_options.register_dns = true; } +#ifdef WIN32 + else if (streq (p[0], "block-outside-dns") && !p[1]) + { + VERIFY_PERMISSION (OPT_P_IPWIN32); + if (win_wfp_init_funcs()) + { + options->block_outside_dns = true; + } + else + { + msg (msglevel_fc, "Failed to enable --block-outside-dns. " + "Maybe WFP is not supported on your system?"); + goto err; + } + } +#endif else if (streq (p[0], "rdns-internal")) /* standalone method for internal use * diff --git a/src/openvpn/options.h b/src/openvpn/options.h index af9a47f..26b09ea 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -593,6 +593,7 @@ struct options bool exit_event_initial_state; bool show_net_up; int route_method; + bool block_outside_dns; #endif bool use_peer_id; @@ -689,6 +690,10 @@ void usage_small (void); void show_library_versions(const unsigned int flags); +#ifdef WIN32 +void show_windows_version(const unsigned int flags); +#endif + void init_options (struct options *o, const bool init_gc); void uninit_options (struct options *o); @@ -777,8 +782,7 @@ void options_string_import (struct options *options, struct env_set *es); bool get_ipv6_addr( const char * prefix_str, struct in6_addr *network, - unsigned int * netbits, char ** printable_ipv6, - int msglevel ); + unsigned int * netbits, int msglevel ); /* * inline functions diff --git a/src/openvpn/pkcs11_polarssl.c b/src/openvpn/pkcs11_polarssl.c index 03b2bab..a58beef 100644 --- a/src/openvpn/pkcs11_polarssl.c +++ b/src/openvpn/pkcs11_polarssl.c @@ -40,6 +40,7 @@ #include "errlevel.h" #include "pkcs11_backend.h" #include <polarssl/pkcs11.h> +#include <polarssl/x509.h> int pkcs11_init_tls_session(pkcs11h_certificate_t certificate, @@ -49,20 +50,21 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate, ASSERT (NULL != ssl_ctx); + ALLOC_OBJ_CLEAR (ssl_ctx->crt_chain, x509_crt); if (pkcs11_x509_cert_init(ssl_ctx->crt_chain, certificate)) { msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); goto cleanup; } - ssl_ctx->priv_key_pkcs11 = malloc(sizeof(pkcs11_context)); - - if (ssl_ctx->priv_key_pkcs11 == NULL) { - msg (M_FATAL, "PKCS#11: Cannot allocate PolarSSL private key object"); + ALLOC_OBJ_CLEAR (ssl_ctx->priv_key_pkcs11, pkcs11_context); + if (pkcs11_priv_key_init(ssl_ctx->priv_key_pkcs11, certificate)) { + msg (M_FATAL, "PKCS#11: Cannot initialize PolarSSL private key object"); goto cleanup; } - if (pkcs11_priv_key_init(ssl_ctx->priv_key_pkcs11, certificate)) { - msg (M_FATAL, "PKCS#11: Cannot initialize PolarSSL private key object"); + ALLOC_OBJ_CLEAR (ssl_ctx->priv_key, pk_context); + if (0 != pk_init_ctx_rsa_alt(ssl_ctx->priv_key, ssl_ctx->priv_key_pkcs11, + ssl_pkcs11_decrypt, ssl_pkcs11_sign, ssl_pkcs11_key_len)) { goto cleanup; } @@ -78,14 +80,14 @@ pkcs11_certificate_dn (pkcs11h_certificate_t cert, struct gc_arena *gc) char *ret = NULL; char dn[1024] = {0}; - x509_cert polar_cert = {0}; + x509_crt polar_cert = {0}; if (pkcs11_x509_cert_init(&polar_cert, cert)) { msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); goto cleanup; } - if (-1 == x509parse_dn_gets (dn, sizeof(dn), &polar_cert.subject)) { + if (-1 == x509_dn_gets (dn, sizeof(dn), &polar_cert.subject)) { msg (M_FATAL, "PKCS#11: PolarSSL cannot parse subject"); goto cleanup; } @@ -93,7 +95,7 @@ pkcs11_certificate_dn (pkcs11h_certificate_t cert, struct gc_arena *gc) ret = string_alloc(dn, gc); cleanup: - x509_free(&polar_cert); + x509_crt_free(&polar_cert); return ret; } @@ -104,14 +106,14 @@ pkcs11_certificate_serial (pkcs11h_certificate_t cert, char *serial, { int ret = 1; - x509_cert polar_cert = {0}; + x509_crt polar_cert = {0}; if (pkcs11_x509_cert_init(&polar_cert, cert)) { msg (M_FATAL, "PKCS#11: Cannot retrieve PolarSSL certificate object"); goto cleanup; } - if (-1 == x509parse_serial_gets (serial, serial_len, &polar_cert.serial)) { + if (-1 == x509_serial_gets (serial, serial_len, &polar_cert.serial)) { msg (M_FATAL, "PKCS#11: PolarSSL cannot parse serial"); goto cleanup; } @@ -119,7 +121,7 @@ pkcs11_certificate_serial (pkcs11h_certificate_t cert, char *serial, ret = 0; cleanup: - x509_free(&polar_cert); + x509_crt_free(&polar_cert); return ret; } diff --git a/src/openvpn/plugin.c b/src/openvpn/plugin.c index 0948f23..54c5b52 100644 --- a/src/openvpn/plugin.c +++ b/src/openvpn/plugin.c @@ -291,7 +291,7 @@ plugin_init_item (struct plugin *p, const struct plugin_option *o) static void plugin_vlog (openvpn_plugin_log_flags_t flags, const char *name, const char *format, va_list arglist) { - unsigned int msg_flags; + unsigned int msg_flags = 0; if (!format) return; diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 11505cb..e4f3984 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -103,6 +103,7 @@ server_pushed_signal (struct context *c, const struct buffer *buffer, const bool m = BSTR (&buf); /* preserve cached passwords? */ + /* advance to next server? */ { bool purge = true; @@ -113,6 +114,12 @@ server_pushed_signal (struct context *c, const struct buffer *buffer, const bool { if (m[i] == 'P') purge = false; + else if (m[i] == 'N') + { + /* next server? */ + if (c->options.connection_list) + c->options.connection_list->no_advance = false; + } } } if (purge) diff --git a/src/openvpn/route.c b/src/openvpn/route.c index 2acfbe8..f35bc85 100644 --- a/src/openvpn/route.c +++ b/src/openvpn/route.c @@ -42,6 +42,7 @@ #include "manage.h" #include "win32.h" #include "options.h" +#include "win32.h" #include "memdbg.h" @@ -390,7 +391,7 @@ init_route_ipv6 (struct route_ipv6 *r6, { r6->defined = false; - if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, NULL, M_WARN )) + if ( !get_ipv6_addr( r6o->prefix, &r6->network, &r6->netbits, M_WARN )) goto fail; /* gateway */ @@ -648,7 +649,7 @@ init_route_list (struct route_list *rl, bool warned = false; for (i = 0; i < opt->n; ++i) { - struct addrinfo* netlist; + struct addrinfo* netlist = NULL; struct route_ipv4 r; if (!init_route (&r, @@ -675,8 +676,9 @@ init_route_list (struct route_list *rl, } } } - freeaddrinfo(netlist); } + if (netlist) + freeaddrinfo(netlist); } rl->n = j; } @@ -1622,6 +1624,13 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla #elif defined (WIN32) + if (win32_version_info() != WIN_XP) + { + struct buffer out = alloc_buf_gc (64, &gc); + buf_printf (&out, "interface=%d", tt->adapter_index ); + device = buf_bptr(&out); + } + /* netsh interface ipv6 add route 2001:db8::/32 MyTunDevice */ argv_printf (&argv, "%s%sc interface ipv6 add route %s/%d %s", get_win_sys_path(), @@ -1953,6 +1962,13 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne #elif defined (WIN32) + if (win32_version_info() != WIN_XP) + { + struct buffer out = alloc_buf_gc (64, &gc); + buf_printf (&out, "interface=%d", tt->adapter_index ); + device = buf_bptr(&out); + } + /* netsh interface ipv6 delete route 2001:db8::/32 MyTunDevice */ argv_printf (&argv, "%s%sc interface ipv6 delete route %s/%d %s", get_win_sys_path(), @@ -3195,7 +3211,7 @@ test_local_addr (const in_addr_t addr, const struct route_gateway_info *rgi) { struct gc_arena gc = gc_new (); const in_addr_t nonlocal_netmask = 0x80000000L; /* routes with netmask <= to this are considered non-local */ - bool ret = TLA_NONLOCAL; + int ret = TLA_NONLOCAL; /* get full routing table */ const MIB_IPFORWARDTABLE *rt = get_windows_routing_table (&gc); diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 0424c0b..3e30c75 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -494,12 +494,9 @@ static void socket_set_sndbuf (int sd, int size) { #if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_SNDBUF) - if (size > 0 && size < SOCKET_SND_RCV_BUF_MAX) + if (setsockopt (sd, SOL_SOCKET, SO_SNDBUF, (void *) &size, sizeof (size)) != 0) { - if (setsockopt (sd, SOL_SOCKET, SO_SNDBUF, (void *) &size, sizeof (size)) != 0) - { - msg (M_WARN, "NOTE: setsockopt SO_SNDBUF=%d failed", size); - } + msg (M_WARN, "NOTE: setsockopt SO_SNDBUF=%d failed", size); } #endif } @@ -523,13 +520,10 @@ static bool socket_set_rcvbuf (int sd, int size) { #if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_RCVBUF) - if (size > 0 && size < SOCKET_SND_RCV_BUF_MAX) + if (setsockopt (sd, SOL_SOCKET, SO_RCVBUF, (void *) &size, sizeof (size)) != 0) { - if (setsockopt (sd, SOL_SOCKET, SO_RCVBUF, (void *) &size, sizeof (size)) != 0) - { - msg (M_WARN, "NOTE: setsockopt SO_RCVBUF=%d failed", size); - return false; - } + msg (M_WARN, "NOTE: setsockopt SO_RCVBUF=%d failed", size); + return false; } return true; #endif @@ -1265,20 +1259,24 @@ resolve_remote (struct link_socket *sock, ASSERT (0); } - /* Temporary fix, this need to be changed for dual stack */ - status = openvpn_getaddrinfo(flags, sock->remote_host, retry, - signal_received, af, &ai); - if(status == 0) { - sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); - freeaddrinfo(ai); + /* Temporary fix, this need to be changed for dual stack */ + status = openvpn_getaddrinfo(flags, sock->remote_host, retry, + signal_received, af, &ai); + if(status == 0) + { + if ( ai->ai_family == AF_INET6 ) + sock->info.lsa->remote.addr.in6 = *((struct sockaddr_in6*)(ai->ai_addr)); + else + sock->info.lsa->remote.addr.in4 = *((struct sockaddr_in*)(ai->ai_addr)); + freeaddrinfo(ai); - dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", + dmsg (D_SOCKET_DEBUG, "RESOLVE_REMOTE flags=0x%04x phase=%d rrs=%d sig=%d status=%d", flags, phase, retry, signal_received ? *signal_received : -1, status); - } + } if (signal_received) { if (*signal_received) @@ -2412,6 +2410,22 @@ setenv_in_addr_t (struct env_set *es, const char *name_prefix, in_addr_t addr, c } void +setenv_in6_addr (struct env_set *es, + const char *name_prefix, + const struct in6_addr *addr, + const unsigned int flags) +{ + if (!IN6_IS_ADDR_UNSPECIFIED (addr) || !(flags & SA_SET_IF_NONZERO)) + { + struct openvpn_sockaddr si; + CLEAR (si); + si.addr.in6.sin6_family = AF_INET6; + si.addr.in6.sin6_addr = *addr; + setenv_sockaddr (es, name_prefix, &si, flags); + } +} + +void setenv_link_socket_actual (struct env_set *es, const char *name_prefix, const struct link_socket_actual *act, diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 793cd9f..b7a4e01 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -42,11 +42,6 @@ #define OPENVPN_PORT 1194 /* - * Maximum size passed passed to setsockopt SNDBUF/RCVBUF - */ -#define SOCKET_SND_RCV_BUF_MAX 1000000 - -/* * Number of seconds that "resolv-retry infinite" * represents. */ @@ -383,6 +378,11 @@ void setenv_in_addr_t (struct env_set *es, in_addr_t addr, const unsigned int flags); +void setenv_in6_addr (struct env_set *es, + const char *name_prefix, + const struct in6_addr *addr, + const unsigned int flags); + void setenv_link_socket_actual (struct env_set *es, const char *name_prefix, const struct link_socket_actual *act, diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index a17c738..0679890 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -43,6 +43,7 @@ #endif #include "syshead.h" +#include "win32.h" #if defined(ENABLE_CRYPTO) && defined(ENABLE_SSL) @@ -301,8 +302,9 @@ tls_init_control_channel_frame_parameters(const struct frame *data_channel_frame reliable_ack_adjust_frame_parameters (frame, CONTROL_SEND_ACK_MAX); frame_add_to_extra_frame (frame, SID_SIZE + sizeof (packet_id_type)); - /* set dynamic link MTU to minimum value */ - frame_set_mtu_dynamic (frame, 0, SET_MTU_TUN); + /* set dynamic link MTU to cap control channel packets at 1250 bytes */ + ASSERT (TUN_LINK_DELTA (frame) < min_int (frame->link_mtu, 1250)); + frame->link_mtu_dynamic = min_int (frame->link_mtu, 1250) - TUN_LINK_DELTA (frame); } void @@ -333,7 +335,7 @@ void pem_password_setup (const char *auth_file) { if (!strlen (passbuf.password)) - get_user_pass (&passbuf, auth_file, UP_TYPE_PRIVATE_KEY, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_PASSWORD_ONLY); + get_user_pass (&passbuf, auth_file, UP_TYPE_PRIVATE_KEY, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_PASSWORD_ONLY); } int @@ -376,11 +378,11 @@ auth_user_pass_setup (const char *auth_file, const struct static_challenge_info get_user_pass_cr (&auth_user_pass, auth_file, UP_TYPE_AUTH, - GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_DYNAMIC_CHALLENGE, + GET_USER_PASS_MANAGEMENT|GET_USER_PASS_DYNAMIC_CHALLENGE, auth_challenge); else if (sci) /* static challenge response */ { - int flags = GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE|GET_USER_PASS_STATIC_CHALLENGE; + int flags = GET_USER_PASS_MANAGEMENT|GET_USER_PASS_STATIC_CHALLENGE; if (sci->flags & SC_ECHO) flags |= GET_USER_PASS_STATIC_CHALLENGE_ECHO; get_user_pass_cr (&auth_user_pass, @@ -391,7 +393,7 @@ auth_user_pass_setup (const char *auth_file, const struct static_challenge_info } else # endif - get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT|GET_USER_PASS_SENSITIVE); + get_user_pass (&auth_user_pass, auth_file, UP_TYPE_AUTH, GET_USER_PASS_MANAGEMENT); #endif } } @@ -555,6 +557,9 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) tls_ctx_load_extra_certs(new_ctx, options->extra_certs_file, options->extra_certs_file_inline); } + /* Check certificate notBefore and notAfter */ + tls_ctx_check_cert_time(new_ctx); + /* Allowable ciphers */ if (options->cipher_list) { @@ -1844,6 +1849,9 @@ push_peer_info(struct buffer *buf, struct tls_session *session) if (rgi.flags & RGI_HWADDR_DEFINED) buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc)); buf_printf (&out, "IV_SSL=%s\n", get_ssl_library_version() ); +#if defined(WIN32) + buf_printf (&out, "IV_PLAT_VER=%s\n", win32_version_string (&gc, false)); +#endif } /* push env vars that begin with UV_ and IV_GUI_VER */ diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index 6d47bd0..4b35e51 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -176,6 +176,15 @@ void tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags); void tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers); /** + * Check our certificate notBefore and notAfter fields, and warn if the cert is + * either not yet valid or has expired. Note that this is a non-fatal error, + * since we compare against the system time, which might be incorrect. + * + * @param ctx TLS context to get our certificate from. + */ +void tls_ctx_check_cert_time (const struct tls_root_ctx *ctx); + +/** * Load Diffie Hellman Parameters, and load them into the library-specific * TLS context. * diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index be33caa..e595e1b 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -335,6 +335,55 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) } void +tls_ctx_check_cert_time (const struct tls_root_ctx *ctx) +{ + int ret; + const X509 *cert; + + ASSERT (ctx); + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + /* OpenSSL 1.0.2 and up */ + cert = SSL_CTX_get0_certificate (ctx->ctx); +#else + /* OpenSSL 1.0.1 and earlier need an SSL object to get at the certificate */ + SSL *ssl = SSL_new (ctx->ctx); + cert = SSL_get_certificate (ssl); +#endif + + if (cert == NULL) + { + goto cleanup; /* Nothing to check if there is no certificate */ + } + + ret = X509_cmp_time (X509_get_notBefore (cert), NULL); + if (ret == 0) + { + msg (D_TLS_DEBUG_MED, "Failed to read certificate notBefore field."); + } + if (ret > 0) + { + msg (M_WARN, "WARNING: Your certificate is not yet valid!"); + } + + ret = X509_cmp_time (X509_get_notAfter (cert), NULL); + if (ret == 0) + { + msg (D_TLS_DEBUG_MED, "Failed to read certificate notAfter field."); + } + if (ret < 0) + { + msg (M_WARN, "WARNING: Your certificate has expired!"); + } + +cleanup: +#if OPENSSL_VERSION_NUMBER < 0x10002000L + SSL_free (ssl); +#endif + return; +} + +void tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file, const char *dh_file_inline ) diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c index 30c7395..cd8ee1a 100644 --- a/src/openvpn/ssl_polarssl.c +++ b/src/openvpn/ssl_polarssl.c @@ -46,12 +46,13 @@ #include "manage.h" #include "ssl_common.h" -#include <polarssl/sha2.h> #include <polarssl/havege.h> #include "ssl_verify_polarssl.h" #include <polarssl/error.h> +#include <polarssl/oid.h> #include <polarssl/pem.h> +#include <polarssl/sha256.h> #include <polarssl/version.h> void @@ -76,11 +77,8 @@ tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) CLEAR(*ctx); ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context); - ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context); - - ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_cert); - ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_cert); + ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_crt); ctx->endpoint = SSL_IS_SERVER; ctx->initialised = true; @@ -93,10 +91,7 @@ tls_ctx_client_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) CLEAR(*ctx); ALLOC_OBJ_CLEAR(ctx->dhm_ctx, dhm_context); - ALLOC_OBJ_CLEAR(ctx->priv_key, rsa_context); - - ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_cert); - ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_cert); + ALLOC_OBJ_CLEAR(ctx->ca_chain, x509_crt); ctx->endpoint = SSL_IS_CLIENT; ctx->initialised = true; @@ -107,17 +102,21 @@ tls_ctx_free(struct tls_root_ctx *ctx) { if (ctx) { - rsa_free(ctx->priv_key); - free(ctx->priv_key); + pk_free(ctx->priv_key); + if (ctx->priv_key) + free(ctx->priv_key); - x509_free(ctx->ca_chain); - free(ctx->ca_chain); + x509_crt_free(ctx->ca_chain); + if (ctx->ca_chain) + free(ctx->ca_chain); - x509_free(ctx->crt_chain); - free(ctx->crt_chain); + x509_crt_free(ctx->crt_chain); + if (ctx->crt_chain) + free(ctx->crt_chain); dhm_free(ctx->dhm_ctx); - free(ctx->dhm_ctx); + if (ctx->dhm_ctx) + free(ctx->dhm_ctx); #if defined(ENABLE_PKCS11) if (ctx->priv_key_pkcs11 != NULL) { @@ -191,7 +190,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) /* Parse allowed ciphers, getting IDs */ i = 0; - tmp_ciphers_orig = tmp_ciphers = strdup(ciphers); + tmp_ciphers_orig = tmp_ciphers = string_alloc (ciphers, NULL); token = strtok (tmp_ciphers, ":"); while(token) @@ -206,19 +205,39 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) } void +tls_ctx_check_cert_time (const struct tls_root_ctx *ctx) +{ + ASSERT (ctx); + if (ctx->crt_chain == NULL) + { + return; /* Nothing to check if there is no certificate */ + } + + if (x509_time_future (&ctx->crt_chain->valid_from)) + { + msg (M_WARN, "WARNING: Your certificate is not yet valid!"); + } + + if (x509_time_expired (&ctx->crt_chain->valid_to)) + { + msg (M_WARN, "WARNING: Your certificate has expired!"); + } +} + +void tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file, const char *dh_inline ) { if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_inline) { - if (0 != x509parse_dhm(ctx->dhm_ctx, (const unsigned char *) dh_inline, + if (0 != dhm_parse_dhm(ctx->dhm_ctx, (const unsigned char *) dh_inline, strlen(dh_inline))) msg (M_FATAL, "Cannot read inline DH parameters"); } else { - if (0 != x509parse_dhmfile(ctx->dhm_ctx, dh_file)) + if (0 != dhm_parse_dhmfile(ctx->dhm_ctx, dh_file)) msg (M_FATAL, "Cannot read DH parameters from file %s", dh_file); } @@ -251,15 +270,20 @@ tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, { ASSERT(NULL != ctx); + if (!ctx->crt_chain) + { + ALLOC_OBJ_CLEAR(ctx->crt_chain, x509_crt); + } + if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_inline) { - if (0 != x509parse_crt(ctx->crt_chain, + if (0 != x509_crt_parse(ctx->crt_chain, (const unsigned char *) cert_inline, strlen(cert_inline))) msg (M_FATAL, "Cannot load inline certificate file"); } else { - if (0 != x509parse_crtfile(ctx->crt_chain, cert_file)) + if (0 != x509_crt_parse_file(ctx->crt_chain, cert_file)) msg (M_FATAL, "Cannot load certificate file %s", cert_file); } } @@ -272,34 +296,40 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, int status; ASSERT(NULL != ctx); + if (!ctx->priv_key) + { + ALLOC_OBJ_CLEAR(ctx->priv_key, pk_context); + } + if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_inline) { - status = x509parse_key(ctx->priv_key, + status = pk_parse_key(ctx->priv_key, (const unsigned char *) priv_key_inline, strlen(priv_key_inline), NULL, 0); - if (POLARSSL_ERR_X509_PASSWORD_REQUIRED == status) + + if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); - status = x509parse_key(ctx->priv_key, + status = pk_parse_key(ctx->priv_key, (const unsigned char *) priv_key_inline, strlen(priv_key_inline), - (const unsigned char *) passbuf, strlen(passbuf)); + (unsigned char *) passbuf, strlen(passbuf)); } } else { - status = x509parse_keyfile(ctx->priv_key, priv_key_file, NULL); - if (POLARSSL_ERR_X509_PASSWORD_REQUIRED == status) + status = pk_parse_keyfile(ctx->priv_key, priv_key_file, NULL); + if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); - status = x509parse_keyfile(ctx->priv_key, priv_key_file, passbuf); + status = pk_parse_keyfile(ctx->priv_key, priv_key_file, passbuf); } } if (0 != status) { #ifdef ENABLE_MANAGEMENT - if (management && (POLARSSL_ERR_X509_PASSWORD_MISMATCH == status)) + if (management && (POLARSSL_ERR_PK_PASSWORD_MISMATCH == status)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif msg (M_WARN, "Cannot load private key file %s", priv_key_file); @@ -323,43 +353,43 @@ struct external_context { size_t signature_length; }; -int -tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, - const char *cert_file, const char *cert_file_inline) -{ - 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; -} - +/** + * external_pkcs1_sign implements a PolarSSL rsa_sign_func callback, that uses + * the management interface to request an RSA signature for the supplied hash. + * + * @param ctx_voidptr Management external key context. + * @param f_rng (Unused) + * @param p_rng (Unused) + * @param mode RSA mode (should be RSA_PRIVATE). + * @param md_alg Message digest ('hash') algorithm type. + * @param hashlen Length of hash (overridden by length specified by md_alg + * if md_alg != POLARSSL_MD_NONE). + * @param hash The digest ('hash') to sign. Should have a size + * matching the length of md_alg (if != POLARSSL_MD_NONE), + * or hashlen otherwise. + * @param sig Buffer that returns the signature. Should be at least of + * size ctx->signature_length. + * + * @return 0 on success, non-zero polarssl error code on failure. + */ 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, + md_type_t md_alg, 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; + unsigned char *p = sig; + size_t asn_len = 0, oid_size = 0, sig_len = 0; + const char *oid = NULL; - ASSERT(NULL != ctx); + if( NULL == ctx ) + return POLARSSL_ERR_RSA_BAD_INPUT_DATA; - if (RSA_PRIVATE != mode) - { - rv = POLARSSL_ERR_RSA_BAD_INPUT_DATA; - goto done; - } + if( RSA_PRIVATE != mode ) + return POLARSSL_ERR_RSA_BAD_INPUT_DATA; /* * Support a wide range of hashes. TLSv1.1 and before only need SIG_RSA_RAW, @@ -367,67 +397,54 @@ static inline int external_pkcs1_sign( void *ctx_voidptr, * * 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; + if( md_alg != POLARSSL_MD_NONE ) + { + const md_info_t *md_info = md_info_from_type( md_alg ); + if( md_info == NULL ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + if( oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->signature_length; + if ( (SIZE_MAX - hashlen) < asn_len || (hashlen + asn_len) > sig_len ) + return POLARSSL_ERR_RSA_BAD_INPUT_DATA; + + if( md_alg != POLARSSL_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = ASN1_SEQUENCE | ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = ASN1_NULL; + *p++ = 0x00; + *p++ = ASN1_OCTET_STRING; + *p++ = hashlen; + + /* Determine added ASN length */ + asn_len = p - sig; } + /* Copy the hash to be signed */ + memcpy( p, hash, hashlen ); + /* convert 'from' to base64 */ if (openvpn_base64_encode (sig, asn_len + hashlen, &in_b64) <= 0) { @@ -454,7 +471,7 @@ static inline int external_pkcs1_sign( void *ctx_voidptr, rv = 0; - done: +done: if (in_b64) free (in_b64); if (out_b64) @@ -468,6 +485,28 @@ static inline size_t external_key_len(void *vctx) return ctx->signature_length; } + +int +tls_ctx_use_external_private_key (struct tls_root_ctx *ctx, + const char *cert_file, const char *cert_file_inline) +{ + ASSERT(NULL != ctx); + + tls_ctx_load_cert_file(ctx, cert_file, cert_file_inline); + + if (ctx->crt_chain == NULL) + return 0; + + ALLOC_OBJ_CLEAR (ctx->external_key, struct external_context); + ctx->external_key->signature_length = pk_get_len(&ctx->crt_chain->pk); + + ALLOC_OBJ_CLEAR (ctx->priv_key, pk_context); + if (0 != pk_init_ctx_rsa_alt(ctx->priv_key, ctx->external_key, + NULL, external_pkcs1_sign, external_key_len)) + return 0; + + return 1; +} #endif void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, @@ -480,14 +519,14 @@ void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_inline) { - if (0 != x509parse_crt(ctx->ca_chain, (const unsigned char *) ca_inline, + if (0 != x509_crt_parse(ctx->ca_chain, (unsigned char *) ca_inline, strlen(ca_inline))) msg (M_FATAL, "Cannot load inline CA certificates"); } else { /* Load CA file for verifying peer supplied certificate */ - if (0 != x509parse_crtfile(ctx->ca_chain, ca_file)) + if (0 != x509_crt_parse_file(ctx->ca_chain, ca_file)) msg (M_FATAL, "Cannot load CA certificate file %s", ca_file); } } @@ -499,16 +538,21 @@ tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file { ASSERT(NULL != ctx); + if (!ctx->crt_chain) + { + ALLOC_OBJ_CLEAR (ctx->crt_chain, x509_crt); + } + if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_inline) { - if (0 != x509parse_crt(ctx->crt_chain, - (const unsigned char *) extra_certs_inline, + if (0 != x509_crt_parse(ctx->crt_chain, + (const unsigned char *) extra_certs_inline, strlen(extra_certs_inline))) msg (M_FATAL, "Cannot load inline extra-certs file"); } else { - if (0 != x509parse_crtfile(ctx->crt_chain, extra_certs_file)) + if (0 != x509_crt_parse_file(ctx->crt_chain, extra_certs_file)) msg (M_FATAL, "Cannot load extra-certs file: %s", extra_certs_file); } } @@ -631,9 +675,9 @@ void tls_ctx_personalise_random(struct tls_root_ctx *ctx) if (NULL != ctx->crt_chain) { - x509_cert *cert = ctx->crt_chain; + x509_crt *cert = ctx->crt_chain; - sha2(cert->tbs.p, cert->tbs.len, sha256_hash, false); + sha256(cert->tbs.p, cert->tbs.len, sha256_hash, false); if ( 0 != memcmp(old_sha256_hash, sha256_hash, sizeof(sha256_hash))) { ctr_drbg_update(cd_ctx, sha256_hash, 32); @@ -707,24 +751,19 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl, if (ssl_ctx->allowed_ciphers) ssl_set_ciphersuites (ks_ssl->ctx, ssl_ctx->allowed_ciphers); + /* Disable record splitting (for now). OpenVPN assumes records are sent + * unfragmented, and changing that will require thorough review and + * testing. Since OpenVPN is not susceptible to BEAST, we can just + * disable record splitting as a quick fix. */ +#if defined(POLARSSL_SSL_CBC_RECORD_SPLITTING) + ssl_set_cbc_record_splitting (ks_ssl->ctx, SSL_CBC_RECORD_SPLITTING_DISABLED); +#endif /* POLARSSL_SSL_CBC_RECORD_SPLITTING */ + /* Initialise authentication information */ if (is_server) - ssl_set_dh_param_ctx (ks_ssl->ctx, ssl_ctx->dhm_ctx ); -#if defined(ENABLE_PKCS11) - if (ssl_ctx->priv_key_pkcs11 != NULL) - ssl_set_own_cert_alt( ks_ssl->ctx, ssl_ctx->crt_chain, - 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 ); + ssl_set_dh_param_ctx (ks_ssl->ctx, ssl_ctx->dhm_ctx); + + ssl_set_own_cert (ks_ssl->ctx, ssl_ctx->crt_chain, ssl_ctx->priv_key); /* Initialise SSL verification */ #if P2MP_SERVER @@ -815,8 +854,8 @@ key_state_write_plaintext (struct key_state_ssl *ks, struct buffer *buf) if (0 == buf->len) { - return 0; perf_pop (); + return 0; } retval = ssl_write(ks->ctx, BPTR(buf), buf->len); @@ -1055,7 +1094,7 @@ key_state_read_plaintext (struct key_state_ssl *ks, struct buffer *buf, void print_details (struct key_state_ssl * ks_ssl, const char *prefix) { - const x509_cert *cert; + const x509_crt *cert; char s1[256]; char s2[256]; @@ -1068,7 +1107,7 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix) cert = ssl_get_peer_cert(ks_ssl->ctx); if (cert != NULL) { - openvpn_snprintf (s2, sizeof (s2), ", " counter_format " bit RSA", (counter_type) cert->rsa.len * 8); + openvpn_snprintf (s2, sizeof (s2), ", %zu bit key", pk_get_size(&cert->pk)); } msg (D_HANDSHAKE, "%s%s", s1, s2); diff --git a/src/openvpn/ssl_polarssl.h b/src/openvpn/ssl_polarssl.h index fc9aa78..b80a509 100644 --- a/src/openvpn/ssl_polarssl.h +++ b/src/openvpn/ssl_polarssl.h @@ -33,6 +33,7 @@ #include "syshead.h" #include <polarssl/ssl.h> +#include <polarssl/x509_crt.h> #if defined(ENABLE_PKCS11) #include <polarssl/pkcs11.h> @@ -64,9 +65,9 @@ struct tls_root_ctx { int endpoint; /**< Whether or not this is a server or a client */ dhm_context *dhm_ctx; /**< Diffie-Helmann-Merkle context */ - x509_cert *crt_chain; /**< Local Certificate chain */ - x509_cert *ca_chain; /**< CA chain for remote verification */ - rsa_context *priv_key; /**< Local private key */ + x509_crt *crt_chain; /**< Local Certificate chain */ + x509_crt *ca_chain; /**< CA chain for remote verification */ + pk_context *priv_key; /**< Local private key */ #if defined(ENABLE_PKCS11) pkcs11_context *priv_key_pkcs11; /**< PKCS11 private key */ #endif diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 9693b81..ca69b41 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -619,7 +619,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep string_replace_leading (subject, '-', '_'); /* extract the username (default is CN) */ - if (SUCCESS != x509_get_username (common_name, sizeof(common_name), + if (SUCCESS != backend_x509_get_username (common_name, sizeof(common_name), opt->x509_username_field, cert)) { if (!cert_depth) diff --git a/src/openvpn/ssl_verify_backend.h b/src/openvpn/ssl_verify_backend.h index 6f118c9..01e453e 100644 --- a/src/openvpn/ssl_verify_backend.h +++ b/src/openvpn/ssl_verify_backend.h @@ -109,7 +109,7 @@ unsigned char *x509_get_sha1_hash (openvpn_x509_cert_t *cert, struct gc_arena *g * * @return \c FAILURE, \c or SUCCESS */ -result_t x509_get_username (char *common_name, int cn_len, +result_t backend_x509_get_username (char *common_name, int cn_len, char * x509_username_field, openvpn_x509_cert_t *peer_cert); /* diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c index e1118d6..4750f02 100644 --- a/src/openvpn/ssl_verify_openssl.c +++ b/src/openvpn/ssl_verify_openssl.c @@ -200,7 +200,7 @@ extract_x509_field_ssl (X509_NAME *x509, const char *field_name, char *out, } result_t -x509_get_username (char *common_name, int cn_len, +backend_x509_get_username (char *common_name, int cn_len, char * x509_username_field, X509 *peer_cert) { #ifdef ENABLE_X509ALTUSERNAME @@ -585,6 +585,8 @@ x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject) BIO *in=NULL; int n,i; result_t retval = FAILURE; + struct gc_arena gc = gc_new(); + char *serial; in = BIO_new_file (crl_file, "r"); @@ -609,7 +611,8 @@ x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject) for (i = 0; i < n; i++) { revoked = (X509_REVOKED *)sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i); if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(peer_cert)) == 0) { - msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED",subject); + serial = backend_x509_get_serial_hex(peer_cert, &gc); + msg (D_HANDSHAKE, "CRL CHECK FAILED: %s (serial %s) is REVOKED", subject, (serial ? serial : "NOT AVAILABLE")); goto end; } } @@ -618,6 +621,7 @@ x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject) msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject); end: + gc_free(&gc); BIO_free(in); if (crl) X509_CRL_free (crl); diff --git a/src/openvpn/ssl_verify_polarssl.c b/src/openvpn/ssl_verify_polarssl.c index f8f9ab5..ac252a3 100644 --- a/src/openvpn/ssl_verify_polarssl.c +++ b/src/openvpn/ssl_verify_polarssl.c @@ -38,14 +38,15 @@ #if defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_POLARSSL) #include "ssl_verify.h" -#include <polarssl/error.h> #include <polarssl/bignum.h> +#include <polarssl/error.h> +#include <polarssl/oid.h> #include <polarssl/sha1.h> #define MAX_SUBJECT_LENGTH 256 int -verify_callback (void *session_obj, x509_cert *cert, int cert_depth, +verify_callback (void *session_obj, x509_crt *cert, int cert_depth, int *flags) { struct tls_session *session = (struct tls_session *) session_obj; @@ -90,8 +91,8 @@ verify_callback (void *session_obj, x509_cert *cert, int cert_depth, #endif result_t -x509_get_username (char *cn, int cn_len, - char *x509_username_field, x509_cert *cert) +backend_x509_get_username (char *cn, int cn_len, + char *x509_username_field, x509_crt *cert) { x509_name *name; @@ -102,7 +103,7 @@ x509_get_username (char *cn, int cn_len, /* Find common name */ while( name != NULL ) { - if( memcmp( name->oid.p, OID_CN, OID_SIZE(OID_CN) ) == 0) + if( memcmp( name->oid.p, OID_AT_CN, OID_SIZE(OID_AT_CN) ) == 0) break; name = name->next; @@ -127,8 +128,6 @@ x509_get_username (char *cn, int cn_len, char * backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc) { - int ret = 0; - int i = 0; char *buf = NULL; size_t buflen = 0; mpi serial_mpi = { 0 }; @@ -172,14 +171,14 @@ backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, struct gc_arena *gc) buf = gc_malloc(len, true, gc); - if(x509parse_serial_gets(buf, len-1, &cert->serial) < 0) + if(x509_serial_gets(buf, len-1, &cert->serial) < 0) buf = NULL; return buf; } unsigned char * -x509_get_sha1_hash (x509_cert *cert, struct gc_arena *gc) +x509_get_sha1_hash (x509_crt *cert, struct gc_arena *gc) { unsigned char *sha1_hash = gc_malloc(SHA_DIGEST_LENGTH, false, gc); sha1(cert->tbs.p, cert->tbs.len, sha1_hash); @@ -187,14 +186,14 @@ x509_get_sha1_hash (x509_cert *cert, struct gc_arena *gc) } char * -x509_get_subject(x509_cert *cert, struct gc_arena *gc) +x509_get_subject(x509_crt *cert, struct gc_arena *gc) { char tmp_subject[MAX_SUBJECT_LENGTH] = {0}; char *subject = NULL; int ret = 0; - ret = x509parse_dn_gets( tmp_subject, MAX_SUBJECT_LENGTH-1, &cert->subject ); + ret = x509_dn_gets( tmp_subject, MAX_SUBJECT_LENGTH-1, &cert->subject ); if (ret > 0) { /* Allocate the required space for the subject */ @@ -224,70 +223,28 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert) while( name != NULL ) { char name_expand[64+8]; + const char *shortname; - if( name->oid.len == 2 && memcmp( name->oid.p, OID_X520, 2 ) == 0 ) + if( 0 == oid_get_attr_short_name(&name->oid, &shortname) ) { - switch( name->oid.p[2] ) - { - case X520_COMMON_NAME: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_CN", - cert_depth); break; - - case X520_COUNTRY: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_C", - cert_depth); break; - - case X520_LOCALITY: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_L", - cert_depth); break; - - case X520_STATE: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_ST", - cert_depth); break; - - case X520_ORGANIZATION: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_O", - cert_depth); break; - - case X520_ORG_UNIT: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_OU", - cert_depth); break; - - default: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_0x%02X", cert_depth, name->oid.p[2]); - break; - } + openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_%s", + cert_depth, shortname); } - else if( name->oid.len == 8 && memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 ) - { - switch( name->oid.p[8] ) - { - case PKCS9_EMAIL: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_emailAddress", cert_depth); break; - - default: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_0x%02X", cert_depth, name->oid.p[8]); - break; - } - } - else - { - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_\?\?", - cert_depth); - } - - for( i = 0; i < name->val.len; i++ ) + else + { + openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_\?\?", + cert_depth); + } + + for( i = 0; i < name->val.len; i++ ) { - if( i >= (int) sizeof( s ) - 1 ) - break; + if( i >= (int) sizeof( s ) - 1 ) + break; - c = name->val.p[i]; - if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) - s[i] = '?'; - else s[i] = c; + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; } s[i] = '\0'; @@ -301,7 +258,7 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert) } result_t -x509_verify_ns_cert_type(const x509_cert *cert, const int usage) +x509_verify_ns_cert_type(const x509_crt *cert, const int usage) { if (usage == NS_CERT_CHECK_NONE) return SUCCESS; @@ -316,7 +273,7 @@ x509_verify_ns_cert_type(const x509_cert *cert, const int usage) } result_t -x509_verify_cert_ku (x509_cert *cert, const unsigned * const expected_ku, +x509_verify_cert_ku (x509_crt *cert, const unsigned * const expected_ku, int expected_len) { result_t fFound = FAILURE; @@ -349,7 +306,7 @@ x509_verify_cert_ku (x509_cert *cert, const unsigned * const expected_ku, } result_t -x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) +x509_verify_cert_eku (x509_crt *cert, const char * const expected_oid) { result_t fFound = FAILURE; @@ -368,8 +325,7 @@ x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) char oid_num_str[1024]; const char *oid_str; - oid_str = x509_oid_get_description(oid); - if (oid_str != NULL) + if (0 == oid_get_extended_key_usage( oid, &oid_str )) { msg (D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", oid_str, expected_oid); @@ -380,7 +336,7 @@ x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) } } - if (0 < x509_oid_get_numeric_string( oid_num_str, + if (0 < oid_get_numeric_string( oid_num_str, sizeof (oid_num_str), oid)) { msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", @@ -399,7 +355,7 @@ x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) } result_t -x509_write_pem(FILE *peercert_file, x509_cert *peercert) +x509_write_pem(FILE *peercert_file, x509_crt *peercert) { msg (M_WARN, "PolarSSL does not support writing peer certificate in PEM format"); return FAILURE; @@ -409,16 +365,18 @@ x509_write_pem(FILE *peercert_file, x509_cert *peercert) * check peer cert against CRL */ result_t -x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) +x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject) { result_t retval = FAILURE; x509_crl crl = {0}; + struct gc_arena gc = gc_new(); + char *serial; - int polar_retval = x509parse_crlfile(&crl, crl_file); + int polar_retval = x509_crl_parse_file(&crl, crl_file); if (polar_retval != 0) { char errstr[128]; - error_strerror(polar_retval, errstr, sizeof(errstr)); + polarssl_strerror(polar_retval, errstr, sizeof(errstr)); msg (M_WARN, "CRL: cannot read CRL from file %s (%s)", crl_file, errstr); goto end; } @@ -432,9 +390,10 @@ x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) goto end; } - if (0 != x509parse_revoked(cert, &crl)) + if (0 != x509_crt_revoked(cert, &crl)) { - msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED", subject); + serial = backend_x509_get_serial_hex(cert, &gc); + msg (D_HANDSHAKE, "CRL CHECK FAILED: %s (serial %s) is REVOKED", subject, (serial ? serial : "NOT AVAILABLE")); goto end; } @@ -442,6 +401,7 @@ x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) msg (D_HANDSHAKE, "CRL CHECK OK: %s",subject); end: + gc_free(&gc); x509_crl_free(&crl); return retval; } diff --git a/src/openvpn/ssl_verify_polarssl.h b/src/openvpn/ssl_verify_polarssl.h index b259081..b5157ed 100644 --- a/src/openvpn/ssl_verify_polarssl.h +++ b/src/openvpn/ssl_verify_polarssl.h @@ -33,11 +33,11 @@ #include "syshead.h" #include "misc.h" #include "manage.h" -#include <polarssl/x509.h> +#include <polarssl/x509_crt.h> #ifndef __OPENVPN_X509_CERT_T_DECLARED #define __OPENVPN_X509_CERT_T_DECLARED -typedef x509_cert openvpn_x509_cert_t; +typedef x509_crt openvpn_x509_cert_t; #endif /** @name Function for authenticating a new connection from a remote OpenVPN peer @@ -72,7 +72,7 @@ typedef x509_cert openvpn_x509_cert_t; * * @return The return value is 0 unless a fatal error occurred. */ -int verify_callback (void *session_obj, x509_cert *cert, int cert_depth, +int verify_callback (void *session_obj, x509_crt *cert, int cert_depth, int *flags); /** @} name Function for authenticating a new connection from a remote OpenVPN peer */ diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h index ffba4e8..24926ae 100644 --- a/src/openvpn/syshead.h +++ b/src/openvpn/syshead.h @@ -47,6 +47,7 @@ #ifdef _MSC_VER // Visual Studio #define __func__ __FUNCTION__ +#define __attribute__(x) #endif #if defined(__APPLE__) diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 3e20215..bb019c0 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -66,6 +66,8 @@ static void netsh_command (const struct argv *a, int n); static const char *netsh_get_id (const char *dev_node, struct gc_arena *gc); +static DWORD get_adapter_index_flexible (const char *name); + #endif #ifdef TARGET_SOLARIS @@ -633,7 +635,7 @@ void delete_route_connected_v6_net(struct tuntap * tt, * is still point to point and no layer 2 resolution is done... */ -char * +const char * create_arbitrary_remote( struct tuntap *tt, struct gc_arena * gc ) { in_addr_t remote; @@ -642,7 +644,7 @@ create_arbitrary_remote( struct tuntap *tt, struct gc_arena * gc ) if ( remote == tt->local ) remote ++; - return print_in_addr_t (remote, 0, &gc); + return print_in_addr_t (remote, 0, gc); } #endif @@ -1228,18 +1230,22 @@ do_ifconfig (struct tuntap *tt, if ( do_ipv6 ) { char * saved_actual; + char iface[64]; + DWORD idx; if (!strcmp (actual, "NULL")) msg (M_FATAL, "Error: When using --tun-ipv6, if you have more than one TAP-Windows adapter, you must also specify --dev-node"); - /* example: netsh interface ipv6 set address MyTap 2001:608:8003::d store=active */ + idx = get_adapter_index_flexible(actual); + openvpn_snprintf(iface, sizeof(iface), "interface=%lu", idx); + + /* example: netsh interface ipv6 set address interface=42 2001:608:8003::d store=active */ argv_printf (&argv, - "%s%sc interface ipv6 set address %s %s store=active", + "%s%sc interface ipv6 set address %s %s store=active", get_win_sys_path(), NETSH_PATH_SUFFIX, - actual, - ifconfig_ipv6_local ); - + win32_version_info() == WIN_XP ? actual : iface, + ifconfig_ipv6_local); netsh_command (&argv, 4); /* explicit route needed */ @@ -1249,6 +1255,8 @@ do_ifconfig (struct tuntap *tt, */ saved_actual = tt->actual_name; tt->actual_name = (char*) actual; + /* we use adapter_index in add_route_ipv6 */ + tt->adapter_index = idx; add_route_connected_v6_net(tt, es); tt->actual_name = saved_actual; } @@ -2389,7 +2397,6 @@ close_tun (struct tuntap *tt) } else if (tt) /* close and destroy */ { - struct gc_arena gc = gc_new (); struct argv argv; /* setup command, close tun dev (clears tt->actual_name!), run command diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index f35c96b..6c6ac4c 100644 --- a/src/openvpn/win32.c +++ b/src/openvpn/win32.c @@ -46,6 +46,34 @@ #include "memdbg.h" +#include "win32_wfp.h" + +#ifdef HAVE_VERSIONHELPERS_H +#include <versionhelpers.h> +#else +#include "compat-versionhelpers.h" +#endif + +/* WFP function pointers. Initialized in win_wfp_init_funcs() */ +func_ConvertInterfaceIndexToLuid ConvertInterfaceIndexToLuid = NULL; +func_FwpmEngineOpen0 FwpmEngineOpen0 = NULL; +func_FwpmEngineClose0 FwpmEngineClose0 = NULL; +func_FwpmFilterAdd0 FwpmFilterAdd0 = NULL; +func_FwpmSubLayerAdd0 FwpmSubLayerAdd0 = NULL; +func_FwpmSubLayerDeleteByKey0 FwpmSubLayerDeleteByKey0 = NULL; +func_FwpmFreeMemory0 FwpmFreeMemory0 = NULL; +func_FwpmGetAppIdFromFileName0 FwpmGetAppIdFromFileName0 = NULL; + +/* + * WFP firewall name. + */ +WCHAR * FIREWALL_NAME = L"OpenVPN"; /* GLOBAL */ + +/* + * WFP handle and GUID. + */ +static HANDLE m_hEngineHandle = NULL; /* GLOBAL */ + /* * Windows internal socket API state (opaque). */ @@ -324,6 +352,53 @@ net_event_win32_close (struct net_event_win32 *ne) * (2) Service mode -- map Windows event object to SIGTERM */ +static void +win_trigger_event(struct win32_signal *ws) +{ + if (ws->mode == WSO_MODE_SERVICE && HANDLE_DEFINED(ws->in.read)) + SetEvent (ws->in.read); + else /* generate a key-press event */ + { + DWORD tmp; + INPUT_RECORD ir; + HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE); + + CLEAR(ir); + ir.EventType = KEY_EVENT; + ir.Event.KeyEvent.bKeyDown = true; + if (!stdin_handle || !WriteConsoleInput(stdin_handle, &ir, 1, &tmp)) + msg(M_WARN|M_ERRNO, "WARN: win_trigger_event: WriteConsoleInput"); + } +} + +/* + * Callback to handle console ctrl events + */ +static bool WINAPI +win_ctrl_handler (DWORD signum) +{ + msg(D_LOW, "win_ctrl_handler: signal received (code=%lu)", (unsigned long) signum); + + if (siginfo_static.signal_received == SIGTERM) + return true; + + switch (signum) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + throw_signal(SIGTERM); + /* trigget the win32_signal to interrupt the event loop */ + win_trigger_event(&win32_signal); + return true; + break; + default: + msg(D_LOW, "win_ctrl_handler: signal (code=%lu) not handled", (unsigned long) signum); + break; + } + /* pass all other signals to the next handler */ + return false; +} + void win32_signal_clear (struct win32_signal *ws) { @@ -403,6 +478,9 @@ win32_signal_open (struct win32_signal *ws, ws->mode = WSO_MODE_SERVICE; } } + /* set the ctrl handler in both console and service modes */ + if (!SetConsoleCtrlHandler ((PHANDLER_ROUTINE) win_ctrl_handler, true)) + msg (M_WARN|M_ERRNO, "WARN: SetConsoleCtrlHandler failed"); } static bool @@ -512,6 +590,9 @@ win32_signal_get (struct win32_signal *ws) case 0x3E: /* F4 -> TERM */ ret = SIGTERM; break; + case 0x03: /* CTRL-C -> TERM */ + ret = SIGTERM; + break; } } if (ret) @@ -763,7 +844,12 @@ win_safe_filename (const char *fn) static char * env_block (const struct env_set *es) { - char * force_path = "PATH=C:\\Windows\\System32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem"; + char force_path[256]; + char *sysroot = get_win_sys_path(); + + if (!openvpn_snprintf(force_path, sizeof(force_path), "PATH=%s\\System32;%s;%s\\System32\\Wbem", + sysroot, sysroot, sysroot)) + msg(M_WARN, "env_block: default path truncated to %s", force_path); if (es) { @@ -1019,4 +1105,251 @@ win_get_tempdir() WideCharToMultiByte (CP_UTF8, 0, wtmpdir, -1, tmpdir, sizeof (tmpdir), NULL, NULL); return tmpdir; } + +bool +win_wfp_init_funcs () +{ + /* Initialize all WFP-related function pointers */ + HMODULE iphlpapiHandle; + HMODULE fwpuclntHandle; + + iphlpapiHandle = LoadLibrary("iphlpapi.dll"); + if (iphlpapiHandle == NULL) + { + msg (M_NONFATAL, "Can't load iphlpapi.dll"); + return false; + } + + fwpuclntHandle = LoadLibrary("fwpuclnt.dll"); + if (fwpuclntHandle == NULL) + { + msg (M_NONFATAL, "Can't load fwpuclnt.dll"); + return false; + } + + ConvertInterfaceIndexToLuid = (func_ConvertInterfaceIndexToLuid)GetProcAddress(iphlpapiHandle, "ConvertInterfaceIndexToLuid"); + FwpmFilterAdd0 = (func_FwpmFilterAdd0)GetProcAddress(fwpuclntHandle, "FwpmFilterAdd0"); + FwpmEngineOpen0 = (func_FwpmEngineOpen0)GetProcAddress(fwpuclntHandle, "FwpmEngineOpen0"); + FwpmEngineClose0 = (func_FwpmEngineClose0)GetProcAddress(fwpuclntHandle, "FwpmEngineClose0"); + FwpmSubLayerAdd0 = (func_FwpmSubLayerAdd0)GetProcAddress(fwpuclntHandle, "FwpmSubLayerAdd0"); + FwpmSubLayerDeleteByKey0 = (func_FwpmSubLayerDeleteByKey0)GetProcAddress(fwpuclntHandle, "FwpmSubLayerDeleteByKey0"); + FwpmFreeMemory0 = (func_FwpmFreeMemory0)GetProcAddress(fwpuclntHandle, "FwpmFreeMemory0"); + FwpmGetAppIdFromFileName0 = (func_FwpmGetAppIdFromFileName0)GetProcAddress(fwpuclntHandle, "FwpmGetAppIdFromFileName0"); + + if (!ConvertInterfaceIndexToLuid || + !FwpmFilterAdd0 || + !FwpmEngineOpen0 || + !FwpmEngineClose0 || + !FwpmSubLayerAdd0 || + !FwpmSubLayerDeleteByKey0 || + !FwpmFreeMemory0 || + !FwpmGetAppIdFromFileName0) + { + msg (M_NONFATAL, "Can't get address for all WFP-related procedures."); + return false; + } + + return true; +} + +bool +win_wfp_add_filter (HANDLE engineHandle, + const FWPM_FILTER0 *filter, + PSECURITY_DESCRIPTOR sd, + UINT64 *id) +{ + if (FwpmFilterAdd0(engineHandle, filter, sd, id) != ERROR_SUCCESS) + { + msg (M_NONFATAL, "Can't add WFP filter"); + return false; + } + return true; +} + +bool +win_wfp_block_dns (const NET_IFINDEX index) +{ + FWPM_SESSION0 session = {0}; + FWPM_SUBLAYER0 SubLayer = {0}; + NET_LUID tapluid; + UINT64 filterid; + WCHAR openvpnpath[MAX_PATH]; + FWP_BYTE_BLOB *openvpnblob = NULL; + FWPM_FILTER0 Filter = {0}; + FWPM_FILTER_CONDITION0 Condition[2] = {0}; + + /* Add temporary filters which don't survive reboots or crashes. */ + session.flags = FWPM_SESSION_FLAG_DYNAMIC; + + dmsg (D_LOW, "Opening WFP engine"); + + if (FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &m_hEngineHandle) != ERROR_SUCCESS) + { + msg (M_NONFATAL, "Can't open WFP engine"); + return false; + } + + if (UuidCreate(&SubLayer.subLayerKey) != NO_ERROR) + return false; + + /* Populate packet filter layer information. */ + SubLayer.displayData.name = FIREWALL_NAME; + SubLayer.displayData.description = FIREWALL_NAME; + SubLayer.flags = 0; + SubLayer.weight = 0x100; + + /* Add packet filter to our interface. */ + dmsg (D_LOW, "Adding WFP sublayer"); + if (FwpmSubLayerAdd0(m_hEngineHandle, &SubLayer, NULL) != ERROR_SUCCESS) + { + msg (M_NONFATAL, "Can't add WFP sublayer"); + return false; + } + + dmsg (D_LOW, "Blocking DNS using WFP"); + if (ConvertInterfaceIndexToLuid(index, &tapluid) != NO_ERROR) + { + msg (M_NONFATAL, "Can't convert interface index to LUID"); + return false; + } + dmsg (D_LOW, "Tap Luid: %I64d", tapluid.Value); + + /* Get OpenVPN path. */ + GetModuleFileNameW(NULL, openvpnpath, MAX_PATH); + + if (FwpmGetAppIdFromFileName0(openvpnpath, &openvpnblob) != ERROR_SUCCESS) + return false; + + /* Prepare filter. */ + Filter.subLayerKey = SubLayer.subLayerKey; + Filter.displayData.name = FIREWALL_NAME; + Filter.weight.type = FWP_EMPTY; + Filter.filterCondition = Condition; + Filter.numFilterConditions = 2; + + /* First filter. Block IPv4 DNS queries except from OpenVPN itself. */ + Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; + Filter.action.type = FWP_ACTION_BLOCK; + + Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT; + Condition[0].matchType = FWP_MATCH_EQUAL; + Condition[0].conditionValue.type = FWP_UINT16; + Condition[0].conditionValue.uint16 = 53; + + Condition[1].fieldKey = FWPM_CONDITION_ALE_APP_ID; + Condition[1].matchType = FWP_MATCH_NOT_EQUAL; + Condition[1].conditionValue.type = FWP_BYTE_BLOB_TYPE; + Condition[1].conditionValue.byteBlob = openvpnblob; + + /* Add filter condition to our interface. */ + if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid)) + goto err; + dmsg (D_LOW, "Filter (Block IPv4 DNS) added with ID=%I64d", filterid); + + /* Second filter. Block IPv6 DNS queries except from OpenVPN itself. */ + Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; + + /* Add filter condition to our interface. */ + if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid)) + goto err; + dmsg (D_LOW, "Filter (Block IPv6 DNS) added with ID=%I64d", filterid); + + /* Third filter. Permit IPv4 DNS queries from TAP. */ + Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4; + Filter.action.type = FWP_ACTION_PERMIT; + + Condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE; + Condition[1].matchType = FWP_MATCH_EQUAL; + Condition[1].conditionValue.type = FWP_UINT64; + Condition[1].conditionValue.uint64 = &tapluid.Value; + + /* Add filter condition to our interface. */ + if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid)) + goto err; + dmsg (D_LOW, "Filter (Permit IPv4 DNS queries from TAP) added with ID=%I64d", filterid); + + /* Forth filter. Permit IPv6 DNS queries from TAP. */ + Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6; + + /* Add filter condition to our interface. */ + if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid)) + goto err; + dmsg (D_LOW, "Filter (Permit IPv6 DNS queries from TAP) added with ID=%I64d", filterid); + + FwpmFreeMemory0((void **)&openvpnblob); + return true; + + err: + FwpmFreeMemory0((void **)&openvpnblob); + return false; +} + +bool +win_wfp_uninit() +{ + dmsg (D_LOW, "Uninitializing WFP"); + if (m_hEngineHandle) { + FwpmEngineClose0(m_hEngineHandle); + m_hEngineHandle = NULL; + } + return true; +} + +int +win32_version_info() +{ + if (!IsWindowsXPOrGreater()) + { + msg (M_FATAL, "Error: Windows version must be XP or greater."); + } + + if (!IsWindowsVistaOrGreater()) + { + return WIN_XP; + } + + if (!IsWindows7OrGreater()) + { + return WIN_VISTA; + } + + if (!IsWindows8OrGreater()) + { + return WIN_7; + } + else + { + return WIN_8; + } +} + +const char * +win32_version_string(struct gc_arena *gc, bool add_name) +{ + int version = win32_version_info(); + struct buffer out = alloc_buf_gc (256, gc); + + switch (version) + { + case WIN_XP: + buf_printf (&out, "5.1%s", add_name ? " (Windows XP)" : ""); + break; + case WIN_VISTA: + buf_printf (&out, "6.0%s", add_name ? " (Windows Vista)" : ""); + break; + case WIN_7: + buf_printf (&out, "6.1%s", add_name ? " (Windows 7)" : ""); + break; + case WIN_8: + buf_printf (&out, "6.2%s", add_name ? " (Windows 8 or greater)" : ""); + break; + default: + msg (M_NONFATAL, "Unknown Windows version: %d", version); + buf_printf (&out, "0.0%s", add_name ? " (unknown)" : ""); + break; + } + + return (const char *)out.data; +} + #endif diff --git a/src/openvpn/win32.h b/src/openvpn/win32.h index cc18f02..0990182 100644 --- a/src/openvpn/win32.h +++ b/src/openvpn/win32.h @@ -271,5 +271,22 @@ const char *win_get_tempdir(); /* Convert a string from UTF-8 to UCS-2 */ WCHAR *wide_string (const char* utf8, struct gc_arena *gc); +bool win_wfp_init_funcs(); +bool win_wfp_block_dns(const NET_IFINDEX index); +bool win_wfp_uninit(); + +#define WIN_XP 0 +#define WIN_VISTA 1 +#define WIN_7 2 +#define WIN_8 3 + +int win32_version_info(); + +/* +String representation of Windows version number and name, see +https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx +*/ +const char * win32_version_string(struct gc_arena *gc, bool add_name); + #endif #endif diff --git a/src/openvpn/win32_wfp.h b/src/openvpn/win32_wfp.h new file mode 100644 index 0000000..7559e5b --- /dev/null +++ b/src/openvpn/win32_wfp.h @@ -0,0 +1,359 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * Windows Filtering Platform (WFP) related prototypes, mostly stripped out of + * mingw-w64. + */ + +/* + * WFP-related defines and GUIDs. + */ + +#ifndef WIN32_WFP_H +#define WIN32_WFP_H + +#include <initguid.h> +#include <iphlpapi.h> +#include <rpc.h> +#include <rpcdce.h> + +#ifndef FWPM_SESSION_FLAG_DYNAMIC +#define FWPM_SESSION_FLAG_DYNAMIC 0x00000001 +#endif + +// c38d57d1-05a7-4c33-904f-7fbceee60e82 +DEFINE_GUID( + FWPM_LAYER_ALE_AUTH_CONNECT_V4, + 0xc38d57d1, + 0x05a7, + 0x4c33, + 0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82 +); + +// 4a72393b-319f-44bc-84c3-ba54dcb3b6b4 +DEFINE_GUID( + FWPM_LAYER_ALE_AUTH_CONNECT_V6, + 0x4a72393b, + 0x319f, + 0x44bc, + 0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4 +); + +// d78e1e87-8644-4ea5-9437-d809ecefc971 +DEFINE_GUID( + FWPM_CONDITION_ALE_APP_ID, + 0xd78e1e87, + 0x8644, + 0x4ea5, + 0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71 +); + +// c35a604d-d22b-4e1a-91b4-68f674ee674b +DEFINE_GUID( + FWPM_CONDITION_IP_REMOTE_PORT, + 0xc35a604d, + 0xd22b, + 0x4e1a, + 0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b +); + +// 4cd62a49-59c3-4969-b7f3-bda5d32890a4 +DEFINE_GUID( + FWPM_CONDITION_IP_LOCAL_INTERFACE, + 0x4cd62a49, + 0x59c3, + 0x4969, + 0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4 +); + +/* From fwptypes.h */ + +#define FWP_ACTION_FLAG_TERMINATING (0x00001000) +#define FWP_ACTION_FLAG_NON_TERMINATING (0x00002000) + +#define FWP_ACTION_BLOCK (0x1 | FWP_ACTION_FLAG_TERMINATING) +#define FWP_ACTION_PERMIT (0x2 | FWP_ACTION_FLAG_TERMINATING) + +typedef UINT32 FWP_ACTION_TYPE; + +typedef enum FWP_DATA_TYPE_ { + FWP_EMPTY = 0, + FWP_UINT8 = 1, + FWP_UINT16 = 2, + FWP_UINT32 = 3, + FWP_UINT64 = 4, + FWP_INT8 = 5, + FWP_INT16 = 6, + FWP_INT32 = 7, + FWP_INT64 = 8, + FWP_FLOAT = 9, + FWP_DOUBLE = 10, + FWP_BYTE_ARRAY16_TYPE = 11, + FWP_BYTE_BLOB_TYPE = 12, + FWP_SID = 13, + FWP_SECURITY_DESCRIPTOR_TYPE = 14, + FWP_TOKEN_INFORMATION_TYPE = 15, + FWP_TOKEN_ACCESS_INFORMATION_TYPE = 16, + FWP_UNICODE_STRING_TYPE = 17, + FWP_BYTE_ARRAY6_TYPE = 18, + FWP_SINGLE_DATA_TYPE_MAX = 0xff, + FWP_V4_ADDR_MASK = 0x100, + FWP_V6_ADDR_MASK = 0x101, + FWP_RANGE_TYPE = 0x102, + FWP_DATA_TYPE_MAX = 0x103 +} FWP_DATA_TYPE; + +typedef enum FWP_MATCH_TYPE_ { + FWP_MATCH_EQUAL = 0, + FWP_MATCH_GREATER = 1, + FWP_MATCH_LESS = 2, + FWP_MATCH_GREATER_OR_EQUAL = 3, + FWP_MATCH_LESS_OR_EQUAL = 4, + FWP_MATCH_RANGE = 5, + FWP_MATCH_FLAGS_ALL_SET = 6, + FWP_MATCH_FLAGS_ANY_SET = 7, + FWP_MATCH_FLAGS_NONE_SET = 8, + FWP_MATCH_EQUAL_CASE_INSENSITIVE = 9, + FWP_MATCH_NOT_EQUAL = 10, + FWP_MATCH_TYPE_MAX = 11 +} FWP_MATCH_TYPE; + +typedef struct FWP_BYTE_ARRAY6_ { + UINT8 byteArray6[6]; +} FWP_BYTE_ARRAY6; + +typedef struct FWP_BYTE_ARRAY16_ { + UINT8 byteArray16[16]; +} FWP_BYTE_ARRAY16; + +typedef struct FWP_BYTE_BLOB_ { + UINT32 size; + UINT8 *data; +} FWP_BYTE_BLOB; + +typedef struct FWP_TOKEN_INFORMATION_ { + ULONG sidCount; + PSID_AND_ATTRIBUTES sids; + ULONG restrictedSidCount; + PSID_AND_ATTRIBUTES restrictedSids; +} FWP_TOKEN_INFORMATION; + +typedef struct FWP_VALUE0_ { + FWP_DATA_TYPE type; + union { + UINT8 uint8; + UINT16 uint16; + UINT32 uint32; + UINT64 *uint64; + INT8 int8; + INT16 int16; + INT32 int32; + INT64 *int64; + float float32; + double *double64; + FWP_BYTE_ARRAY16 *byteArray16; + FWP_BYTE_BLOB *byteBlob; + SID *sid; + FWP_BYTE_BLOB *sd; + FWP_TOKEN_INFORMATION *tokenInformation; + FWP_BYTE_BLOB *tokenAccessInformation; + LPWSTR unicodeString; + FWP_BYTE_ARRAY6 *byteArray6; + }; +} FWP_VALUE0; + +typedef struct FWP_V4_ADDR_AND_MASK_ { + UINT32 addr; + UINT32 mask; +} FWP_V4_ADDR_AND_MASK; + +typedef struct FWP_V6_ADDR_AND_MASK_ { + UINT8 addr[16]; + UINT8 prefixLength; +} FWP_V6_ADDR_AND_MASK; + +typedef struct FWP_RANGE0_ { + FWP_VALUE0 valueLow; + FWP_VALUE0 valueHigh; +} FWP_RANGE0; + +typedef struct FWP_CONDITION_VALUE0_ { + FWP_DATA_TYPE type; + union { + UINT8 uint8; + UINT16 uint16; + UINT32 uint32; + UINT64 *uint64; + INT8 int8; + INT16 int16; + INT32 int32; + INT64 *int64; + float float32; + double *double64; + FWP_BYTE_ARRAY16 *byteArray16; + FWP_BYTE_BLOB *byteBlob; + SID *sid; + FWP_BYTE_BLOB *sd; + FWP_TOKEN_INFORMATION *tokenInformation; + FWP_BYTE_BLOB *tokenAccessInformation; + LPWSTR unicodeString; + FWP_BYTE_ARRAY6 *byteArray6; + FWP_V4_ADDR_AND_MASK *v4AddrMask; + FWP_V6_ADDR_AND_MASK *v6AddrMask; + FWP_RANGE0 *rangeValue; + }; +} FWP_CONDITION_VALUE0; + +typedef struct FWPM_DISPLAY_DATA0_ { + wchar_t *name; + wchar_t *description; +} FWPM_DISPLAY_DATA0; + +/* From fwpmtypes.h */ + +typedef struct FWPM_ACTION0_ { + FWP_ACTION_TYPE type; + union { + GUID filterType; + GUID calloutKey; + }; +} FWPM_ACTION0; + +typedef struct FWPM_SESSION0_ { + GUID sessionKey; + FWPM_DISPLAY_DATA0 displayData; + UINT32 flags; + UINT32 txnWaitTimeoutInMSec; + DWORD processId; + SID *sid; + wchar_t *username; + BOOL kernelMode; +} FWPM_SESSION0; + +typedef struct FWPM_SUBLAYER0_ { + GUID subLayerKey; + FWPM_DISPLAY_DATA0 displayData; + UINT16 flags; + GUID *providerKey; + FWP_BYTE_BLOB providerData; + UINT16 weight; +} FWPM_SUBLAYER0; + +typedef struct FWPM_FILTER_CONDITION0_ { + GUID fieldKey; + FWP_MATCH_TYPE matchType; + FWP_CONDITION_VALUE0 conditionValue; +} FWPM_FILTER_CONDITION0; + +typedef struct FWPM_FILTER0_ { + GUID filterKey; + FWPM_DISPLAY_DATA0 displayData; + UINT32 flags; + GUID *providerKey; + FWP_BYTE_BLOB providerData; + GUID layerKey; + GUID subLayerKey; + FWP_VALUE0 weight; + UINT32 numFilterConditions; + FWPM_FILTER_CONDITION0 *filterCondition; + FWPM_ACTION0 action; + union { + UINT64 rawContext; + GUID providerContextKey; + }; + GUID *reserved; + UINT64 filterId; + FWP_VALUE0 effectiveWeight; +} FWPM_FILTER0; + +/* Typedefs of WFP functions */ + +#define NETIO_STATUS DWORD + +typedef NETIO_STATUS *(WINAPI *func_ConvertInterfaceIndexToLuid)( + NET_IFINDEX InterfaceIndex, + PNET_LUID InterfaceLuid +); + +typedef DWORD *(WINAPI *func_FwpmEngineOpen0)( + const wchar_t *serverName, + UINT32 authnService, + SEC_WINNT_AUTH_IDENTITY_W *authIdentity, + const FWPM_SESSION0 *session, + HANDLE *engineHandle +); + +typedef DWORD *(WINAPI *func_FwpmEngineClose0)( + HANDLE engineHandle +); + +typedef DWORD *(WINAPI *func_FwpmFilterAdd0)( + HANDLE engineHandle, + const FWPM_FILTER0 *filter, + PSECURITY_DESCRIPTOR sd, + UINT64 *id +); + +typedef DWORD *(WINAPI *func_FwpmSubLayerAdd0)( + HANDLE engineHandle, + const FWPM_SUBLAYER0 *subLayer, + PSECURITY_DESCRIPTOR sd +); + +typedef DWORD *(WINAPI *func_FwpmSubLayerDeleteByKey0)( + HANDLE engineHandle, + const GUID *key +); + +typedef void *(WINAPI *func_FwpmFreeMemory0)( + void **p +); + +typedef DWORD *(WINAPI *func_FwpmGetAppIdFromFileName0)( + const wchar_t *fileName, + FWP_BYTE_BLOB **appId +); + +#endif diff --git a/src/openvpnserv/openvpnserv.vcxproj b/src/openvpnserv/openvpnserv.vcxproj index 0b75ed0..2a8943d 100644 --- a/src/openvpnserv/openvpnserv.vcxproj +++ b/src/openvpnserv/openvpnserv.vcxproj @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup Label="ProjectConfigurations"> <ProjectConfiguration Include="Debug|Win32"> <Configuration>Debug</Configuration> @@ -20,10 +20,12 @@ <ConfigurationType>Application</ConfigurationType> <CharacterSet>MultiByte</CharacterSet> <WholeProgramOptimization>true</WholeProgramOptimization> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <ConfigurationType>Application</ConfigurationType> <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v120</PlatformToolset> </PropertyGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <ImportGroup Label="ExtensionSettings"> diff --git a/src/plugins/auth-pam/auth-pam.c b/src/plugins/auth-pam/auth-pam.c index bd71792..95692ab 100644 --- a/src/plugins/auth-pam/auth-pam.c +++ b/src/plugins/auth-pam/auth-pam.c @@ -642,6 +642,9 @@ my_conv (int n, const struct pam_message **msg_array, if (ret == PAM_SUCCESS) *response_array = aresp; + else + free(aresp); + return ret; } @@ -1,9 +1,9 @@ dnl define the OpenVPN version define([PRODUCT_NAME], [OpenVPN]) define([PRODUCT_TARNAME], [openvpn]) -define([PRODUCT_VERSION], [2.3.8]) +define([PRODUCT_VERSION], [2.3.10]) define([PRODUCT_BUGREPORT], [openvpn-users@lists.sourceforge.net]) -define([PRODUCT_VERSION_RESOURCE], [2,3,8,0]) +define([PRODUCT_VERSION_RESOURCE], [2,3,10,0]) dnl define the TAP version define([PRODUCT_TAP_WIN_COMPONENT_ID], [tap0901]) define([PRODUCT_TAP_WIN_MIN_MAJOR], [9]) |