diff options
Diffstat (limited to 'src/openvpn')
37 files changed, 832 insertions, 311 deletions
diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 5d38628..2e602f1 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -119,6 +119,7 @@ openvpn_LDADD = \ $(OPTIONAL_PKCS11_HELPER_LIBS) \ $(OPTIONAL_CRYPTO_LIBS) \ $(OPTIONAL_SELINUX_LIBS) \ + $(OPTIONAL_SYSTEMD_LIBS) \ $(OPTIONAL_DL_LIBS) if WIN32 openvpn_SOURCES += openvpn_win32_resources.rc diff --git a/src/openvpn/Makefile.in b/src/openvpn/Makefile.in index b5a6c69..ea9547c 100644 --- a/src/openvpn/Makefile.in +++ b/src/openvpn/Makefile.in @@ -181,7 +181,7 @@ openvpn_DEPENDENCIES = $(top_builddir)/src/compat/libcompat.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent @@ -316,8 +316,11 @@ OPTIONAL_LZO_LIBS = @OPTIONAL_LZO_LIBS@ OPTIONAL_PKCS11_HELPER_CFLAGS = @OPTIONAL_PKCS11_HELPER_CFLAGS@ OPTIONAL_PKCS11_HELPER_LIBS = @OPTIONAL_PKCS11_HELPER_LIBS@ OPTIONAL_SELINUX_LIBS = @OPTIONAL_SELINUX_LIBS@ +OPTIONAL_SYSTEMD_LIBS = @OPTIONAL_SYSTEMD_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ +P11KIT_CFLAGS = @P11KIT_CFLAGS@ +P11KIT_LIBS = @P11KIT_LIBS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ @@ -344,6 +347,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCKETS_LIBS = @SOCKETS_LIBS@ STRIP = @STRIP@ +SYSTEMD_ASK_PASSWORD = @SYSTEMD_ASK_PASSWORD@ TAP_CFLAGS = @TAP_CFLAGS@ TAP_WIN_COMPONENT_ID = @TAP_WIN_COMPONENT_ID@ TAP_WIN_MIN_MAJOR = @TAP_WIN_MIN_MAJOR@ @@ -384,6 +388,8 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +libsystemd_CFLAGS = @libsystemd_CFLAGS@ +libsystemd_LIBS = @libsystemd_LIBS@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ @@ -451,7 +457,8 @@ openvpn_SOURCES = base64.c base64.h basic.h buffer.c buffer.h \ openvpn_LDADD = $(top_builddir)/src/compat/libcompat.la \ $(SOCKETS_LIBS) $(OPTIONAL_LZO_LIBS) \ $(OPTIONAL_PKCS11_HELPER_LIBS) $(OPTIONAL_CRYPTO_LIBS) \ - $(OPTIONAL_SELINUX_LIBS) $(OPTIONAL_DL_LIBS) $(am__append_3) + $(OPTIONAL_SELINUX_LIBS) $(OPTIONAL_SYSTEMD_LIBS) \ + $(OPTIONAL_DL_LIBS) $(am__append_3) all: all-am .SUFFIXES: @@ -465,9 +472,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build/ltrc.inc $(am_ exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/openvpn/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/openvpn/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/openvpn/Makefile + $(AUTOMAKE) --foreign src/openvpn/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/openvpn/base64.c b/src/openvpn/base64.c index bb89aae..7dccec2 100644 --- a/src/openvpn/base64.c +++ b/src/openvpn/base64.c @@ -110,7 +110,7 @@ token_decode(const char *token) int i; unsigned int val = 0; int marker = 0; - if (strlen(token) < 4) + if (!token[0] || !token[1] || !token[2] || !token[3]) return DECODE_ERROR; for (i = 0; i < 4; i++) { val *= 64; diff --git a/src/openvpn/console.c b/src/openvpn/console.c index afda8ca..d66d408 100644 --- a/src/openvpn/console.c +++ b/src/openvpn/console.c @@ -34,6 +34,10 @@ #include "buffer.h" #include "misc.h" +#ifdef ENABLE_SYSTEMD +#include <systemd/sd-daemon.h> +#endif + #ifdef WIN32 #include "win32.h" @@ -143,14 +147,14 @@ close_tty (FILE *fp) static bool check_systemd_running () { - struct stat a, b; + struct stat c; /* We simply test whether the systemd cgroup hierarchy is - * mounted */ + * mounted, as well as the systemd-ask-password executable + * being available */ - return (lstat("/sys/fs/cgroup", &a) == 0) - && (lstat("/sys/fs/cgroup/systemd", &b) == 0) - && (a.st_dev != b.st_dev); + return (sd_booted() > 0) + && (stat(SYSTEMD_ASK_PASSWORD_PATH, &c) == 0); } @@ -162,7 +166,7 @@ get_console_input_systemd (const char *prompt, const bool echo, char *input, con struct argv argv; argv_init (&argv); - argv_printf (&argv, "/bin/systemd-ask-password"); + argv_printf (&argv, SYSTEMD_ASK_PASSWORD_PATH); argv_printf_cat (&argv, "%s", prompt); if ((std_out = openvpn_popen (&argv, NULL)) < 0) { diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index d9adf5b..aa93a7b 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -100,10 +100,10 @@ openvpn_encrypt (struct buffer *buf, struct buffer work, { uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH]; const int iv_size = cipher_ctx_iv_length (ctx->cipher); - const unsigned int mode = cipher_ctx_mode (ctx->cipher); + const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher); int outlen; - if (mode == OPENVPN_MODE_CBC) + if (cipher_kt_mode_cbc(cipher_kt)) { CLEAR (iv_buf); @@ -119,7 +119,7 @@ openvpn_encrypt (struct buffer *buf, struct buffer work, ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true)); } } - else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB) + else if (cipher_kt_mode_ofb_cfb(cipher_kt)) { struct packet_id_net pin; struct buffer b; @@ -171,7 +171,10 @@ openvpn_encrypt (struct buffer *buf, struct buffer work, /* Flush the encryption buffer */ ASSERT(cipher_ctx_final(ctx->cipher, BPTR (&work) + outlen, &outlen)); work.len += outlen; - ASSERT (outlen == iv_size); + + /* For all CBC mode ciphers, check the last block is complete */ + ASSERT (cipher_kt_mode (cipher_kt) != OPENVPN_MODE_CBC || + outlen == iv_size); /* prepend the IV to the ciphertext */ if (opt->flags & CO_USE_IV) @@ -272,8 +275,8 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, if (ctx->cipher) { - const unsigned int mode = cipher_ctx_mode (ctx->cipher); const int iv_size = cipher_ctx_iv_length (ctx->cipher); + const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher); uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH]; int outlen; @@ -320,7 +323,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, /* Get packet ID from plaintext buffer or IV, depending on cipher mode */ { - if (mode == OPENVPN_MODE_CBC) + if (cipher_kt_mode_cbc(cipher_kt)) { if (opt->packet_id) { @@ -329,7 +332,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, have_pin = true; } } - else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB) + else if (cipher_kt_mode_ofb_cfb(cipher_kt)) { struct buffer b; @@ -400,11 +403,27 @@ crypto_adjust_frame_parameters(struct frame *frame, bool packet_id, bool packet_id_long_form) { - frame_add_to_extra_frame (frame, - (packet_id ? packet_id_size (packet_id_long_form) : 0) + - ((cipher_defined && use_iv) ? cipher_kt_iv_size (kt->cipher) : 0) + - (cipher_defined ? cipher_kt_block_size (kt->cipher) : 0) + /* worst case padding expansion */ - kt->hmac_length); + size_t crypto_overhead = 0; + + if (packet_id) + crypto_overhead += packet_id_size (packet_id_long_form); + + if (cipher_defined) + { + if (use_iv) + crypto_overhead += cipher_kt_iv_size (kt->cipher); + + if (cipher_kt_mode_cbc (kt->cipher)) + /* worst case padding expansion */ + crypto_overhead += cipher_kt_block_size (kt->cipher); + } + + crypto_overhead += kt->hmac_length; + + frame_add_to_extra_frame (frame, crypto_overhead); + + msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for crypto by %zu bytes", + __func__, crypto_overhead); } /* @@ -426,17 +445,12 @@ init_key_type (struct key_type *kt, const char *ciphername, /* check legal cipher mode */ { - const unsigned int mode = cipher_kt_mode (kt->cipher); - if (!(mode == OPENVPN_MODE_CBC -#ifdef ALLOW_NON_CBC_CIPHERS - || (cfb_ofb_allowed && (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB)) + if (!(cipher_kt_mode_cbc(kt->cipher) +#ifdef ENABLE_OFB_CFB_MODE + || (cfb_ofb_allowed && cipher_kt_mode_ofb_cfb(kt->cipher)) #endif )) -#ifdef ENABLE_SMALL msg (M_FATAL, "Cipher '%s' mode not supported", ciphername); -#else - msg (M_FATAL, "Cipher '%s' uses a mode not supported by " PACKAGE_NAME " in your current configuration. CBC mode is always supported, while CFB and OFB modes are supported only when using SSL/TLS authentication and key exchange mode, and when " PACKAGE_NAME " has been built with ALLOW_NON_CBC_CIPHERS.", ciphername); -#endif } } else @@ -606,18 +620,10 @@ fixup_key (struct key *key, const struct key_type *kt) void check_replay_iv_consistency (const struct key_type *kt, bool packet_id, bool use_iv) { - if (cfb_ofb_mode (kt) && !(packet_id && use_iv)) - msg (M_FATAL, "--no-replay or --no-iv cannot be used with a CFB or OFB mode cipher"); -} + ASSERT(kt); -bool -cfb_ofb_mode (const struct key_type* kt) -{ - if (kt && kt->cipher) { - const unsigned int mode = cipher_kt_mode (kt->cipher); - return mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB; - } - return false; + if (cipher_kt_mode_ofb_cfb(kt->cipher) && !(packet_id && use_iv)) + msg (M_FATAL, "--no-replay or --no-iv cannot be used with a CFB or OFB mode cipher"); } /* @@ -797,6 +803,7 @@ get_tls_handshake_key (const struct key_type *key_type, msg (M_INFO, "Control Channel Authentication: using '%s' as a free-form passphrase file", passphrase_file); + msg (M_WARN, "DEPRECATED OPTION: Using freeform files for tls-auth is deprecated and is not supported in OpenVPN 2.4 or newer versions"); } } /* handle key direction */ diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index 3b4b88e..e489827 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -6,7 +6,7 @@ * packet compression. * * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> + * Copyright (C) 2010-2014 Fox Crypto B.V. <openvpn@fox-it.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -25,6 +25,76 @@ /** * @file Data Channel Cryptography Module + * + * @addtogroup data_crypto Data Channel Crypto module + * + * @par Crypto packet formats + * The Data Channel Crypto module supports a number of crypto modes and + * configurable options. The actual packet format depends on these options. A + * Data Channel packet can consist of: + * - \b Opcode, one byte specifying the packet type (see @ref network_protocol + * "Network protocol"). + * - \b Peer-id, if using the v2 data channel packet format (see @ref + * network_protocol "Network protocol"). + * - \b HMAC, covering the ciphertext IV + ciphertext. The HMAC size depends + * on the \c \-\-auth option. If \c \-\-auth \c none is specified, there is no + * HMAC at all. + * - \b Ciphertext \b IV, if not disabled by \c \-\-no-iv. The IV size depends on + * the \c \-\-cipher option. + * - \b Packet \b ID, a 32-bit incrementing packet counter that provides replay + * protection (if not disabled by \c \-\-no-replay). + * - \b Timestamp, a 32-bit timestamp of the current time. + * - \b Payload, the plain text network packet to be encrypted (unless + * encryption is disabled by using \c \-\-cipher \c none). The payload might + * already be compressed (see @ref compression "Compression module"). + * + * @par + * This section does not discuss the opcode and peer-id, since those do not + * depend on the data channel crypto. See @ref network_protocol + * "Network protocol" for more information on those. + * + * @par + * \e Legenda \n + * <tt>[ xxx ]</tt> = unprotected \n + * <tt>[ - xxx - ]</tt> = authenticated \n + * <tt>[ * xxx * ]</tt> = encrypted and authenticated + * + * @par + * <b>CBC data channel cypto format</b> \n + * In CBC mode, both TLS-mode and static key mode are supported. The IV + * consists of random bits to provide unpredictable IVs. \n + * <i>CBC IV format:</i> \n + * <tt> [ - random - ] </tt> \n + * <i>CBC data channel crypto format in TLS-mode:</i> \n + * <tt> [ HMAC ] [ - IV - ] [ * packet ID * ] [ * packet payload * ] </tt> \n + * <i>CBC data channel crypto format in static key mode:</i> \n + * <tt> [ HMAC ] [ - IV - ] [ * packet ID * ] [ * timestamp * ] + * [ * packet payload * ] </tt> + * + * @par + * <b>CFB/OFB data channel crypto format</b> \n + * CFB and OFB modes are only supported in TLS mode. In these modes, the IV + * consists of the packet counter and a timestamp. If the IV is more than 8 + * bytes long, the remaining space is filled with zeroes. The packet counter may + * not roll over within a single TLS sessions. This results in a unique IV for + * each packet, as required by the CFB and OFB cipher modes. + * + * @par + * <i>CFB/OFB IV format:</i> \n + * <tt> [ - packet ID - ] [ - timestamp - ] [ - opt: zero-padding - ] </tt>\n + * <i>CFB/OFB data channel crypto format:</i> \n + * <tt> [ HMAC ] [ - IV - ] [ * packet payload * ] </tt> + * + * @par + * <b>No-crypto data channel format</b> \n + * In no-crypto mode (\c \-\-cipher \c none is specified), both TLS-mode and + * static key mode are supported. No encryption will be performed on the packet, + * but packets can still be authenticated. This mode does not require an IV.\n + * <i>No-crypto data channel crypto format in TLS-mode:</i> \n + * <tt> [ HMAC ] [ - packet ID - ] [ - packet payload - ] </tt> \n + * <i>No-crypto data channel crypto format in static key mode:</i> \n + * <tt> [ HMAC ] [ - packet ID - ] [ - timestamp - ] [ - packet payload - ] </tt> + * */ #ifndef CRYPTO_H @@ -32,8 +102,6 @@ #ifdef ENABLE_CRYPTO -#define ALLOW_NON_CBC_CIPHERS - #include "crypto_backend.h" #include "basic.h" #include "buffer.h" @@ -189,8 +257,6 @@ bool write_key (const struct key *key, const struct key_type *kt, int read_key (struct key *key, const struct key_type *kt, struct buffer *buf); -bool cfb_ofb_mode (const struct key_type* kt); - void init_key_type (struct key_type *kt, const char *ciphername, bool ciphername_defined, const char *authname, bool authname_defined, int keysize, bool cfb_ofb_allowed, bool warn); diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h index 5ae47e6..4e45df0 100644 --- a/src/openvpn/crypto_backend.h +++ b/src/openvpn/crypto_backend.h @@ -223,13 +223,31 @@ int cipher_kt_block_size (const cipher_kt_t *cipher_kt); /** * Returns the mode that the cipher runs in. * - * @param cipher_kt Static cipher parameters + * @param cipher_kt Static cipher parameters. May not be NULL. * * @return Cipher mode, either \c OPENVPN_MODE_CBC, \c * OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB */ int cipher_kt_mode (const cipher_kt_t *cipher_kt); +/** + * Check if the supplied cipher is a supported CBC mode cipher. + * + * @param cipher Static cipher parameters. + * + * @return true iff the cipher is a CBC mode cipher. + */ +bool cipher_kt_mode_cbc(const cipher_kt_t *cipher); + +/** + * Check if the supplied cipher is a supported OFB or CFB mode cipher. + * + * @param cipher Static cipher parameters. + * + * @return true iff the cipher is a OFB or CFB mode cipher. + */ +bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher); + /** * @@ -288,6 +306,16 @@ int cipher_ctx_block_size (const cipher_ctx_t *ctx); int cipher_ctx_mode (const cipher_ctx_t *ctx); /** + * Returns the static cipher parameters for this context. + * + * @param ctx Cipher's context. May not be NULL. + * + * @return Static cipher parameters for the supplied context. + */ +const cipher_kt_t *cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) + __attribute__((nonnull)); + +/** * Resets the given cipher context, setting the IV to the specified value. * Preserves the associated key information. * diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c index 1501bc8..348bdee 100644 --- a/src/openvpn/crypto_openssl.c +++ b/src/openvpn/crypto_openssl.c @@ -40,6 +40,7 @@ #include "basic.h" #include "buffer.h" #include "integer.h" +#include "crypto.h" #include "crypto_backend.h" #include <openssl/objects.h> #include <openssl/evp.h> @@ -84,24 +85,6 @@ #endif -static inline int -EVP_CipherInit_ov (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, uint8_t *key, uint8_t *iv, int enc) -{ - return EVP_CipherInit (ctx, type, key, iv, enc); -} - -static inline int -EVP_CipherUpdate_ov (EVP_CIPHER_CTX *ctx, uint8_t *out, int *outl, uint8_t *in, int inl) -{ - return EVP_CipherUpdate (ctx, out, outl, in, inl); -} - -static inline bool -cipher_ok (const char* name) -{ - return true; -} - #ifndef EVP_CIPHER_name #define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) #endif @@ -306,25 +289,30 @@ show_available_ciphers () "used as a parameter to the --cipher option. The default\n" "key size is shown as well as whether or not it can be\n" "changed with the --keysize directive. Using a CBC mode\n" - "is recommended.\n\n"); + "is recommended. In static key mode only CBC mode is allowed.\n\n"); #endif for (nid = 0; nid < 10000; ++nid) /* is there a better way to get the size of the nid list? */ { const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid); - if (cipher && cipher_ok (OBJ_nid2sn (nid))) + if (cipher) { - const unsigned int mode = EVP_CIPHER_mode (cipher); - if (mode == EVP_CIPH_CBC_MODE -#ifdef ALLOW_NON_CBC_CIPHERS - || mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE + if (cipher_kt_mode_cbc(cipher) +#ifdef ENABLE_OFB_CFB_MODE + || cipher_kt_mode_ofb_cfb(cipher) #endif ) - printf ("%s %d bit default key (%s)\n", - OBJ_nid2sn (nid), - EVP_CIPHER_key_length (cipher) * 8, - ((EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ? - "variable" : "fixed")); + { + const char *var_key_size = + (EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ? + "variable" : "fixed"; + const char *ssl_only = cipher_kt_mode_ofb_cfb(cipher) ? + " (TLS client/server mode)" : ""; + + printf ("%s %d bit default key (%s)%s\n", OBJ_nid2sn (nid), + EVP_CIPHER_key_length (cipher) * 8, var_key_size, + ssl_only); + } } } printf ("\n"); @@ -491,7 +479,7 @@ cipher_kt_get (const char *ciphername) cipher = EVP_get_cipherbyname (ciphername); - if ((NULL == cipher) || !cipher_ok (OBJ_nid2sn (EVP_CIPHER_nid (cipher)))) + if (NULL == cipher) msg (M_SSLERR, "Cipher algorithm '%s' not found", ciphername); if (EVP_CIPHER_key_length (cipher) > MAX_CIPHER_KEY_LENGTH) @@ -536,6 +524,29 @@ cipher_kt_mode (const EVP_CIPHER *cipher_kt) return EVP_CIPHER_mode (cipher_kt); } +bool +cipher_kt_mode_cbc(const cipher_kt_t *cipher) +{ + return cipher && cipher_kt_mode(cipher) == OPENVPN_MODE_CBC +#ifdef EVP_CIPH_FLAG_AEAD_CIPHER + /* Exclude AEAD cipher modes, they require a different API */ + && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) +#endif + ; +} + +bool +cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher) +{ + return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB || + cipher_kt_mode(cipher) == OPENVPN_MODE_CFB) +#ifdef EVP_CIPH_FLAG_AEAD_CIPHER + /* Exclude AEAD cipher modes, they require a different API */ + && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) +#endif + ; +} + /* * * Generic cipher context functions @@ -552,13 +563,13 @@ cipher_ctx_init (EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, CLEAR (*ctx); EVP_CIPHER_CTX_init (ctx); - if (!EVP_CipherInit_ov (ctx, kt, NULL, NULL, enc)) + if (!EVP_CipherInit (ctx, kt, NULL, NULL, enc)) msg (M_SSLERR, "EVP cipher init #1"); #ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH if (!EVP_CIPHER_CTX_set_key_length (ctx, key_len)) msg (M_SSLERR, "EVP set key size"); #endif - if (!EVP_CipherInit_ov (ctx, NULL, key, NULL, enc)) + if (!EVP_CipherInit (ctx, NULL, key, NULL, enc)) msg (M_SSLERR, "EVP cipher init #2"); /* make sure we used a big enough key */ @@ -589,17 +600,24 @@ cipher_ctx_mode (const EVP_CIPHER_CTX *ctx) return EVP_CIPHER_CTX_mode (ctx); } +const cipher_kt_t * +cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) +{ + return EVP_CIPHER_CTX_cipher(ctx); +} + + int cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf) { - return EVP_CipherInit_ov (ctx, NULL, NULL, iv_buf, -1); + return EVP_CipherInit (ctx, NULL, NULL, iv_buf, -1); } int cipher_ctx_update (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len, uint8_t *src, int src_len) { - return EVP_CipherUpdate_ov (ctx, dst, dst_len, src, src_len); + return EVP_CipherUpdate (ctx, dst, dst_len, src, src_len); } int diff --git a/src/openvpn/crypto_polarssl.c b/src/openvpn/crypto_polarssl.c index 1f27d6c..af79029 100644 --- a/src/openvpn/crypto_polarssl.c +++ b/src/openvpn/crypto_polarssl.c @@ -416,6 +416,19 @@ cipher_kt_mode (const cipher_info_t *cipher_kt) return cipher_kt->mode; } +bool +cipher_kt_mode_cbc(const cipher_kt_t *cipher) +{ + return cipher && cipher_kt_mode(cipher) == OPENVPN_MODE_CBC; +} + +bool +cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher) +{ + return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB || + cipher_kt_mode(cipher) == OPENVPN_MODE_CFB); +} + /* * @@ -464,6 +477,14 @@ int cipher_ctx_mode (const cipher_context_t *ctx) return cipher_kt_mode(ctx->cipher_info); } +const cipher_kt_t * +cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) +{ + ASSERT(NULL != ctx); + + return ctx->cipher_info; +} + int cipher_ctx_reset (cipher_context_t *ctx, uint8_t *iv_buf) { return 0 == cipher_reset(ctx, iv_buf); diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 024cd58..217fbb3 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -331,6 +331,7 @@ void check_server_poll_timeout_dowork (struct context *c) { event_timeout_reset (&c->c2.server_poll_interval); + ASSERT(c->c2.tls_multi); if (!tls_initial_packet_received (c->c2.tls_multi)) { msg (M_INFO, "Server poll timeout, restarting"); @@ -952,6 +953,15 @@ read_incoming_tun (struct context *c) return; } + /* 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"); + perf_pop(); + return; + } + /* Check the status return from read() */ check_status (c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap); diff --git a/src/openvpn/helper.c b/src/openvpn/helper.c index d9eef03..339e2ae 100644 --- a/src/openvpn/helper.c +++ b/src/openvpn/helper.c @@ -232,6 +232,8 @@ helper_client_server (struct options *o) * if !nopool: * ifconfig-pool 10.8.0.2 10.8.0.254 255.255.255.0 * push "route-gateway 10.8.0.1" + * if route-gateway unset: + * route-gateway 10.8.0.2 */ if (o->server_defined) @@ -311,8 +313,10 @@ helper_client_server (struct options *o) ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end); } o->ifconfig_pool_netmask = o->server_netmask; - + push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE); + if (!o->route_default_gateway) + o->route_default_gateway = print_in_addr_t (o->server_network + 2, 0, &o->gc); } else ASSERT (0); @@ -530,7 +534,7 @@ helper_tcp_nodelay (struct options *o) } else { - ASSERT (0); + o->sockflags |= SF_TCP_NODELAY; } } #endif diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 52d370b..c99e775 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -183,10 +183,12 @@ ce_management_query_proxy (struct context *c) if (management) { gc = gc_new (); - struct buffer out = alloc_buf_gc (256, &gc); - buf_printf (&out, ">PROXY:%u,%s,%s", (l ? l->current : 0) + 1, - (proto_is_udp (ce->proto) ? "UDP" : "TCP"), np (ce->remote)); - management_notify_generic (management, BSTR (&out)); + { + struct buffer out = alloc_buf_gc (256, &gc); + buf_printf (&out, ">PROXY:%u,%s,%s", (l ? l->current : 0) + 1, + (proto_is_udp (ce->proto) ? "UDP" : "TCP"), np (ce->remote)); + management_notify_generic (management, BSTR (&out)); + } ce->flags |= CE_MAN_QUERY_PROXY; while (ce->flags & CE_MAN_QUERY_PROXY) { @@ -908,7 +910,6 @@ do_genkey (const struct options * options) bool do_persist_tuntap (const struct options *options) { -#ifdef ENABLE_FEATURE_TUN_PERSIST if (options->persist_config) { /* sanity check on options for --mktun or --rmtun */ @@ -924,14 +925,21 @@ do_persist_tuntap (const struct options *options) ) msg (M_FATAL|M_OPTERR, "options --mktun or --rmtun should only be used together with --dev"); +#ifdef ENABLE_FEATURE_TUN_PERSIST tuncfg (options->dev, options->dev_type, options->dev_node, options->persist_mode, options->username, options->groupname, &options->tuntap_options); if (options->persist_mode && options->lladdr) set_lladdr(options->dev, options->lladdr, NULL); return true; - } +#else + msg( M_FATAL|M_OPTERR, + "options --mktun and --rmtun are not available on your operating " + "system. Please check 'man tun' (or 'tap'), whether your system " + "supports using 'ifconfig %s create' / 'destroy' to create/remove " + "persistant tunnel interfaces.", options->dev ); #endif + } return false; } @@ -939,23 +947,20 @@ do_persist_tuntap (const struct options *options) * Should we become a daemon? * Return true if we did it. */ -static bool -possibly_become_daemon (const struct options *options, const bool first_time) +bool +possibly_become_daemon (const struct options *options) { bool ret = false; - if (first_time && options->daemon) + if (options->daemon) { ASSERT (!options->inetd); - if (daemon (options->cd_dir != NULL, options->log) < 0) + /* Don't chdir immediately, but the end of the init sequence, if needed */ + if (daemon (1, options->log) < 0) msg (M_ERR, "daemon() failed or unsupported"); restore_signal_state (); if (options->log) set_std_files_to_null (true); -#if defined(ENABLE_PKCS11) - pkcs11_forkFixup (); -#endif - ret = true; } return ret; @@ -1481,6 +1486,9 @@ do_open_tun (struct context *c) msg (M_INFO, "Preserving previous TUN/TAP instance: %s", c->c1.tuntap->actual_name); + /* explicitly set the ifconfig_* env vars */ + do_ifconfig_setenv(c->c1.tuntap, c->c2.es); + /* run the up script if user specified --up-restart */ if (c->options.up_restart) run_up_down (c->options.up_script, @@ -1709,7 +1717,8 @@ pull_permission_mask (const struct context *c) | OPT_P_MESSAGES | OPT_P_EXPLICIT_NOTIFY | OPT_P_ECHO - | OPT_P_PULL_MODE; + | OPT_P_PULL_MODE + | OPT_P_PEER_ID; if (!c->options.route_nopull) flags |= (OPT_P_ROUTE | OPT_P_IPWIN32); @@ -1788,21 +1797,39 @@ do_deferred_options (struct context *c, const unsigned int found) msg (D_PUSH, "OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified"); if (found & OPT_P_SETENV) msg (D_PUSH, "OPTIONS IMPORT: environment modified"); + +#ifdef ENABLE_SSL + if (found & OPT_P_PEER_ID) + { + msg (D_PUSH, "OPTIONS IMPORT: peer-id set"); + c->c2.tls_multi->use_peer_id = true; + c->c2.tls_multi->peer_id = c->options.peer_id; + frame_add_to_extra_frame(&c->c2.frame, +3); /* peer-id overhead */ + if ( !c->options.ce.link_mtu_defined ) + { + frame_add_to_link_mtu(&c->c2.frame, +3); + msg (D_PUSH, "OPTIONS IMPORT: adjusting link_mtu to %d", + EXPANDED_SIZE(&c->c2.frame)); + } + else + { + msg (M_WARN, "OPTIONS IMPORT: WARNING: peer-id set, but link-mtu" + " fixed by config - reducing tun-mtu to %d, expect" + " MTU problems", TUN_MTU_SIZE(&c->c2.frame) ); + } + } +#endif } /* * Possible hold on initialization */ static bool -do_hold (struct context *c) +do_hold (void) { #ifdef ENABLE_MANAGEMENT if (management) { - /* if c is defined, daemonize before hold */ - if (c && c->options.daemon && management_should_daemonize (management)) - do_init_first_time (c); - /* block until management hold is released */ if (management_hold (management)) return true; @@ -1868,7 +1895,7 @@ socket_restart_pause (struct context *c) c->persist.restart_sleep_seconds = 0; /* do managment hold on context restart, i.e. second, third, fourth, etc. initialization */ - if (do_hold (NULL)) + if (do_hold ()) sec = 0; if (sec) @@ -1887,7 +1914,7 @@ do_startup_pause (struct context *c) if (!c->first_time) socket_restart_pause (c); else - do_hold (NULL); /* do management hold on first context initialization */ + do_hold (); /* do management hold on first context initialization */ } /* @@ -2159,7 +2186,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) options->use_iv); /* In short form, unique datagram identifier is 32 bits, in long form 64 bits */ - packet_id_long_form = cfb_ofb_mode (&c->c1.ks.key_type); + packet_id_long_form = cipher_kt_mode_ofb_cfb (c->c1.ks.key_type.cipher); /* Compute MTU parameters */ crypto_adjust_frame_parameters (&c->c2.frame, @@ -2242,6 +2269,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) to.tmp_dir = options->tmp_dir; if (options->ccd_exclusive) to.client_config_dir_exclusive = options->client_config_dir; + to.auth_user_pass_file = options->auth_user_pass_file; #endif #ifdef ENABLE_X509_TRACK @@ -2388,6 +2416,17 @@ do_init_frame (struct context *c) */ frame_finalize_options (c, NULL); + /* packets with peer-id (P_DATA_V2) need 3 extra bytes in frame (on client) + * and need link_mtu+3 bytes on socket reception (on server). + * + * accomodate receive path in f->extra_link + * send path in f->extra_buffer (+leave room for alignment) + * + * f->extra_frame is adjusted when peer-id option is push-received + */ + frame_add_to_extra_link(&c->c2.frame, 3); + frame_add_to_extra_buffer(&c->c2.frame, 8); + #ifdef ENABLE_FRAGMENT /* * Set frame parameter for fragment code. This is necessary because @@ -2724,7 +2763,7 @@ do_compute_occ_strings (struct context *c) static void do_init_first_time (struct context *c) { - if (c->first_time && !c->did_we_daemonize && !c->c0) + if (c->first_time && !c->c0) { struct context_0 *c0; @@ -2739,12 +2778,9 @@ do_init_first_time (struct context *c) /* get --writepid file descriptor */ get_pid_file (c->options.writepid, &c0->pid_state); - /* become a daemon if --daemon */ - c->did_we_daemonize = possibly_become_daemon (&c->options, c->first_time); - - /* should we disable paging? */ - if (c->options.mlock && c->did_we_daemonize) - platform_mlockall (true); /* call again in case we daemonized */ + /* perform postponed chdir if --daemon */ + if (c->did_we_daemonize && c->options.cd_dir == NULL) + platform_chdir("/"); /* save process ID in a file */ write_pid (&c0->pid_state); @@ -3185,7 +3221,7 @@ open_management (struct context *c) } /* initial management hold, called early, before first context initialization */ - do_hold (c); + do_hold (); if (IS_SIG (c)) { msg (M_WARN, "Signal received from management interface, exiting"); diff --git a/src/openvpn/init.h b/src/openvpn/init.h index 5a1d1dc..d1908ed 100644 --- a/src/openvpn/init.h +++ b/src/openvpn/init.h @@ -55,6 +55,8 @@ bool do_genkey (const struct options *options); bool do_persist_tuntap (const struct options *options); +bool possibly_become_daemon (const struct options *options); + void pre_setup (const struct options *options); void init_instance_handle_signals (struct context *c, const struct env_set *env, const unsigned int flags); diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index 56a01a6..8408438 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -376,8 +376,11 @@ openvpn_popen (const struct argv *a, const struct env_set *es) } else /* parent side */ { - ret=pipe_stdout[0]; - close (pipe_stdout[1]); + int status = 0; + + waitpid(pid, &status, 0); + ret = pipe_stdout[0]; + close (pipe_stdout[1]); } } else { @@ -869,6 +872,12 @@ test_file (const char *filename) fclose (fp); ret = true; } + else + { + if( openvpn_errno () == EACCES ) { + msg( M_WARN | M_ERRNO, "Could not access file '%s'", filename); + } + } } dmsg (D_TEST_FILE, "TEST FILE '%s' [%d]", diff --git a/src/openvpn/mtu.h b/src/openvpn/mtu.h index 29ec21f..bccd681 100644 --- a/src/openvpn/mtu.h +++ b/src/openvpn/mtu.h @@ -258,6 +258,12 @@ frame_headroom (const struct frame *f, const unsigned int flag_mask) */ static inline void +frame_add_to_link_mtu (struct frame *frame, const int increment) +{ + frame->link_mtu += increment; +} + +static inline void frame_add_to_extra_frame (struct frame *frame, const int increment) { frame->extra_frame += increment; diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index ab3f10c..374950e 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -1452,10 +1452,6 @@ multi_client_connect_post (struct multi_context *m, option_types_found, mi->context.c2.es); - if (!platform_unlink (dc_file)) - msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", - dc_file); - /* * If the --client-connect script generates a config file * with an --ifconfig-push directive, it will override any @@ -1698,6 +1694,11 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi multi_client_connect_post (m, mi, dc_file, option_permissions_mask, &option_types_found); ++cc_succeeded_count; } + + if (!platform_unlink (dc_file)) + msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", + dc_file); + script_depr_failed: argv_reset (&argv); } @@ -1751,6 +1752,11 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi } else cc_succeeded = false; + + if (!platform_unlink (dc_file)) + msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", + dc_file); + script_failed: argv_reset (&argv); } @@ -2153,8 +2159,17 @@ multi_process_incoming_link (struct multi_context *m, struct multi_instance *ins /* make sure that source address is associated with this client */ else if (multi_get_instance_by_virtual_addr (m, &src, true) != m->pending) { - msg (D_MULTI_DROPPED, "MULTI: bad source address from client [%s], packet dropped", - mroute_addr_print (&src, &gc)); + /* IPv6 link-local address (fe80::xxx)? */ + if ( (src.type & MR_ADDR_MASK) == MR_ADDR_IPV6 && + src.addr[0] == 0xfe && src.addr[1] == 0x80 ) + { + /* do nothing, for now. TODO: add address learning */ + } + else + { + msg (D_MULTI_DROPPED, "MULTI: bad source address from client [%s], packet dropped", + mroute_addr_print (&src, &gc)); + } c->c2.to_tun.len = 0; } /* client-to-client communication enabled? */ diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c index fd87fc1..2f327f3 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -229,6 +229,10 @@ openvpn_main (int argc, char *argv[]) if (do_test_crypto (&c.options)) break; + /* become a daemon if --daemon */ + if (c.first_time) + c.did_we_daemonize = possibly_become_daemon (&c.options); + #ifdef ENABLE_MANAGEMENT /* open management subsystem */ if (!open_management (&c)) diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 1c0edbc..ff4b07b 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -572,13 +572,14 @@ static const char usage_message[] = "--tls-version-min <version> ['or-highest'] : sets the minimum TLS version we\n" " will accept from the peer. If version is unrecognized and 'or-highest'\n" " is specified, require max TLS version supported by SSL implementation.\n" + "--tls-version-max <version> : sets the maximum TLS version we will use.\n" #ifndef ENABLE_CRYPTO_POLARSSL "--pkcs12 file : PKCS#12 file containing local private key, local certificate\n" " and optionally the root CA certificate.\n" #endif #ifdef ENABLE_X509ALTUSERNAME - "--x509-username-field : Field used in x509 certificate to be username.\n" - " Default is CN.\n" + "--x509-username-field : Field in x509 certificate containing the username.\n" + " Default is CN in the Subject field.\n" #endif "--verify-hash : Specify SHA1 fingerprint for level-1 cert.\n" #ifdef WIN32 @@ -739,7 +740,11 @@ static const char usage_message[] = #ifdef ENABLE_PKCS11 "\n" "PKCS#11 standalone options:\n" - "--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n" +#ifdef DEFAULT_PKCS11_MODULE + "--show-pkcs11-ids [provider] [cert_private] : Show PKCS#11 available ids.\n" +#else + "--show-pkcs11-ids provider [cert_private] : Show PKCS#11 available ids.\n" +#endif " --verb option can be added *BEFORE* this.\n" #endif /* ENABLE_PKCS11 */ "\n" @@ -1266,7 +1271,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 ) < 0 ) + if ( !get_ipv6_addr (prefix_str, &ir->network, &ir->netbits, NULL, msglevel )) { msg (msglevel, "in --iroute-ipv6 %s: Bad IPv6 prefix specification", prefix_str); @@ -2125,7 +2130,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne if (options->ssl_flags & SSLF_OPT_VERIFY) msg (M_USAGE, "--opt-verify requires --mode server"); if (options->server_flags & SF_TCP_NODELAY_HELPER) - msg (M_USAGE, "--tcp-nodelay requires --mode server"); + msg (M_WARN, "WARNING: setting tcp-nodelay on the client side will not " + "affect the server. To have TCP_NODELAY in both direction use " + "tcp-nodelay in the server configuration instead."); if (options->auth_user_pass_verify_script) msg (M_USAGE, "--auth-user-pass-verify requires --mode server"); #if PORT_SHARE @@ -2330,6 +2337,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne MUST_BE_UNDEF (pkcs11_id); MUST_BE_UNDEF (pkcs11_id_management); #endif +#if P2MP + MUST_BE_UNDEF (server_poll_timeout); +#endif if (pull) msg (M_USAGE, err, "--pull"); @@ -2393,7 +2403,7 @@ options_postprocess_mutate_ce (struct options *o, struct connection_entry *ce) { #ifdef ENABLE_FRAGMENT if (ce->fragment) - o->ce.mssfix = ce->fragment; + ce->mssfix = ce->fragment; #else msg (M_USAGE, "--mssfix must specify a parameter"); #endif @@ -2463,6 +2473,15 @@ options_postprocess_mutate_invariant (struct options *options) #endif } #endif + +#ifdef DEFAULT_PKCS11_MODULE + /* If p11-kit is present on the system then load its p11-kit-proxy.so + by default if the user asks for PKCS#11 without otherwise specifying + the module to use. */ + if (!options->pkcs11_providers[0] && + (options->pkcs11_id || options->pkcs11_id_management)) + options->pkcs11_providers[0] = DEFAULT_PKCS11_MODULE; +#endif } static void @@ -2537,6 +2556,24 @@ options_postprocess_mutate (struct options *o) else options_postprocess_mutate_ce (o, &o->ce); +#ifdef ENABLE_CRYPTOAPI + if (o->cryptoapi_cert) + { + const int tls_version_max = + (o->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & + SSLF_TLS_VERSION_MAX_MASK; + + if (tls_version_max == TLS_VER_UNSPEC || tls_version_max > TLS_VER_1_1) + { + msg(M_WARN, "Warning: cryptapicert used, setting maximum TLS " + "version to 1.1."); + o->ssl_flags &= ~(SSLF_TLS_VERSION_MAX_MASK << + SSLF_TLS_VERSION_MAX_SHIFT); + o->ssl_flags |= (TLS_VER_1_1 << SSLF_TLS_VERSION_MAX_SHIFT); + } + } +#endif /* ENABLE_CRYPTOAPI */ + #if P2MP /* * Save certain parms before modifying options via --pull @@ -3439,18 +3476,21 @@ usage_small (void) void show_library_versions(const unsigned int flags) { - msg (flags, "library versions: %s%s%s", #ifdef ENABLE_SSL - get_ssl_library_version(), +#define SSL_LIB_VER_STR get_ssl_library_version() #else - "", +#define SSL_LIB_VER_STR "" #endif #ifdef ENABLE_LZO - ", LZO ", lzo_version_string() +#define LZO_LIB_VER_STR ", LZO ", lzo_version_string() #else - "", "" +#define LZO_LIB_VER_STR "", "" #endif - ); + + msg (flags, "library versions: %s%s%s", SSL_LIB_VER_STR, LZO_LIB_VER_STR); + +#undef SSL_LIB_VER_STR +#undef LZO_LIB_VER_STR } static void @@ -3715,12 +3755,21 @@ static char * read_inline_file (struct in_src *is, const char *close_tag, struct gc_arena *gc) { char line[OPTION_LINE_SIZE]; - struct buffer buf = alloc_buf (10000); + struct buffer buf = alloc_buf (8*OPTION_LINE_SIZE); char *ret; while (in_src_get (is, line, sizeof (line))) { if (!strncmp (line, close_tag, strlen (close_tag))) break; + if (!buf_safe (&buf, strlen(line))) + { + /* Increase buffer size */ + struct buffer buf2 = alloc_buf (buf.capacity * 2); + ASSERT (buf_copy (&buf2, &buf)); + buf_clear (&buf); + free_buf (&buf); + buf = buf2; + } buf_printf (&buf, "%s", line); } ret = string_alloc (BSTR (&buf), gc); @@ -6567,14 +6616,29 @@ add_option (struct options *options, { int ver; VERIFY_PERMISSION (OPT_P_GENERAL); - ver = tls_version_min_parse(p[1], p[2]); + ver = tls_version_parse(p[1], p[2]); if (ver == TLS_VER_BAD) { msg (msglevel, "unknown tls-version-min parameter: %s", p[1]); goto err; } - options->ssl_flags &= ~(SSLF_TLS_VERSION_MASK << SSLF_TLS_VERSION_SHIFT); - options->ssl_flags |= (ver << SSLF_TLS_VERSION_SHIFT); + options->ssl_flags &= + ~(SSLF_TLS_VERSION_MIN_MASK << SSLF_TLS_VERSION_MIN_SHIFT); + options->ssl_flags |= (ver << SSLF_TLS_VERSION_MIN_SHIFT); + } + else if (streq (p[0], "tls-version-max") && p[1]) + { + int ver; + VERIFY_PERMISSION (OPT_P_GENERAL); + ver = tls_version_parse(p[1], NULL); + if (ver == TLS_VER_BAD) + { + msg (msglevel, "unknown tls-version-max parameter: %s", p[1]); + goto err; + } + options->ssl_flags &= + ~(SSLF_TLS_VERSION_MAX_MASK << SSLF_TLS_VERSION_MAX_SHIFT); + options->ssl_flags |= (ver << SSLF_TLS_VERSION_MAX_SHIFT); } #ifndef ENABLE_CRYPTO_POLARSSL else if (streq (p[0], "pkcs12") && p[1]) @@ -6872,21 +6936,62 @@ add_option (struct options *options, #ifdef ENABLE_X509ALTUSERNAME else if (streq (p[0], "x509-username-field") && p[1]) { + /* This option used to automatically upcase the fieldname passed as the + * option argument, e.g., "ou" became "OU". Now, this "helpfulness" is + * fine-tuned by only upcasing Subject field attribute names which consist + * of all lower-case characters. Mixed-case attributes such as + * "emailAddress" are left as-is. An option parameter having the "ext:" + * prefix for matching X.509v3 extended fields will also remain unchanged. + */ char *s = p[1]; + VERIFY_PERMISSION (OPT_P_GENERAL); - if( strncmp ("ext:",s,4) != 0 ) - while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */ + if (strncmp("ext:", s, 4) != 0) + { + size_t i = 0; + while (s[i] && !isupper(s[i])) i++; + if (strlen(s) == i) + { + while ((*s = toupper(*s)) != '\0') s++; + msg(M_WARN, "DEPRECATED FEATURE: automatically upcased the " + "--x509-username-field parameter to '%s'; please update your" + "configuration", p[1]); + } + } options->x509_username_field = p[1]; } #endif /* ENABLE_X509ALTUSERNAME */ #endif /* ENABLE_SSL */ #endif /* ENABLE_CRYPTO */ #ifdef ENABLE_PKCS11 - else if (streq (p[0], "show-pkcs11-ids") && p[1]) + else if (streq (p[0], "show-pkcs11-ids")) { char *provider = p[1]; bool cert_private = (p[2] == NULL ? false : ( atoi (p[2]) != 0 )); +#ifdef DEFAULT_PKCS11_MODULE + if (!provider) + provider = DEFAULT_PKCS11_MODULE; + else if (!p[2]) + { + char *endp = NULL; + int i = strtol(provider, &endp, 10); + + if (*endp == 0) + { + /* There was one argument, and it was purely numeric. + Interpret it as the cert_private argument */ + provider = DEFAULT_PKCS11_MODULE; + cert_private = i; + } + } +#else + if (!provider) + { + msg (msglevel, "--show-pkcs11-ids requires a provider parameter"); + goto err; + } +#endif VERIFY_PERMISSION (OPT_P_GENERAL); set_debug_level (options->verbosity, SDL_CONSTRAIN); @@ -6945,7 +7050,6 @@ add_option (struct options *options, options->pkcs11_id_management = true; } #endif -#ifdef ENABLE_FEATURE_TUN_PERSIST else if (streq (p[0], "rmtun")) { VERIFY_PERMISSION (OPT_P_GENERAL); @@ -6958,7 +7062,12 @@ add_option (struct options *options, options->persist_config = true; options->persist_mode = 1; } -#endif + else if (streq (p[0], "peer-id") && p[1]) + { + VERIFY_PERMISSION (OPT_P_PEER_ID); + options->use_peer_id = true; + options->peer_id = atoi(p[1]); + } else { int i; diff --git a/src/openvpn/options.h b/src/openvpn/options.h index 8cbb85a..af9a47f 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -594,6 +594,9 @@ struct options bool show_net_up; int route_method; #endif + + bool use_peer_id; + uint32_t peer_id; }; #define streq(x, y) (!strcmp((x), (y))) @@ -629,6 +632,7 @@ struct options #define OPT_P_SOCKBUF (1<<25) #define OPT_P_SOCKFLAGS (1<<26) #define OPT_P_CONNECTION (1<<27) +#define OPT_P_PEER_ID (1<<28) #define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE)) @@ -683,6 +687,8 @@ void notnull (const char *arg, const char *description); void usage_small (void); +void show_library_versions(const unsigned int flags); + void init_options (struct options *o, const bool init_gc); void uninit_options (struct options *o); diff --git a/src/openvpn/pkcs11.c b/src/openvpn/pkcs11.c index 3a15ef6..a1f13c5 100644 --- a/src/openvpn/pkcs11.c +++ b/src/openvpn/pkcs11.c @@ -336,11 +336,6 @@ pkcs11_terminate () { ); } -void -pkcs11_forkFixup () { - pkcs11h_forkFixup (); -} - bool pkcs11_addProvider ( const char * const provider, diff --git a/src/openvpn/pkcs11.h b/src/openvpn/pkcs11.h index 4261871..b49401c 100644 --- a/src/openvpn/pkcs11.h +++ b/src/openvpn/pkcs11.h @@ -38,9 +38,6 @@ pkcs11_initialize ( void pkcs11_terminate (); -void -pkcs11_forkFixup (); - bool pkcs11_addProvider ( const char * const provider, diff --git a/src/openvpn/route.c b/src/openvpn/route.c index 532edc6..2acfbe8 100644 --- a/src/openvpn/route.c +++ b/src/openvpn/route.c @@ -838,7 +838,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u if ( rl && rl->flags & RG_ENABLE ) { - if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT)) + if (!(rl->spec.flags & RTSA_REMOTE_ENDPOINT) && (rl->flags & RG_REROUTE_GW)) { msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err); } @@ -1318,15 +1318,18 @@ add_route (struct route_ipv4 *r, #if defined(TARGET_LINUX) #ifdef ENABLE_IPROUTE - /* FIXME -- add on-link support for ENABLE_IPROUTE */ - argv_printf (&argv, "%s route add %s/%d via %s", + argv_printf (&argv, "%s route add %s/%d", iproute_path, network, - count_netmask_bits(netmask), - gateway); + count_netmask_bits(netmask)); + if (r->flags & RT_METRIC_DEFINED) argv_printf_cat (&argv, "metric %d", r->metric); + if (is_on_link (is_local_route, flags, rgi)) + argv_printf_cat (&argv, "dev %s", rgi->iface); + else + argv_printf_cat (&argv, "via %s", gateway); #else argv_printf (&argv, "%s add -net %s netmask %s", ROUTE_PATH, @@ -2598,7 +2601,7 @@ get_default_gateway (struct route_gateway_info *rgi) gc_free (&gc); } -#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY) +#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY)||defined(TARGET_SOLARIS) #include <sys/types.h> #include <sys/socket.h> @@ -2626,6 +2629,8 @@ get_default_gateway (struct route_gateway_info *rgi) struct sockaddr *gate = NULL, *sa; struct rt_msghdr *rtm_aux; +#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY) + #define NEXTADDR(w, u) \ if (rtm_addrs & (w)) {\ l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\ @@ -2633,6 +2638,18 @@ get_default_gateway (struct route_gateway_info *rgi) #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) +#else /* TARGET_SOLARIS */ + +#define NEXTADDR(w, u) \ + if (rtm_addrs & (w)) {\ + l = ROUNDUP(sizeof(struct sockaddr_in)); memmove(cp, &(u), l); cp += l;\ + } + +#define ADVANCE(x, n) (x += ROUNDUP(sizeof(struct sockaddr_in))) + +#endif + + #define rtm m_rtmsg.m_rtm CLEAR(*rgi); @@ -2652,9 +2669,12 @@ get_default_gateway (struct route_gateway_info *rgi) rtm.rtm_addrs = rtm_addrs; so_dst.sa_family = AF_INET; - so_dst.sa_len = sizeof(struct sockaddr_in); so_mask.sa_family = AF_INET; + +#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY) + so_dst.sa_len = sizeof(struct sockaddr_in); so_mask.sa_len = sizeof(struct sockaddr_in); +#endif NEXTADDR(RTA_DST, so_dst); NEXTADDR(RTA_NETMASK, so_mask); diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index 23566f1..0424c0b 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -137,10 +137,6 @@ openvpn_getaddrinfo (unsigned int flags, ASSERT(res); -#if defined(HAVE_RES_INIT) - res_init (); -#endif - if (!hostname) hostname = "::"; @@ -197,6 +193,9 @@ openvpn_getaddrinfo (unsigned int flags, */ while (true) { +#ifndef WIN32 + res_init (); +#endif /* try hostname lookup */ hints.ai_flags = 0; dmsg (D_SOCKET_DEBUG, "GETADDRINFO flags=0x%04x ai_family=%d ai_socktype=%d", @@ -215,10 +214,13 @@ openvpn_getaddrinfo (unsigned int flags, } else { + /* turn success into failure (interrupted syscall) */ if (0 == status) { ASSERT(res); freeaddrinfo(*res); - res = NULL; + *res = NULL; + status = EAI_AGAIN; /* = temporary failure */ + errno = EINTR; } goto done; } @@ -1150,7 +1152,6 @@ resolve_bind_local (struct link_socket *sock) case AF_INET6: { int status; - int err; CLEAR(sock->info.lsa->local.addr.in6); if (sock->local_host) { @@ -1173,7 +1174,7 @@ resolve_bind_local (struct link_socket *sock) { msg (M_FATAL, "getaddr6() failed for local \"%s\": %s", sock->local_host, - gai_strerror(err)); + gai_strerror(status)); } sock->info.lsa->local.addr.in6.sin6_port = htons (sock->local_port); } @@ -1227,6 +1228,7 @@ resolve_remote (struct link_socket *sock, unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); int retry = 0; int status = -1; + struct addrinfo* ai; if (sock->connection_profiles_defined && sock->resolve_retry_seconds == RESOLV_RETRY_INFINITE) { @@ -1263,7 +1265,6 @@ resolve_remote (struct link_socket *sock, ASSERT (0); } - struct addrinfo* ai; /* Temporary fix, this need to be changed for dual stack */ status = openvpn_getaddrinfo(flags, sock->remote_host, retry, signal_received, af, &ai); diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h index 4e7e7f8..793cd9f 100644 --- a/src/openvpn/socket.h +++ b/src/openvpn/socket.h @@ -1023,7 +1023,7 @@ static inline void link_socket_set_tos (struct link_socket *ls) { if (ls && ls->ptos_defined) - setsockopt (ls->sd, IPPROTO_IP, IP_TOS, &ls->ptos, sizeof (ls->ptos)); + setsockopt (ls->sd, IPPROTO_IP, IP_TOS, (const void *)&ls->ptos, sizeof (ls->ptos)); } #endif diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index ac6818e..a17c738 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -271,7 +271,7 @@ tls_get_cipher_name_pair (const char * cipher_name, size_t len) { * Max number of bytes we will add * for data structures common to both * data and control channel packets. - * (opcode only). + * (opcode only). */ void tls_adjust_frame_parameters(struct frame *frame) @@ -458,7 +458,7 @@ ssl_put_auth_challenge (const char *cr_str) * return tls_version_max(). */ int -tls_version_min_parse(const char *vstr, const char *extra) +tls_version_parse(const char *vstr, const char *extra) { const int max_version = tls_version_max(); if (!strcmp(vstr, "1.0") && TLS_VER_1_0 <= max_version) @@ -627,6 +627,8 @@ packet_opcode_name (int op) return "P_ACK_V1"; case P_DATA_V1: return "P_DATA_V1"; + case P_DATA_V2: + return "P_DATA_V2"; default: return "P_???"; } @@ -1053,6 +1055,9 @@ tls_multi_init (struct tls_options *tls_options) ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK]; ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK]; + /* By default not use P_DATA_V2 */ + ret->use_peer_id = false; + return ret; } @@ -1828,6 +1833,8 @@ push_peer_info(struct buffer *buf, struct tls_session *session) #ifdef ENABLE_LZO_STUB buf_printf (&out, "IV_LZO_STUB=1\n"); #endif + /* support for P_DATA_V2 */ + buf_printf(&out, "IV_PROTO=2\n"); if (session->opt->push_peer_info_detail >= 2) { @@ -1898,9 +1905,9 @@ key_method_2_write (struct buffer *buf, struct tls_session *session) if (auth_user_pass_enabled) { #ifdef ENABLE_CLIENT_CR - auth_user_pass_setup (NULL, session->opt->sci); + auth_user_pass_setup (session->opt->auth_user_pass_file, session->opt->sci); #else - auth_user_pass_setup (NULL, NULL); + auth_user_pass_setup (session->opt->auth_user_pass_file, NULL); #endif if (!write_string (buf, auth_user_pass.username, -1)) goto error; @@ -2028,7 +2035,11 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi ASSERT (session->opt->key_method == 2); /* discard leading uint32 */ - ASSERT (buf_advance (buf, 4)); + if (!buf_advance (buf, 4)) { + msg (D_TLS_ERRORS, "TLS ERROR: Plaintext buffer too short (%d bytes).", + buf->len); + goto error; + } /* get key method */ key_method_flags = buf_read_u8 (buf); @@ -2777,8 +2788,9 @@ tls_pre_decrypt (struct tls_multi *multi, key_id = c & P_KEY_ID_MASK; } - if (op == P_DATA_V1) - { /* data channel packet */ + if ((op == P_DATA_V1) || (op == P_DATA_V2)) + { + /* data channel packet */ for (i = 0; i < KEY_SCAN_SIZE; ++i) { struct key_state *ks = multi->key_scan[i]; @@ -2810,7 +2822,19 @@ tls_pre_decrypt (struct tls_multi *multi, opt->pid_persist = NULL; opt->flags &= multi->opt.crypto_flags_and; opt->flags |= multi->opt.crypto_flags_or; + ASSERT (buf_advance (buf, 1)); + if (op == P_DATA_V2) + { + if (buf->len < 4) + { + msg (D_TLS_ERRORS, "Protocol error: received P_DATA_V2 from %s but length is < 4", + print_link_socket_actual (from, &gc)); + goto error; + } + ASSERT (buf_advance (buf, 3)); + } + ++ks->n_packets; ks->n_bytes += buf->len; dmsg (D_TLS_KEYSELECT, @@ -3375,14 +3399,24 @@ tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) { struct key_state *ks; uint8_t *op; + uint32_t peer; ks = multi->save_ks; multi->save_ks = NULL; if (buf->len > 0) { ASSERT (ks); - ASSERT (op = buf_prepend (buf, 1)); - *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id; + + if (!multi->opt.server && multi->use_peer_id) + { + peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->peer_id & 0xFFFFFF)); + ASSERT (buf_write_prepend (buf, &peer, 4)); + } + else + { + ASSERT (op = buf_prepend (buf, 1)); + *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id; + } ++ks->n_packets; ks->n_bytes += buf->len; } @@ -3489,7 +3523,7 @@ protocol_dump (struct buffer *buffer, unsigned int flags, struct gc_arena *gc) key_id = c & P_KEY_ID_MASK; buf_printf (&out, "%s kid=%d", packet_opcode_name (op), key_id); - if (op == P_DATA_V1) + if ((op == P_DATA_V1) || (op == P_DATA_V2)) goto print_data; /* diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index cd7cae2..6a14768 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -61,6 +61,7 @@ #define P_CONTROL_V1 4 /* control channel packet (usually TLS ciphertext) */ #define P_ACK_V1 5 /* acknowledgement for packets received */ #define P_DATA_V1 6 /* data channel packet */ +#define P_DATA_V2 9 /* data channel packet with peer-id */ /* indicates key_method >= 2 */ #define P_CONTROL_HARD_RESET_CLIENT_V2 7 /* initial key from client, forget previous state */ @@ -68,7 +69,7 @@ /* define the range of legal opcodes */ #define P_FIRST_OPCODE 1 -#define P_LAST_OPCODE 8 +#define P_LAST_OPCODE 9 /* Should we aggregate TLS * acknowledgements, and tack them onto diff --git a/src/openvpn/ssl_backend.h b/src/openvpn/ssl_backend.h index b37b1e5..6d47bd0 100644 --- a/src/openvpn/ssl_backend.h +++ b/src/openvpn/ssl_backend.h @@ -114,7 +114,7 @@ void tls_clear_error(); #define TLS_VER_1_0 1 #define TLS_VER_1_1 2 #define TLS_VER_1_2 3 -int tls_version_min_parse(const char *vstr, const char *extra); +int tls_version_parse(const char *vstr, const char *extra); /** * Return the maximum TLS version (as a TLS_VER_x constant) @@ -472,6 +472,6 @@ void get_highest_preference_tls_cipher (char *buf, int size); * return a pointer to a static memory area containing the * name and version number of the SSL library in use */ -char * get_ssl_library_version(void); +const char * get_ssl_library_version(void); #endif /* SSL_BACKEND_H_ */ diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 66b6492..449172d 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -277,6 +277,7 @@ struct tls_options const char *auth_user_pass_verify_script; bool auth_user_pass_verify_script_via_file; const char *tmp_dir; + const char *auth_user_pass_file; /* use the client-config-dir as a positive authenticator */ const char *client_config_dir_exclusive; @@ -291,8 +292,10 @@ struct tls_options # define SSLF_AUTH_USER_PASS_OPTIONAL (1<<2) # define SSLF_OPT_VERIFY (1<<4) # define SSLF_CRL_VERIFY_DIR (1<<5) -# define SSLF_TLS_VERSION_SHIFT 6 -# define SSLF_TLS_VERSION_MASK 0xF /* (uses bit positions 6 to 9) */ +# define SSLF_TLS_VERSION_MIN_SHIFT 6 +# define SSLF_TLS_VERSION_MIN_MASK 0xF /* (uses bit positions 6 to 9) */ +# define SSLF_TLS_VERSION_MAX_SHIFT 10 +# define SSLF_TLS_VERSION_MAX_MASK 0xF /* (uses bit positions 10 to 13) */ unsigned int ssl_flags; #ifdef MANAGEMENT_DEF_AUTH @@ -488,6 +491,10 @@ struct tls_multi time_t tas_last; #endif + /* For P_DATA_V2 */ + uint32_t peer_id; + bool use_peer_id; + /* * Our session objects. */ @@ -498,4 +505,9 @@ struct tls_multi }; +#define SHOW_TLS_CIPHER_LIST_WARNING \ + "Be aware that that whether a cipher suite in this list can actually work\n" \ + "depends on the specific setup of both peers. See the man page entries of\n" \ + "--tls-cipher and --show-tls for more details.\n\n" + #endif /* SSL_COMMON_H_ */ diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index 481600a..be33caa 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -121,14 +121,15 @@ tmp_rsa_cb (SSL * s, int is_export, int keylength) void tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) { - const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; + const int tls_version_max = + (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK; ASSERT(NULL != ctx); - if (tls_version_min > TLS_VER_UNSPEC) - ctx->ctx = SSL_CTX_new (SSLv23_server_method ()); - else + if (tls_version_max == TLS_VER_1_0) ctx->ctx = SSL_CTX_new (TLSv1_server_method ()); + else + ctx->ctx = SSL_CTX_new (SSLv23_server_method ()); if (ctx->ctx == NULL) msg (M_SSLERR, "SSL_CTX_new SSLv23_server_method"); @@ -139,14 +140,15 @@ tls_ctx_server_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) void tls_ctx_client_new(struct tls_root_ctx *ctx, unsigned int ssl_flags) { - const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; + const int tls_version_max = + (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK; ASSERT(NULL != ctx); - if (tls_version_min > TLS_VER_UNSPEC) - ctx->ctx = SSL_CTX_new (SSLv23_client_method ()); - else + if (tls_version_max == TLS_VER_1_0) ctx->ctx = SSL_CTX_new (TLSv1_client_method ()); + else + ctx->ctx = SSL_CTX_new (SSLv23_client_method ()); if (ctx->ctx == NULL) msg (M_SSLERR, "SSL_CTX_new SSLv23_client_method"); @@ -218,17 +220,28 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags) /* process SSL options including minimum TLS version we will accept from peer */ { long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - const int tls_version_min = (ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; - if (tls_version_min > TLS_VER_1_0) + const int tls_ver_min = + (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK; + int tls_ver_max = + (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK; + + if (tls_ver_max <= TLS_VER_UNSPEC) + tls_ver_max = tls_version_max(); + + if (tls_ver_min > TLS_VER_1_0 || tls_ver_max < TLS_VER_1_0) sslopt |= SSL_OP_NO_TLSv1; #ifdef SSL_OP_NO_TLSv1_1 - if (tls_version_min > TLS_VER_1_1) + if (tls_ver_min > TLS_VER_1_1 || tls_ver_max < TLS_VER_1_1) sslopt |= SSL_OP_NO_TLSv1_1; #endif #ifdef SSL_OP_NO_TLSv1_2 - if (tls_version_min > TLS_VER_1_2) + if (tls_ver_min > TLS_VER_1_2 || tls_ver_max < TLS_VER_1_2) sslopt |= SSL_OP_NO_TLSv1_2; #endif +#ifdef SSL_OP_NO_COMPRESSION + /* Disable compression - flag not available in OpenSSL 0.9.8 */ + sslopt |= SSL_OP_NO_COMPRESSION; +#endif SSL_CTX_set_options (ctx->ctx, sslopt); } @@ -261,8 +274,7 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) const tls_cipher_name_pair *cipher_pair; - const size_t openssl_ciphers_size = 4096; - char openssl_ciphers[openssl_ciphers_size]; + char openssl_ciphers[4096]; size_t openssl_ciphers_len = 0; openssl_ciphers[0] = '\0'; @@ -301,8 +313,8 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) } // Make sure new cipher name fits in cipher string - if (((openssl_ciphers_size-1) - openssl_ciphers_len) < current_cipher_len) { - msg(M_SSLERR, "Failed to set restricted TLS cipher list, too long (>%zu).", openssl_ciphers_size-1); + if (((sizeof(openssl_ciphers)-1) - openssl_ciphers_len) < current_cipher_len) { + msg(M_SSLERR, "Failed to set restricted TLS cipher list, too long (>%d).", (int)sizeof(openssl_ciphers)-1); } // Concatenate cipher name to OpenSSL cipher string @@ -1328,7 +1340,7 @@ show_available_tls_ciphers (const char *cipher_list) } } - printf ("\n"); + printf ("\n" SHOW_TLS_CIPHER_LIST_WARNING); SSL_free (ssl); SSL_CTX_free (tls_ctx.ctx); @@ -1355,7 +1367,7 @@ get_highest_preference_tls_cipher (char *buf, int size) SSL_CTX_free (ctx); } -char * +const char * get_ssl_library_version(void) { return SSLeay_version(SSLEAY_VERSION); diff --git a/src/openvpn/ssl_polarssl.c b/src/openvpn/ssl_polarssl.c index 0dfffd6..30c7395 100644 --- a/src/openvpn/ssl_polarssl.c +++ b/src/openvpn/ssl_polarssl.c @@ -40,6 +40,7 @@ #include "errlevel.h" #include "ssl_backend.h" +#include "base64.h" #include "buffer.h" #include "misc.h" #include "manage.h" @@ -49,7 +50,9 @@ #include <polarssl/havege.h> #include "ssl_verify_polarssl.h" +#include <polarssl/error.h> #include <polarssl/pem.h> +#include <polarssl/version.h> void tls_init_lib() @@ -204,12 +207,13 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) void tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file, - const char *dh_file_inline + const char *dh_inline ) { - if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_file_inline) + if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_inline) { - if (0 != x509parse_dhm(ctx->dhm_ctx, dh_file_inline, strlen(dh_file_inline))) + if (0 != x509parse_dhm(ctx->dhm_ctx, (const unsigned char *) dh_inline, + strlen(dh_inline))) msg (M_FATAL, "Cannot read inline DH parameters"); } else @@ -242,15 +246,15 @@ tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert) void tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, - const char *cert_file_inline + const char *cert_inline ) { ASSERT(NULL != ctx); - if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_file_inline) + if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_inline) { - if (0 != x509parse_crt(ctx->crt_chain, cert_file_inline, - strlen(cert_file_inline))) + if (0 != x509parse_crt(ctx->crt_chain, + (const unsigned char *) cert_inline, strlen(cert_inline))) msg (M_FATAL, "Cannot load inline certificate file"); } else @@ -262,30 +266,30 @@ tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, - const char *priv_key_file_inline + const char *priv_key_inline ) { int status; ASSERT(NULL != ctx); - if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_file_inline) + if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_inline) { status = x509parse_key(ctx->priv_key, - priv_key_file_inline, strlen(priv_key_file_inline), + (const unsigned char *) priv_key_inline, strlen(priv_key_inline), NULL, 0); - if (POLARSSL_ERR_PEM_PASSWORD_REQUIRED == status) + if (POLARSSL_ERR_X509_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); status = x509parse_key(ctx->priv_key, - priv_key_file_inline, strlen(priv_key_file_inline), - passbuf, strlen(passbuf)); + (const unsigned char *) priv_key_inline, strlen(priv_key_inline), + (const unsigned char *) passbuf, strlen(passbuf)); } } else { status = x509parse_keyfile(ctx->priv_key, priv_key_file, NULL); - if (POLARSSL_ERR_PEM_PASSWORD_REQUIRED == status) + if (POLARSSL_ERR_X509_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); @@ -295,7 +299,7 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, if (0 != status) { #ifdef ENABLE_MANAGEMENT - if (management && (POLARSSL_ERR_PEM_PASSWORD_MISMATCH == status)) + if (management && (POLARSSL_ERR_X509_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); @@ -467,16 +471,17 @@ static inline size_t external_key_len(void *vctx) #endif void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, - const char *ca_file_inline, + const char *ca_inline, const char *ca_path, bool tls_server ) { if (ca_path) msg(M_FATAL, "ERROR: PolarSSL cannot handle the capath directive"); - if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_file_inline) + if (ca_file && !strcmp (ca_file, INLINE_FILE_TAG) && ca_inline) { - if (0 != x509parse_crt(ctx->ca_chain, ca_file_inline, strlen(ca_file_inline))) + if (0 != x509parse_crt(ctx->ca_chain, (const unsigned char *) ca_inline, + strlen(ca_inline))) msg (M_FATAL, "Cannot load inline CA certificates"); } else @@ -489,15 +494,16 @@ void tls_ctx_load_ca (struct tls_root_ctx *ctx, const char *ca_file, void tls_ctx_load_extra_certs (struct tls_root_ctx *ctx, const char *extra_certs_file, - const char *extra_certs_file_inline + const char *extra_certs_inline ) { ASSERT(NULL != ctx); - if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_file_inline) + if (!strcmp (extra_certs_file, INLINE_FILE_TAG) && extra_certs_inline) { - if (0 != x509parse_crt(ctx->crt_chain, extra_certs_file_inline, - strlen(extra_certs_file_inline))) + if (0 != x509parse_crt(ctx->crt_chain, + (const unsigned char *) extra_certs_inline, + strlen(extra_certs_inline))) msg (M_FATAL, "Cannot load inline extra-certs file"); } else @@ -620,7 +626,7 @@ static void my_debug( void *ctx, int level, const char *str ) void tls_ctx_personalise_random(struct tls_root_ctx *ctx) { static char old_sha256_hash[32] = {0}; - char sha256_hash[32] = {0}; + unsigned char sha256_hash[32] = {0}; ctr_drbg_context *cd_ctx = rand_ctx_get(); if (NULL != ctx->crt_chain) @@ -648,6 +654,40 @@ tls_version_max(void) #endif } +/** + * Convert an OpenVPN tls-version variable to PolarSSl format (i.e. a major and + * minor ssl version number). + * + * @param tls_ver The tls-version variable to convert. + * @param major Returns the TLS major version in polarssl format. + * Must be a valid pointer. + * @param minor Returns the TLS minor version in polarssl format. + * Must be a valid pointer. + */ +static void tls_version_to_major_minor(int tls_ver, int *major, int *minor) { + ASSERT(major); + ASSERT(minor); + + switch (tls_ver) + { + case TLS_VER_1_0: + *major = SSL_MAJOR_VERSION_3; + *minor = SSL_MINOR_VERSION_1; + break; + case TLS_VER_1_1: + *major = SSL_MAJOR_VERSION_3; + *minor = SSL_MINOR_VERSION_2; + break; + case TLS_VER_1_2: + *major = SSL_MAJOR_VERSION_3; + *minor = SSL_MINOR_VERSION_3; + break; + default: + msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver); + break; + } +} + void key_state_ssl_init(struct key_state_ssl *ks_ssl, const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session) { @@ -706,30 +746,32 @@ void key_state_ssl_init(struct key_state_ssl *ks_ssl, /* Initialize minimum TLS version */ { - const int tls_version_min = (session->opt->ssl_flags >> SSLF_TLS_VERSION_SHIFT) & SSLF_TLS_VERSION_MASK; - int polar_major; - int polar_minor; - switch (tls_version_min) + const int tls_version_min = + (session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & + SSLF_TLS_VERSION_MIN_MASK; + + /* default to TLS 1.0 */ + int major = SSL_MAJOR_VERSION_3; + int minor = SSL_MINOR_VERSION_1; + + if (tls_version_min > TLS_VER_UNSPEC) + tls_version_to_major_minor(tls_version_min, &major, &minor); + + ssl_set_min_version(ks_ssl->ctx, major, minor); + } + + /* Initialize maximum TLS version */ + { + const int tls_version_max = + (session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & + SSLF_TLS_VERSION_MAX_MASK; + + if (tls_version_max > TLS_VER_UNSPEC) { - case TLS_VER_1_0: - default: - polar_major = SSL_MAJOR_VERSION_3; - polar_minor = SSL_MINOR_VERSION_1; - break; -#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_2) - case TLS_VER_1_1: - polar_major = SSL_MAJOR_VERSION_3; - polar_minor = SSL_MINOR_VERSION_2; - break; -#endif -#if defined(SSL_MAJOR_VERSION_3) && defined(SSL_MINOR_VERSION_3) - case TLS_VER_1_2: - polar_major = SSL_MAJOR_VERSION_3; - polar_minor = SSL_MINOR_VERSION_3; - break; -#endif + int major, minor; + tls_version_to_major_minor(tls_version_max, &major, &minor); + ssl_set_max_version(ks_ssl->ctx, major, minor); } - ssl_set_min_version(ks_ssl->ctx, polar_major, polar_minor); } /* Initialise BIOs */ @@ -1053,7 +1095,7 @@ show_available_tls_ciphers (const char *cipher_list) printf ("%s\n", ssl_get_ciphersuite_name(*ciphers)); ciphers++; } - printf ("\n"); + printf ("\n" SHOW_TLS_CIPHER_LIST_WARNING); } void @@ -1068,7 +1110,7 @@ get_highest_preference_tls_cipher (char *buf, int size) strncpynt (buf, cipher_name, size); } -char * +const char * get_ssl_library_version(void) { static char polar_version[30]; diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index c90c2c3..9693b81 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -596,7 +596,7 @@ verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_dep { result_t ret = FAILURE; char *subject = NULL; - char common_name[TLS_USERNAME_LEN] = {0}; + char common_name[TLS_USERNAME_LEN+1] = {0}; /* null-terminated */ const struct tls_options *opt; struct gc_arena gc = gc_new(); @@ -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, TLS_USERNAME_LEN, + if (SUCCESS != x509_get_username (common_name, sizeof(common_name), opt->x509_username_field, cert)) { if (!cert_depth) @@ -1165,7 +1165,7 @@ verify_user_pass(struct user_pass *up, struct tls_multi *multi, s2 = verify_user_pass_script (session, up); /* check sizing of username if it will become our common name */ - if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) >= TLS_USERNAME_LEN) + if ((session->opt->ssl_flags & SSLF_USERNAME_AS_COMMON_NAME) && strlen (up->username) > TLS_USERNAME_LEN) { msg (D_TLS_ERRORS, "TLS Auth Error: --username-as-common name specified and username is longer than the maximum permitted Common Name length of %d characters", TLS_USERNAME_LEN); s1 = OPENVPN_PLUGIN_FUNC_ERROR; diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c index 19982ae..e1118d6 100644 --- a/src/openvpn/ssl_verify_openssl.c +++ b/src/openvpn/ssl_verify_openssl.c @@ -97,9 +97,7 @@ static bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size) { bool retval = false; - X509_EXTENSION *pExt; char *buf = 0; - int length = 0; GENERAL_NAMES *extensions; int nid = OBJ_txt2nid(fieldname); @@ -591,12 +589,12 @@ x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject) in = BIO_new_file (crl_file, "r"); if (in == NULL) { - msg (M_ERR, "CRL: cannot read: %s", crl_file); + msg (M_WARN, "CRL: cannot read: %s", crl_file); goto end; } crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL); if (crl == NULL) { - msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file); + msg (M_WARN, "CRL: cannot read CRL from file %s", crl_file); goto end; } diff --git a/src/openvpn/ssl_verify_polarssl.c b/src/openvpn/ssl_verify_polarssl.c index 3fd861c..f8f9ab5 100644 --- a/src/openvpn/ssl_verify_polarssl.c +++ b/src/openvpn/ssl_verify_polarssl.c @@ -380,7 +380,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 < x509_oid_get_numeric_string( oid_num_str, sizeof (oid_num_str), oid)) { msg (D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", @@ -414,9 +414,12 @@ x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) result_t retval = FAILURE; x509_crl crl = {0}; - if (x509parse_crlfile(&crl, crl_file) != 0) + int polar_retval = x509parse_crlfile(&crl, crl_file); + if (polar_retval != 0) { - msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file); + char errstr[128]; + error_strerror(polar_retval, errstr, sizeof(errstr)); + msg (M_WARN, "CRL: cannot read CRL from file %s (%s)", crl_file, errstr); goto end; } diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h index 7a7d53a..7075b96 100644 --- a/src/openvpn/syshead.h +++ b/src/openvpn/syshead.h @@ -214,10 +214,6 @@ #ifdef TARGET_LINUX -#if defined(HAVE_NETINET_IF_ETHER_H) -#include <netinet/if_ether.h> -#endif - #ifdef HAVE_LINUX_IF_TUN_H #include <linux/if_tun.h> #endif @@ -349,6 +345,14 @@ #endif /* TARGET_DRAGONFLY */ +#ifdef TARGET_DARWIN + +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +#endif /* TARGET_DARWIN */ + #ifdef WIN32 #include <iphlpapi.h> #include <ntddndis.h> diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index ba4b15e..285e774 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -396,6 +396,49 @@ is_tun_p2p (const struct tuntap *tt) } /* + * Set the ifconfig_* environment variables, both for IPv4 and IPv6 + */ +void +do_ifconfig_setenv (const struct tuntap *tt, struct env_set *es) +{ + struct gc_arena gc = gc_new (); + const char *ifconfig_local = print_in_addr_t (tt->local, 0, &gc); + const char *ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc); + + /* + * Set environmental variables with ifconfig parameters. + */ + if (tt->did_ifconfig_setup) + { + bool tun = is_tun_p2p (tt); + + setenv_str (es, "ifconfig_local", ifconfig_local); + if (tun) + { + setenv_str (es, "ifconfig_remote", ifconfig_remote_netmask); + } + else + { + const char *ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc); + setenv_str (es, "ifconfig_netmask", ifconfig_remote_netmask); + setenv_str (es, "ifconfig_broadcast", ifconfig_broadcast); + } + } + + if (tt->did_ifconfig_ipv6_setup) + { + const char *ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc); + const char *ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc); + + setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local); + setenv_int (es, "ifconfig_ipv6_netbits", tt->netbits_ipv6); + setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote); + } + + gc_free (&gc); +} + +/* * Init tun/tap object. * * Set up tuntap structure for ifconfig, @@ -427,9 +470,6 @@ init_tun (const char *dev, /* --dev option */ if (ifconfig_local_parm && ifconfig_remote_netmask_parm) { bool tun = false; - const char *ifconfig_local = NULL; - const char *ifconfig_remote_netmask = NULL; - const char *ifconfig_broadcast = NULL; /* * We only handle TUN/TAP devices here, not --dev null devices. @@ -491,44 +531,19 @@ init_tun (const char *dev, /* --dev option */ } /* - * Set ifconfig parameters - */ - ifconfig_local = print_in_addr_t (tt->local, 0, &gc); - ifconfig_remote_netmask = print_in_addr_t (tt->remote_netmask, 0, &gc); - - /* * If TAP-style interface, generate broadcast address. */ if (!tun) { tt->broadcast = generate_ifconfig_broadcast_addr (tt->local, tt->remote_netmask); - ifconfig_broadcast = print_in_addr_t (tt->broadcast, 0, &gc); } - /* - * Set environmental variables with ifconfig parameters. - */ - if (es) - { - setenv_str (es, "ifconfig_local", ifconfig_local); - if (tun) - { - setenv_str (es, "ifconfig_remote", ifconfig_remote_netmask); - } - else - { - setenv_str (es, "ifconfig_netmask", ifconfig_remote_netmask); - setenv_str (es, "ifconfig_broadcast", ifconfig_broadcast); - } - } tt->did_ifconfig_setup = true; } if (ifconfig_ipv6_local_parm && ifconfig_ipv6_remote_parm) { - const char *ifconfig_ipv6_local = NULL; - const char *ifconfig_ipv6_remote = NULL; /* * Convert arguments to binary IPv6 addresses. @@ -541,24 +556,14 @@ init_tun (const char *dev, /* --dev option */ } tt->netbits_ipv6 = ifconfig_ipv6_netbits_parm; - /* - * Set ifconfig parameters - */ - ifconfig_ipv6_local = print_in6_addr (tt->local_ipv6, 0, &gc); - ifconfig_ipv6_remote = print_in6_addr (tt->remote_ipv6, 0, &gc); - - /* - * Set environmental variables with ifconfig parameters. - */ - if (es) - { - setenv_str (es, "ifconfig_ipv6_local", ifconfig_ipv6_local); - setenv_int (es, "ifconfig_ipv6_netbits", tt->netbits_ipv6); - setenv_str (es, "ifconfig_ipv6_remote", ifconfig_ipv6_remote); - } tt->did_ifconfig_ipv6_setup = true; } + /* + * Set environmental variables with ifconfig parameters. + */ + if (es) do_ifconfig_setenv(tt, es); + gc_free (&gc); return tt; } @@ -618,6 +623,28 @@ void delete_route_connected_v6_net(struct tuntap * tt, } #endif +#if defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY) +/* we can't use true subnet mode on tun on all platforms, as that + * conflicts with IPv6 (wants to use ND then, which we don't do), + * but the OSes want "a remote address that is different from ours" + * - so we construct one, normally the first in the subnet, but if + * this is the same as ours, use the second one. + * The actual address does not matter at all, as the tun interface + * is still point to point and no layer 2 resolution is done... + */ + +char * +create_arbitrary_remote( struct tuntap *tt, struct gc_arena * gc ) +{ + in_addr_t remote; + + remote = (tt->local & tt->remote_netmask) +1; + + if ( remote == tt->local ) remote ++; + + return print_in_addr_t (remote, 0, &gc); +} +#endif /* execute the ifconfig command through the shell */ void @@ -1114,7 +1141,7 @@ do_ifconfig (struct tuntap *tt, IFCONFIG_PATH, actual, ifconfig_local, - ifconfig_local, + create_arbitrary_remote( tt, &gc ), tun_mtu, ifconfig_remote_netmask ); @@ -1710,9 +1737,9 @@ write_tun (struct tuntap* tt, uint8_t *buf, int len) pi.flags = 0; if(iph->version == 6) - pi.proto = htons(ETH_P_IPV6); + pi.proto = htons(OPENVPN_ETH_P_IPV6); else - pi.proto = htons(ETH_P_IP); + pi.proto = htons(OPENVPN_ETH_P_IPV4); vect[0].iov_len = sizeof(pi); vect[0].iov_base = π diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 085d6a3..7089f7c 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -241,6 +241,9 @@ void init_tun_post (struct tuntap *tt, const struct frame *frame, const struct tuntap_options *options); +void do_ifconfig_setenv (const struct tuntap *tt, + struct env_set *es); + void do_ifconfig (struct tuntap *tt, const char *actual, /* actual device name */ int tun_mtu, @@ -374,6 +377,19 @@ tuntap_stop (int status) return false; } +static inline bool +tuntap_abort(int status) +{ + /* + * Typically generated when driver is halted. + */ + if (status < 0) + { + return openvpn_errno() == ERROR_OPERATION_ABORTED; + } + return false; +} + static inline int tun_write_win32 (struct tuntap *tt, struct buffer *buf) { @@ -415,6 +431,12 @@ tuntap_stop (int status) return false; } +static inline bool +tuntap_abort(int status) +{ + return false; +} + static inline void tun_standby_init (struct tuntap *tt) { diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index 13fd881..f35c96b 100644 --- a/src/openvpn/win32.c +++ b/src/openvpn/win32.c @@ -870,6 +870,9 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i WCHAR *cl = wide_cmd_line (a, &gc); WCHAR *cmd = wide_string (a->argv[0], &gc); + /* this allows console programs to run, and is ignored otherwise */ + DWORD proc_flags = CREATE_NO_WINDOW; + CLEAR (start_info); CLEAR (proc_info); @@ -879,9 +882,6 @@ openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned i start_info.dwFlags = STARTF_USESHOWWINDOW; start_info.wShowWindow = SW_HIDE; - /* this allows console programs to run, and is ignored otherwise */ - DWORD proc_flags = CREATE_NO_WINDOW; - if (CreateProcessW (cmd, cl, NULL, NULL, FALSE, proc_flags, env, NULL, &start_info, &proc_info)) { DWORD exit_status = 0; |