summaryrefslogtreecommitdiff
path: root/src/openvpn
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn')
-rw-r--r--src/openvpn/Makefile.am1
-rw-r--r--src/openvpn/Makefile.in15
-rw-r--r--src/openvpn/base64.c2
-rw-r--r--src/openvpn/console.c16
-rw-r--r--src/openvpn/crypto.c69
-rw-r--r--src/openvpn/crypto.h76
-rw-r--r--src/openvpn/crypto_backend.h30
-rw-r--r--src/openvpn/crypto_openssl.c86
-rw-r--r--src/openvpn/crypto_polarssl.c21
-rw-r--r--src/openvpn/forward.c10
-rw-r--r--src/openvpn/helper.c8
-rw-r--r--src/openvpn/init.c98
-rw-r--r--src/openvpn/init.h2
-rw-r--r--src/openvpn/misc.c13
-rw-r--r--src/openvpn/mtu.h6
-rw-r--r--src/openvpn/multi.c27
-rw-r--r--src/openvpn/openvpn.c4
-rw-r--r--src/openvpn/options.c151
-rw-r--r--src/openvpn/options.h6
-rw-r--r--src/openvpn/pkcs11.c5
-rw-r--r--src/openvpn/pkcs11.h3
-rw-r--r--src/openvpn/route.c34
-rw-r--r--src/openvpn/socket.c17
-rw-r--r--src/openvpn/socket.h2
-rw-r--r--src/openvpn/ssl.c54
-rw-r--r--src/openvpn/ssl.h3
-rw-r--r--src/openvpn/ssl_backend.h4
-rw-r--r--src/openvpn/ssl_common.h16
-rw-r--r--src/openvpn/ssl_openssl.c48
-rw-r--r--src/openvpn/ssl_polarssl.c136
-rw-r--r--src/openvpn/ssl_verify.c6
-rw-r--r--src/openvpn/ssl_verify_openssl.c6
-rw-r--r--src/openvpn/ssl_verify_polarssl.c9
-rw-r--r--src/openvpn/syshead.h12
-rw-r--r--src/openvpn/tun.c119
-rw-r--r--src/openvpn/tun.h22
-rw-r--r--src/openvpn/win32.c6
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 = &pi;
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;