diff options
author | Jörg Frings-Fürst <debian@jff.email> | 2020-04-10 23:10:07 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff.email> | 2020-04-10 23:10:07 +0200 |
commit | 4f3065b441a19ac8661a487a1f87c25d7173ac03 (patch) | |
tree | ccf4fa15d6322e1c080d29500261cc7dc0be042a /src/openvpn | |
parent | a351f71e82badcc71a2ce881bbb97eccfcebc06b (diff) | |
parent | 8a3450ef8682b9085637d7b94afc5c7e6f92e64b (diff) |
Update upstream source from tag 'upstream/2.4.8'
Update to upstream version '2.4.8'
with Debian dir 00c9c7e7fdd8b0a1729f9102507c151f67ca8c5d
Diffstat (limited to 'src/openvpn')
-rw-r--r-- | src/openvpn/Makefile.in | 3 | ||||
-rw-r--r-- | src/openvpn/crypto.c | 1 | ||||
-rw-r--r-- | src/openvpn/crypto_backend.h | 9 | ||||
-rw-r--r-- | src/openvpn/crypto_mbedtls.c | 7 | ||||
-rw-r--r-- | src/openvpn/crypto_openssl.c | 8 | ||||
-rw-r--r-- | src/openvpn/cryptoapi.c | 379 | ||||
-rw-r--r-- | src/openvpn/forward.c | 2 | ||||
-rw-r--r-- | src/openvpn/init.c | 2 | ||||
-rw-r--r-- | src/openvpn/init.h | 2 | ||||
-rw-r--r-- | src/openvpn/misc.c | 93 | ||||
-rw-r--r-- | src/openvpn/misc.h | 5 | ||||
-rw-r--r-- | src/openvpn/mtcp.c | 2 | ||||
-rw-r--r-- | src/openvpn/mudp.c | 2 | ||||
-rw-r--r-- | src/openvpn/multi.c | 32 | ||||
-rw-r--r-- | src/openvpn/multi.h | 9 | ||||
-rw-r--r-- | src/openvpn/openssl_compat.h | 12 | ||||
-rw-r--r-- | src/openvpn/openvpn.c | 2 | ||||
-rw-r--r-- | src/openvpn/openvpn_win32_resources.rc | 2 | ||||
-rw-r--r-- | src/openvpn/options.c | 20 | ||||
-rw-r--r-- | src/openvpn/pkcs11.c | 2 | ||||
-rw-r--r-- | src/openvpn/proxy.c | 2 | ||||
-rw-r--r-- | src/openvpn/route.c | 4 | ||||
-rw-r--r-- | src/openvpn/socket.c | 2 | ||||
-rw-r--r-- | src/openvpn/socks.c | 4 | ||||
-rw-r--r-- | src/openvpn/ssl_openssl.c | 22 | ||||
-rw-r--r-- | src/openvpn/tun.c | 10 | ||||
-rw-r--r-- | src/openvpn/tun.h | 2 | ||||
-rw-r--r-- | src/openvpn/win32.c | 15 |
28 files changed, 484 insertions, 171 deletions
diff --git a/src/openvpn/Makefile.in b/src/openvpn/Makefile.in index 6aab503..3db2849 100644 --- a/src/openvpn/Makefile.in +++ b/src/openvpn/Makefile.in @@ -417,9 +417,6 @@ TAP_WIN_MIN_MINOR = @TAP_WIN_MIN_MINOR@ TEST_CFLAGS = @TEST_CFLAGS@ TEST_LDFLAGS = @TEST_LDFLAGS@ TMPFILES_DIR = @TMPFILES_DIR@ -VENDOR_BUILD_ROOT = @VENDOR_BUILD_ROOT@ -VENDOR_DIST_ROOT = @VENDOR_DIST_ROOT@ -VENDOR_SRC_ROOT = @VENDOR_SRC_ROOT@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index 59e5ac5..7e7dead 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -919,7 +919,6 @@ free_key_ctx(struct key_ctx *ctx) { if (ctx->cipher) { - cipher_ctx_cleanup(ctx->cipher); cipher_ctx_free(ctx->cipher); ctx->cipher = NULL; } diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h index 1ee2980..b3db925 100644 --- a/src/openvpn/crypto_backend.h +++ b/src/openvpn/crypto_backend.h @@ -307,7 +307,7 @@ bool cipher_kt_mode_aead(const cipher_kt_t *cipher); cipher_ctx_t *cipher_ctx_new(void); /** - * Free a cipher context + * Cleanup and free a cipher context * * @param ctx Cipher context. */ @@ -327,13 +327,6 @@ void cipher_ctx_init(cipher_ctx_t *ctx, const uint8_t *key, int key_len, const cipher_kt_t *kt, int enc); /** - * Cleanup the specified context. - * - * @param ctx Cipher context to cleanup. - */ -void cipher_ctx_cleanup(cipher_ctx_t *ctx); - -/** * Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is * used. * diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c index 82a92af..748043e 100644 --- a/src/openvpn/crypto_mbedtls.c +++ b/src/openvpn/crypto_mbedtls.c @@ -519,6 +519,7 @@ cipher_ctx_new(void) void cipher_ctx_free(mbedtls_cipher_context_t *ctx) { + mbedtls_cipher_free(ctx); free(ctx); } @@ -544,12 +545,6 @@ cipher_ctx_init(mbedtls_cipher_context_t *ctx, const uint8_t *key, int key_len, ASSERT(ctx->key_bitlen <= key_len*8); } -void -cipher_ctx_cleanup(mbedtls_cipher_context_t *ctx) -{ - mbedtls_cipher_free(ctx); -} - int cipher_ctx_iv_length(const mbedtls_cipher_context_t *ctx) { diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c index 71602f3..3abcc99 100644 --- a/src/openvpn/crypto_openssl.c +++ b/src/openvpn/crypto_openssl.c @@ -679,7 +679,7 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len, { ASSERT(NULL != kt && NULL != ctx); - EVP_CIPHER_CTX_init(ctx); + EVP_CIPHER_CTX_reset(ctx); if (!EVP_CipherInit(ctx, kt, NULL, NULL, enc)) { crypto_msg(M_FATAL, "EVP cipher init #1"); @@ -699,12 +699,6 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len, ASSERT(EVP_CIPHER_CTX_key_length(ctx) <= key_len); } -void -cipher_ctx_cleanup(EVP_CIPHER_CTX *ctx) -{ - EVP_CIPHER_CTX_cleanup(ctx); -} - int cipher_ctx_iv_length(const EVP_CIPHER_CTX *ctx) { diff --git a/src/openvpn/cryptoapi.c b/src/openvpn/cryptoapi.c index 720fce0..7f2c3c0 100644 --- a/src/openvpn/cryptoapi.c +++ b/src/openvpn/cryptoapi.c @@ -39,6 +39,7 @@ #ifdef ENABLE_CRYPTOAPI #include <openssl/ssl.h> +#include <openssl/evp.h> #include <openssl/err.h> #include <windows.h> #include <wincrypt.h> @@ -101,6 +102,12 @@ static ERR_STRING_DATA CRYPTOAPI_str_functs[] = { { 0, NULL } }; +/* Global EVP_PKEY_METHOD used to override the sign operation */ +static EVP_PKEY_METHOD *pmethod; +static int (*default_pkey_sign_init) (EVP_PKEY_CTX *ctx); +static int (*default_pkey_sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, + size_t *siglen, const unsigned char *tbs, size_t tbslen); + typedef struct _CAPI_DATA { const CERT_CONTEXT *cert_context; HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov; @@ -108,6 +115,80 @@ typedef struct _CAPI_DATA { BOOL free_crypt_prov; } CAPI_DATA; +/** + * Translate OpenSSL padding type to CNG padding type + * Returns 0 for unknown/unsupported padding. + */ +static DWORD +cng_padding_type(int padding) +{ + DWORD pad = 0; + + switch (padding) + { + case RSA_NO_PADDING: + pad = BCRYPT_PAD_NONE; + break; + + case RSA_PKCS1_PADDING: + pad = BCRYPT_PAD_PKCS1; + break; + + case RSA_PKCS1_PSS_PADDING: + pad = BCRYPT_PAD_PSS; + break; + + default: + msg(M_WARN|M_INFO, "cryptoapicert: unknown OpenSSL padding type %d.", + padding); + } + + return pad; +} + +/** + * Translate OpenSSL hash OID to CNG algorithm name. Returns + * "UNKNOWN" for unsupported algorithms and NULL for MD5+SHA1 + * mixed hash used in TLS 1.1 and earlier. + */ +static const wchar_t * +cng_hash_algo(int md_type) +{ + const wchar_t *alg = L"UNKNOWN"; + switch (md_type) + { + case NID_md5: + alg = BCRYPT_MD5_ALGORITHM; + break; + + case NID_sha1: + alg = BCRYPT_SHA1_ALGORITHM; + break; + + case NID_sha256: + alg = BCRYPT_SHA256_ALGORITHM; + break; + + case NID_sha384: + alg = BCRYPT_SHA384_ALGORITHM; + break; + + case NID_sha512: + alg = BCRYPT_SHA512_ALGORITHM; + break; + + case NID_md5_sha1: + case 0: + alg = NULL; + break; + + default: + msg(M_WARN|M_INFO, "cryptoapicert: Unknown hash type NID=0x%x", md_type); + break; + } + return alg; +} + static char * ms_error_text(DWORD ms_err) { @@ -217,25 +298,44 @@ rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, in * Sign the hash in 'from' using NCryptSignHash(). This requires an NCRYPT * key handle in cd->crypt_prov. On return the signature is in 'to'. Returns * the length of the signature or 0 on error. + * Only RSA is supported and padding should be BCRYPT_PAD_PKCS1 or + * BCRYPT_PAD_PSS. * If the hash_algo is not NULL, PKCS #1 DigestInfo header gets added - * to 'from', else it is signed as is. - * For now we support only RSA and the padding is assumed to be PKCS1 v1.5 + * to |from|, else it is signed as is. Use NULL for MD5 + SHA1 hash used + * in TLS 1.1 and earlier. + * In case of PSS padding, |saltlen| should specify the size of salt to use. + * If |to| is NULL returns the required buffer size. */ static int priv_enc_CNG(const CAPI_DATA *cd, const wchar_t *hash_algo, const unsigned char *from, - int flen, unsigned char *to, int tlen, int padding) + int flen, unsigned char *to, int tlen, DWORD padding, DWORD saltlen) { NCRYPT_KEY_HANDLE hkey = cd->crypt_prov; DWORD len = 0; ASSERT(cd->key_spec == CERT_NCRYPT_KEY_SPEC); - msg(D_LOW, "Signing hash using CNG: data size = %d", flen); - - BCRYPT_PKCS1_PADDING_INFO padinfo = {hash_algo}; DWORD status; - status = NCryptSignHash(hkey, padding? &padinfo : NULL, (BYTE*) from, flen, - to, tlen, &len, padding? BCRYPT_PAD_PKCS1 : 0); + msg(D_LOW, "Signing hash using CNG: data size = %d padding = %lu", flen, padding); + + if (padding == BCRYPT_PAD_PKCS1) + { + BCRYPT_PKCS1_PADDING_INFO padinfo = {hash_algo}; + status = NCryptSignHash(hkey, &padinfo, (BYTE *)from, flen, + to, tlen, &len, padding); + } + else if (padding == BCRYPT_PAD_PSS) + { + BCRYPT_PSS_PADDING_INFO padinfo = {hash_algo, saltlen}; + status = NCryptSignHash(hkey, &padinfo, (BYTE *)from, flen, + to, tlen, &len, padding); + } + else + { + RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); + return 0; + } + if (status != ERROR_SUCCESS) { SetLastError(status); @@ -261,16 +361,19 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } + + if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) + { + return priv_enc_CNG(cd, NULL, from, flen, to, RSA_size(rsa), + cng_padding_type(padding), 0); + } + if (padding != RSA_PKCS1_PADDING) { /* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */ RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } - if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) - { - return priv_enc_CNG(cd, NULL, from, flen, to, RSA_size(rsa), padding); - } /* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would * be way to straightforward for M$, I guess... So we have to do it this @@ -333,12 +436,13 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i return len; } -/* +/** * Sign the hash in |m| and return the signature in |sig|. * Returns 1 on success, 0 on error. * NCryptSignHash() is used to sign and it is instructed to add the * the PKCS #1 DigestInfo header to |m| unless the hash algorithm is * the MD5/SHA1 combination used in TLS 1.1 and earlier versions. + * OpenSSL exercises this callback only when padding is PKCS1 v1.5. */ static int rsa_sign_CNG(int type, const unsigned char *m, unsigned int m_len, @@ -355,45 +459,17 @@ rsa_sign_CNG(int type, const unsigned char *m, unsigned int m_len, return 0; } - switch (type) + alg = cng_hash_algo(type); + if (alg && wcscmp(alg, L"UNKNOWN") == 0) { - case NID_md5: - alg = BCRYPT_MD5_ALGORITHM; - break; - - case NID_sha1: - alg = BCRYPT_SHA1_ALGORITHM; - break; - - case NID_sha256: - alg = BCRYPT_SHA256_ALGORITHM; - break; - - case NID_sha384: - alg = BCRYPT_SHA384_ALGORITHM; - break; - - case NID_sha512: - alg = BCRYPT_SHA512_ALGORITHM; - break; - - case NID_md5_sha1: - if (m_len != SSL_SIG_LENGTH) - { - RSAerr(RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH); - return 0; - } - /* No DigestInfo header is required -- set alg-name to NULL */ - alg = NULL; - break; - default: - msg(M_WARN, "cryptoapicert: Unknown hash type NID=0x%x", type); - RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); - return 0; + RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return 0; } - *siglen = priv_enc_CNG(cd, alg, m, (int)m_len, sig, RSA_size(rsa), padding); - return (siglen == 0) ? 0 : 1; + *siglen = priv_enc_CNG(cd, alg, m, (int)m_len, sig, RSA_size(rsa), + cng_padding_type(padding), 0); + + return (*siglen == 0) ? 0 : 1; } /* decrypt */ @@ -518,6 +594,176 @@ find_certificate_in_store(const char *cert_prop, HCERTSTORE cert_store) return rv; } +#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) + +static const CAPI_DATA * +retrieve_capi_data(EVP_PKEY *pkey) +{ + const CAPI_DATA *cd = NULL; + + if (pkey && EVP_PKEY_id(pkey) == EVP_PKEY_RSA) + { + RSA *rsa = EVP_PKEY_get0_RSA(pkey); + if (rsa) + { + cd = (CAPI_DATA *)RSA_meth_get0_app_data(RSA_get_method(rsa)); + } + } + return cd; +} + +static int +pkey_rsa_sign_init(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx); + + if (pkey && retrieve_capi_data(pkey)) + { + return 1; /* Return success */ + } + else if (default_pkey_sign_init) /* Not our key. Call the default method */ + { + return default_pkey_sign_init(ctx); + } + return 1; +} + +/** + * Implementation of EVP_PKEY_sign() using CNG: sign the digest in |tbs| + * and save the the signature in |sig| and its size in |*siglen|. + * If |sig| is NULL the required buffer size is returned in |*siglen|. + * Returns 1 on success, 0 or a negative integer on error. + */ +static int +pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, + const unsigned char *tbs, size_t tbslen) +{ + EVP_PKEY *pkey = NULL; + const CAPI_DATA *cd = NULL; + EVP_MD *md = NULL; + const wchar_t *alg = NULL; + + int padding; + int hashlen; + int saltlen; + + pkey = EVP_PKEY_CTX_get0_pkey(ctx); + if (pkey) + { + cd = retrieve_capi_data(pkey); + } + + /* + * We intercept all sign requests, not just the one's for our key. + * Check the key and call the saved OpenSSL method for unknown keys. + */ + if (!pkey || !cd) + { + if (default_pkey_sign) + { + return default_pkey_sign(ctx, sig, siglen, tbs, tbslen); + } + else /* This should not happen */ + { + msg(M_FATAL, "cryptopaicert: Unknown key and no default sign operation to fallback on"); + return -1; + } + } + + if (!EVP_PKEY_CTX_get_rsa_padding(ctx, &padding)) + { + padding = RSA_PKCS1_PADDING; /* Default padding for RSA */ + } + + if (EVP_PKEY_CTX_get_signature_md(ctx, &md)) + { + hashlen = EVP_MD_size(md); + alg = cng_hash_algo(EVP_MD_type(md)); + + /* + * alg == NULL indicates legacy MD5+SHA1 hash, else alg should be a valid + * digest algorithm. + */ + if (alg && wcscmp(alg, L"UNKNOWN") == 0) + { + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return -1; + } + } + else + { + msg(M_NONFATAL, "cryptoapicert: could not determine the signature digest algorithm"); + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE); + return -1; + } + + if (tbslen != (size_t)hashlen) + { + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH); + return -1; + } + + /* If padding is PSS, determine parameters to pass to CNG */ + if (padding == RSA_PKCS1_PSS_PADDING) + { + /* + * Ensure the digest type for signature and mask generation match. + * In CNG there is no option to specify separate hash functions for + * the two, but OpenSSL supports it. However, I have not seen the + * two being different in practice. Also the recommended practice is + * to use the same for both (rfc 8017 sec 8.1). + */ + EVP_MD *mgf1md; + if (!EVP_PKEY_CTX_get_rsa_mgf1_md(ctx, &mgf1md) + || EVP_MD_type(mgf1md) != EVP_MD_type(md)) + { + msg(M_NONFATAL, "cryptoapicert: Unknown MGF1 digest type or does" + " not match the signature digest type."); + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_UNSUPPORTED_MASK_PARAMETER); + } + + if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx, &saltlen)) + { + msg(M_WARN|M_INFO, "cryptoapicert: unable to get the salt length from context." + " Using the default value."); + saltlen = -1; + } + + /* + * In OpenSSL saltlen = -1 indicates to use the size of the digest as + * size of the salt. A value of -2 or -3 indicates maximum salt length + * that will fit. See RSA_padding_add_PKCS1_PSS_mgf1() of OpenSSL. + */ + if (saltlen == -1) + { + saltlen = hashlen; + } + else if (saltlen < 0) + { + const RSA *rsa = EVP_PKEY_get0_RSA(pkey); + saltlen = RSA_size(rsa) - hashlen - 2; /* max salt length for RSASSA-PSS */ + if (RSA_bits(rsa) &0x7) /* number of bits in the key not a multiple of 8 */ + { + saltlen--; + } + } + + if (saltlen < 0) + { + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE); + return -1; + } + msg(D_LOW, "cryptoapicert: PSS padding using saltlen = %d", saltlen); + } + + *siglen = priv_enc_CNG(cd, alg, tbs, (int)tbslen, sig, *siglen, + cng_padding_type(padding), (DWORD)saltlen); + + return (*siglen == 0) ? 0 : 1; +} + +#endif /* OPENSSL_VERSION >= 1.1.0 */ + int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) { @@ -620,10 +866,45 @@ SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop) /* For CNG, set the RSA_sign method which gets priority over priv_enc(). * This method is called with the raw hash without the digestinfo * header and works better when using NCryptSignHash() with some tokens. + * However, if PSS padding is in use, openssl does not call this + * function but adds the padding and then calls rsa_priv_enc() + * with padding set to NONE which is not supported by CNG. + * So, when posisble (OpenSSL 1.1.0 and up), we hook on to the sign + * operation in EVP_PKEY_METHOD struct. */ if (cd->key_spec == CERT_NCRYPT_KEY_SPEC) { +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) RSA_meth_set_sign(my_rsa_method, rsa_sign_CNG); +#else + /* pmethod is global -- initialize only if NULL */ + if (!pmethod) + { + pmethod = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0); + if (!pmethod) + { + SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); + goto err; + } + const EVP_PKEY_METHOD *default_pmethod = EVP_PKEY_meth_find(EVP_PKEY_RSA); + EVP_PKEY_meth_copy(pmethod, default_pmethod); + + /* We want to override only sign_init() and sign() */ + EVP_PKEY_meth_set_sign(pmethod, pkey_rsa_sign_init, pkey_rsa_sign); + EVP_PKEY_meth_add0(pmethod); + + /* Keep a copy of the default sign and sign_init methods */ + +#if (OPENSSL_VERSION_NUMBER < 0x1010009fL) /* < version 1.1.0i */ + /* The function signature is not const-correct in these versions */ + EVP_PKEY_meth_get_sign((EVP_PKEY_METHOD *)default_pmethod, &default_pkey_sign_init, + &default_pkey_sign); +#else + EVP_PKEY_meth_get_sign(default_pmethod, &default_pkey_sign_init, + &default_pkey_sign); +#endif + } +#endif /* (OPENSSL_VERSION_NUMBER < 0x10100000L) */ } rsa = RSA_new(); diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index 8f90418..65f790f 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -1037,7 +1037,7 @@ read_incoming_tun(struct context *c) c->c2.buf = c->c2.buffers->read_tun_buf; #ifdef TUN_PASS_BUFFER - read_tun_buffered(c->c1.tuntap, &c->c2.buf, MAX_RW_SIZE_TUN(&c->c2.frame)); + read_tun_buffered(c->c1.tuntap, &c->c2.buf); #else ASSERT(buf_init(&c->c2.buf, FRAME_HEADROOM(&c->c2.frame))); ASSERT(buf_safe(&c->c2.buf, MAX_RW_SIZE_TUN(&c->c2.frame))); diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 1cdef31..d3785ca 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -3883,7 +3883,7 @@ init_management_callback_p2p(struct context *c) #ifdef ENABLE_MANAGEMENT void -init_management(struct context *c) +init_management(void) { if (!management) { diff --git a/src/openvpn/init.h b/src/openvpn/init.h index c8ebe76..2c846db 100644 --- a/src/openvpn/init.h +++ b/src/openvpn/init.h @@ -119,7 +119,7 @@ void initialization_sequence_completed(struct context *c, const unsigned int fla #ifdef ENABLE_MANAGEMENT -void init_management(struct context *c); +void init_management(void); bool open_management(struct context *c); diff --git a/src/openvpn/misc.c b/src/openvpn/misc.c index 581a890..f44c65f 100644 --- a/src/openvpn/misc.c +++ b/src/openvpn/misc.c @@ -99,44 +99,57 @@ save_inetd_socket_descriptor(void) } /* - * Print an error message based on the status code returned by system(). + * Generate an error message based on the status code returned by openvpn_execve(). */ const char * system_error_message(int stat, struct gc_arena *gc) { struct buffer out = alloc_buf_gc(256, gc); -#ifdef _WIN32 - if (stat == -1) + + switch (stat) { - buf_printf(&out, "external program did not execute -- "); - } - buf_printf(&out, "returned error code %d", stat); + case OPENVPN_EXECVE_NOT_ALLOWED: + buf_printf(&out, "disallowed by script-security setting"); + break; + +#ifdef _WIN32 + case OPENVPN_EXECVE_ERROR: + buf_printf(&out, "external program did not execute -- "); + /* fall through */ + + default: + buf_printf(&out, "returned error code %d", stat); + break; #else /* ifdef _WIN32 */ - if (stat == -1) - { - buf_printf(&out, "external program fork failed"); - } - else if (!WIFEXITED(stat)) - { - buf_printf(&out, "external program did not exit normally"); - } - else - { - const int cmd_ret = WEXITSTATUS(stat); - if (!cmd_ret) - { - buf_printf(&out, "external program exited normally"); - } - else if (cmd_ret == 127) - { - buf_printf(&out, "could not execute external program"); - } - else - { - buf_printf(&out, "external program exited with error status: %d", cmd_ret); - } - } + + case OPENVPN_EXECVE_ERROR: + buf_printf(&out, "external program fork failed"); + break; + + default: + if (!WIFEXITED(stat)) + { + buf_printf(&out, "external program did not exit normally"); + } + else + { + const int cmd_ret = WEXITSTATUS(stat); + if (!cmd_ret) + { + buf_printf(&out, "external program exited normally"); + } + else if (cmd_ret == OPENVPN_EXECVE_FAILURE) + { + buf_printf(&out, "could not execute external program"); + } + else + { + buf_printf(&out, "external program exited with error status: %d", cmd_ret); + } + } + break; #endif /* ifdef _WIN32 */ + } return (const char *)out.data; } @@ -186,12 +199,14 @@ openvpn_execve_allowed(const unsigned int flags) * Run execve() inside a fork(). Designed to replicate the semantics of system() but * in a safer way that doesn't require the invocation of a shell or the risks * assocated with formatting and parsing a command line. + * Returns the exit status of child, OPENVPN_EXECVE_NOT_ALLOWED if openvpn_execve_allowed() + * returns false, or OPENVPN_EXECVE_ERROR on other errors. */ int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags) { struct gc_arena gc = gc_new(); - int ret = -1; + int ret = OPENVPN_EXECVE_ERROR; static bool warn_shown = false; if (a && a->argv[0]) @@ -208,7 +223,7 @@ openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned in if (pid == (pid_t)0) /* child side */ { execve(cmd, argv, envp); - exit(127); + exit(OPENVPN_EXECVE_FAILURE); } else if (pid < (pid_t)0) /* fork failed */ { @@ -218,14 +233,18 @@ openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned in { if (waitpid(pid, &ret, 0) != pid) { - ret = -1; + ret = OPENVPN_EXECVE_ERROR; } } } - else if (!warn_shown && (script_security < SSEC_SCRIPTS)) + else { - msg(M_WARN, SCRIPT_SECURITY_WARNING); - warn_shown = true; + ret = OPENVPN_EXECVE_NOT_ALLOWED; + if (!warn_shown && (script_security < SSEC_SCRIPTS)) + { + msg(M_WARN, SCRIPT_SECURITY_WARNING); + warn_shown = true; + } } #else /* if defined(ENABLE_FEATURE_EXECVE) */ msg(M_WARN, "openvpn_execve: execve function not available"); @@ -272,7 +291,7 @@ openvpn_popen(const struct argv *a, const struct env_set *es) close(pipe_stdout[0]); /* Close read end */ dup2(pipe_stdout[1],1); execve(cmd, argv, envp); - exit(127); + exit(OPENVPN_EXECVE_FAILURE); } else if (pid > (pid_t)0) /* parent side */ { diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h index a64ddcc..8a34f43 100644 --- a/src/openvpn/misc.h +++ b/src/openvpn/misc.h @@ -57,6 +57,11 @@ struct env_set { const char *system_error_message(int, struct gc_arena *gc); +/* openvpn_execve return codes */ +#define OPENVPN_EXECVE_ERROR -1 /* generic error while forking to run an external program */ +#define OPENVPN_EXECVE_NOT_ALLOWED -2 /* external program not run due to script security */ +#define OPENVPN_EXECVE_FAILURE 127 /* exit code passed back from child when execve fails */ + /* wrapper around the execve() call */ int openvpn_popen(const struct argv *a, const struct env_set *es); diff --git a/src/openvpn/mtcp.c b/src/openvpn/mtcp.c index 3756c27..e8d2add 100644 --- a/src/openvpn/mtcp.c +++ b/src/openvpn/mtcp.c @@ -834,7 +834,7 @@ tunnel_server_tcp(struct context *top) #endif /* shut down management interface */ - uninit_management_callback_multi(&multi); + uninit_management_callback(); /* save ifconfig-pool */ multi_ifconfig_pool_persist(&multi, true); diff --git a/src/openvpn/mudp.c b/src/openvpn/mudp.c index b3690ab..4f63654 100644 --- a/src/openvpn/mudp.c +++ b/src/openvpn/mudp.c @@ -362,7 +362,7 @@ tunnel_server_udp_single_threaded(struct context *top) #endif /* shut down management interface */ - uninit_management_callback_multi(&multi); + uninit_management_callback(); /* save ifconfig-pool */ multi_ifconfig_pool_persist(&multi, true); diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index 28c3b88..baffd74 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -555,8 +555,7 @@ setenv_stats(struct context *c) } static void -multi_client_disconnect_setenv(struct multi_context *m, - struct multi_instance *mi) +multi_client_disconnect_setenv(struct multi_instance *mi) { /* setenv client real IP address */ setenv_trusted(mi->context.c2.es, get_link_socket_info(&mi->context)); @@ -572,13 +571,12 @@ multi_client_disconnect_setenv(struct multi_context *m, } static void -multi_client_disconnect_script(struct multi_context *m, - struct multi_instance *mi) +multi_client_disconnect_script(struct multi_instance *mi) { if ((mi->context.c2.context_auth == CAS_SUCCEEDED && mi->connection_established_flag) || mi->context.c2.context_auth == CAS_PARTIAL) { - multi_client_disconnect_setenv(m, mi); + multi_client_disconnect_setenv(mi); if (plugin_defined(mi->context.plugins, OPENVPN_PLUGIN_CLIENT_DISCONNECT)) { @@ -685,7 +683,7 @@ multi_close_instance(struct multi_context *m, set_cc_config(mi, NULL); #endif - multi_client_disconnect_script(m, mi); + multi_client_disconnect_script(mi); if (mi->did_open_context) { @@ -1112,7 +1110,7 @@ multi_learn_addr(struct multi_context *m, if (oldroute) /* route already exists? */ { - if (route_quota_test(m, mi) && learn_address_script(m, mi, "update", &newroute->addr)) + if (route_quota_test(mi) && learn_address_script(m, mi, "update", &newroute->addr)) { learn_succeeded = true; owner = mi; @@ -1129,7 +1127,7 @@ multi_learn_addr(struct multi_context *m, } else { - if (route_quota_test(m, mi) && learn_address_script(m, mi, "add", &newroute->addr)) + if (route_quota_test(mi) && learn_address_script(m, mi, "add", &newroute->addr)) { learn_succeeded = true; owner = mi; @@ -1579,7 +1577,7 @@ multi_select_virtual_addr(struct multi_context *m, struct multi_instance *mi) * Set virtual address environmental variables. */ static void -multi_set_virtual_addr_env(struct multi_context *m, struct multi_instance *mi) +multi_set_virtual_addr_env(struct multi_instance *mi) { setenv_del(mi->context.c2.es, "ifconfig_pool_local_ip"); setenv_del(mi->context.c2.es, "ifconfig_pool_remote_ip"); @@ -1658,7 +1656,7 @@ multi_client_connect_post(struct multi_context *m, * directory or any --ifconfig-pool dynamic address. */ multi_select_virtual_addr(m, mi); - multi_set_virtual_addr_env(m, mi); + multi_set_virtual_addr_env(mi); } } @@ -1702,7 +1700,7 @@ multi_client_connect_post_plugin(struct multi_context *m, * directory or any --ifconfig-pool dynamic address. */ multi_select_virtual_addr(m, mi); - multi_set_virtual_addr_env(m, mi); + multi_set_virtual_addr_env(mi); } } @@ -1742,7 +1740,7 @@ multi_client_connect_mda(struct multi_context *m, * directory or any --ifconfig-pool dynamic address. */ multi_select_virtual_addr(m, mi); - multi_set_virtual_addr_env(m, mi); + multi_set_virtual_addr_env(mi); } } @@ -1761,7 +1759,7 @@ multi_client_connect_setenv(struct multi_context *m, setenv_trusted(mi->context.c2.es, get_link_socket_info(&mi->context)); /* setenv client virtual IP address */ - multi_set_virtual_addr_env(m, mi); + multi_set_virtual_addr_env(mi); /* setenv connection time */ { @@ -2919,7 +2917,7 @@ multi_process_drop_outgoing_tun(struct multi_context *m, const unsigned int mpp_ */ void -route_quota_exceeded(const struct multi_context *m, const struct multi_instance *mi) +route_quota_exceeded(const struct multi_instance *mi) { struct gc_arena gc = gc_new(); msg(D_ROUTE_QUOTA, "MULTI ROUTE: route quota (%d) exceeded for %s (see --max-routes-per-client option)", @@ -3355,12 +3353,6 @@ init_management_callback_multi(struct multi_context *m) #endif /* ifdef ENABLE_MANAGEMENT */ } -void -uninit_management_callback_multi(struct multi_context *m) -{ - uninit_management_callback(); -} - /* * Top level event loop. */ diff --git a/src/openvpn/multi.h b/src/openvpn/multi.h index d7e5c29..ebcc22d 100644 --- a/src/openvpn/multi.h +++ b/src/openvpn/multi.h @@ -346,9 +346,6 @@ void multi_close_instance_on_signal(struct multi_context *m, struct multi_instan void init_management_callback_multi(struct multi_context *m); -void uninit_management_callback_multi(struct multi_context *m); - - #ifdef ENABLE_ASYNC_PUSH /** * Called when inotify event is fired, which happens when acf file is closed or deleted. @@ -403,7 +400,7 @@ multi_process_outgoing_link_pre(struct multi_context *m) * Per-client route quota management */ -void route_quota_exceeded(const struct multi_context *m, const struct multi_instance *mi); +void route_quota_exceeded(const struct multi_instance *mi); static inline void route_quota_inc(struct multi_instance *mi) @@ -419,11 +416,11 @@ route_quota_dec(struct multi_instance *mi) /* can we add a new route? */ static inline bool -route_quota_test(const struct multi_context *m, const struct multi_instance *mi) +route_quota_test(const struct multi_instance *mi) { if (mi->route_count >= mi->context.options.max_routes_per_client) { - route_quota_exceeded(m, mi); + route_quota_exceeded(mi); return false; } else diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h index e680702..8acc7d1 100644 --- a/src/openvpn/openssl_compat.h +++ b/src/openvpn/openssl_compat.h @@ -88,6 +88,18 @@ EVP_MD_CTX_new(void) } #endif +#if !defined(HAVE_EVP_CIPHER_CTX_RESET) +#define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_init +#endif + +#if !defined(HAVE_X509_GET0_NOTBEFORE) +#define X509_get0_notBefore X509_get_notBefore +#endif + +#if !defined(HAVE_X509_GET0_NOTAFTER) +#define X509_get0_notAfter X509_get_notAfter +#endif + #if !defined(HAVE_HMAC_CTX_RESET) /** * Reset a HMAC context diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c index 3819889..3d244fc 100644 --- a/src/openvpn/openvpn.c +++ b/src/openvpn/openvpn.c @@ -201,7 +201,7 @@ openvpn_main(int argc, char *argv[]) #ifdef ENABLE_MANAGEMENT /* initialize management subsystem */ - init_management(&c); + init_management(); #endif /* initialize options to default state */ diff --git a/src/openvpn/openvpn_win32_resources.rc b/src/openvpn/openvpn_win32_resources.rc index d092e21..e4f1ee9 100644 --- a/src/openvpn/openvpn_win32_resources.rc +++ b/src/openvpn/openvpn_win32_resources.rc @@ -19,7 +19,7 @@ VS_VERSION_INFO VERSIONINFO FILEFLAGS 0x0L #endif FILEOS 0x40004L - FILETYPE 0x2L + FILETYPE VFT_APP FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" diff --git a/src/openvpn/options.c b/src/openvpn/options.c index f951814..de30fcb 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -2228,7 +2228,7 @@ options_postprocess_verify_ce(const struct options *options, const struct connec } if (options->pull_filter_list) { - msg(M_USAGE, "--pull-filter cannot be used with --mode server"); + msg(M_WARN, "--pull-filter ignored for --mode server"); } if (!(proto_is_udp(ce->proto) || ce->proto == PROTO_TCP_SERVER)) { @@ -2832,6 +2832,24 @@ options_postprocess_mutate_ce(struct options *o, struct connection_entry *ce) #endif } + /* our socks code is not fully IPv6 enabled yet (TCP works, UDP not) + * so fall back to IPv4-only (trac #1221) + */ + if (ce->socks_proxy_server && proto_is_udp(ce->proto) && ce->af != AF_INET) + { + if (ce->af == AF_INET6) + { + msg(M_INFO, "WARNING: '--proto udp6' is not compatible with " + "'--socks-proxy' today. Forcing IPv4 mode." ); + } + else + { + msg(M_INFO, "NOTICE: dual-stack mode for '--proto udp' does not " + "work correctly with '--socks-proxy' today. Forcing IPv4." ); + } + ce->af = AF_INET; + } + /* * Set MTU defaults */ diff --git a/src/openvpn/pkcs11.c b/src/openvpn/pkcs11.c index 93f8580..d40ca45 100644 --- a/src/openvpn/pkcs11.c +++ b/src/openvpn/pkcs11.c @@ -312,7 +312,7 @@ pkcs11_initialize( pkcs11h_setLogLevel(_pkcs11_msg_openvpn2pkcs11(get_debug_level())); - if ((rv = pkcs11h_setForkMode(TRUE)) != CKR_OK) + if ((rv = pkcs11h_setForkMode(FALSE)) != CKR_OK) { msg(M_FATAL, "PKCS#11: Cannot set fork mode %ld-'%s'", rv, pkcs11h_getMessage(rv)); goto cleanup; diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c index 3fdec86..afcca86 100644 --- a/src/openvpn/proxy.c +++ b/src/openvpn/proxy.c @@ -355,7 +355,7 @@ get_proxy_authenticate(socket_descriptor_t sd, #if NTLM else if (!strncmp(buf+20, "NTLM", 4)) { - msg(D_PROXY, "PROXY AUTH HTLM: '%s'", buf); + msg(D_PROXY, "PROXY AUTH NTLM: '%s'", buf); *data = NULL; ret = HTTP_AUTH_NTLM; } diff --git a/src/openvpn/route.c b/src/openvpn/route.c index 2d6428b..4199da3 100644 --- a/src/openvpn/route.c +++ b/src/openvpn/route.c @@ -2038,8 +2038,8 @@ add_route_ipv6(struct route_ipv6 *r6, const struct tuntap *tt, unsigned int flag r6->netbits, gateway ); - /* on tun/tap, not "elsewhere"? -> metric 0 */ - if (!r6->iface) + /* on tun (not tap), not "elsewhere"? -> metric 0 */ + if (tt->type == DEV_TYPE_TUN && !r6->iface) { argv_printf_cat(&argv, "0"); } diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c index c76d206..9131ec2 100644 --- a/src/openvpn/socket.c +++ b/src/openvpn/socket.c @@ -1170,7 +1170,7 @@ socket_do_listen(socket_descriptor_t sd, ASSERT(local); msg(M_INFO, "Listening for incoming TCP connection on %s", print_sockaddr(local->ai_addr, &gc)); - if (listen(sd, 1)) + if (listen(sd, 32)) { msg(M_ERR, "TCP: listen() failed"); } diff --git a/src/openvpn/socks.c b/src/openvpn/socks.c index c61ef55..ad3a70b 100644 --- a/src/openvpn/socks.c +++ b/src/openvpn/socks.c @@ -414,6 +414,10 @@ recv_socks_reply(socket_descriptor_t sd, { memcpy(&addr->addr.in4.sin_addr, buf + 4, sizeof(addr->addr.in4.sin_addr)); memcpy(&addr->addr.in4.sin_port, buf + 8, sizeof(addr->addr.in4.sin_port)); + struct gc_arena gc = gc_new(); + msg(M_INFO, "SOCKS proxy wants us to send UDP to %s", + print_sockaddr(addr, &gc)); + gc_free(&gc); } diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c index a78dae9..6aa3ac3 100644 --- a/src/openvpn/ssl_openssl.c +++ b/src/openvpn/ssl_openssl.c @@ -71,12 +71,13 @@ int mydata_index; /* GLOBAL */ void tls_init_lib(void) { +#if (OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) SSL_library_init(); #ifndef ENABLE_SMALL SSL_load_error_strings(); #endif OpenSSL_add_all_algorithms(); - +#endif mydata_index = SSL_get_ex_new_index(0, "struct session *", NULL, NULL, NULL); ASSERT(mydata_index >= 0); } @@ -84,10 +85,12 @@ tls_init_lib(void) void tls_free_lib(void) { +#if (OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) EVP_cleanup(); #ifndef ENABLE_SMALL ERR_free_strings(); #endif +#endif } void @@ -206,7 +209,7 @@ info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) int tls_version_max(void) { -#if defined(TLS1_3_VERSION) +#if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) return TLS_VER_1_3; #elif defined(TLS1_2_VERSION) || defined(SSL_OP_NO_TLSv1_2) return TLS_VER_1_2; @@ -233,7 +236,7 @@ openssl_tls_version(int ver) { return TLS1_2_VERSION; } -#if defined(TLS1_3_VERSION) +#if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) else if (ver == TLS_VER_1_3) { return TLS1_3_VERSION; @@ -459,8 +462,8 @@ tls_ctx_restrict_ciphers_tls13(struct tls_root_ctx *ctx, const char *ciphers) return; } -#if (OPENSSL_VERSION_NUMBER < 0x1010100fL) - crypto_msg(M_WARN, "Not compiled with OpenSSL 1.1.1 or higher. " +#if (OPENSSL_VERSION_NUMBER < 0x1010100fL) || !defined(TLS1_3_VERSION) || defined(OPENSSL_NO_TLS1_3) + crypto_msg(M_WARN, "Not compiled with OpenSSL 1.1.1 or higher, or without TLS 1.3 support. " "Ignoring TLS 1.3 only tls-ciphersuites '%s' setting.", ciphers); #else @@ -534,7 +537,7 @@ tls_ctx_check_cert_time(const struct tls_root_ctx *ctx) goto cleanup; /* Nothing to check if there is no certificate */ } - ret = X509_cmp_time(X509_get_notBefore(cert), NULL); + ret = X509_cmp_time(X509_get0_notBefore(cert), NULL); if (ret == 0) { msg(D_TLS_DEBUG_MED, "Failed to read certificate notBefore field."); @@ -544,7 +547,7 @@ tls_ctx_check_cert_time(const struct tls_root_ctx *ctx) msg(M_WARN, "WARNING: Your certificate is not yet valid!"); } - ret = X509_cmp_time(X509_get_notAfter(cert), NULL); + ret = X509_cmp_time(X509_get0_notAfter(cert), NULL); if (ret == 0) { msg(D_TLS_DEBUG_MED, "Failed to read certificate notAfter field."); @@ -626,10 +629,13 @@ tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name else { #if OPENSSL_VERSION_NUMBER >= 0x10002000L +#if (OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)) + /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter * loading */ SSL_CTX_set_ecdh_auto(ctx->ctx, 1); return; +#endif #else /* For older OpenSSL we have to extract the curve from key on our own */ EC_KEY *eckey = NULL; @@ -1846,7 +1852,7 @@ show_available_tls_ciphers_list(const char *cipher_list, crypto_msg(M_FATAL, "Cannot create SSL_CTX object"); } -#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL) +#if (OPENSSL_VERSION_NUMBER >= 0x1010100fL) && defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) if (tls13) { SSL_CTX_set_min_proto_version(tls_ctx.ctx, TLS1_3_VERSION); diff --git a/src/openvpn/tun.c b/src/openvpn/tun.c index 63f9d1b..80eaa2c 100644 --- a/src/openvpn/tun.c +++ b/src/openvpn/tun.c @@ -5044,7 +5044,6 @@ void ipconfig_register_dns(const struct env_set *es) { struct argv argv = argv_new(); - bool status; const char err[] = "ERROR: Windows ipconfig command failed"; msg(D_TUNTAP_INFO, "Start ipconfig commands for register-dns..."); @@ -5054,14 +5053,14 @@ ipconfig_register_dns(const struct env_set *es) get_win_sys_path(), WIN_IPCONFIG_PATH_SUFFIX); argv_msg(D_TUNTAP_INFO, &argv); - status = openvpn_execve_check(&argv, es, 0, err); + openvpn_execve_check(&argv, es, 0, err); argv_reset(&argv); argv_printf(&argv, "%s%sc /registerdns", get_win_sys_path(), WIN_IPCONFIG_PATH_SUFFIX); argv_msg(D_TUNTAP_INFO, &argv); - status = openvpn_execve_check(&argv, es, 0, err); + openvpn_execve_check(&argv, es, 0, err); argv_reset(&argv); netcmd_semaphore_release(); @@ -5355,8 +5354,7 @@ netsh_ifconfig(const struct tuntap_options *to, } static void -netsh_enable_dhcp(const struct tuntap_options *to, - const char *actual_name) +netsh_enable_dhcp(const char *actual_name) { struct argv argv = argv_new(); @@ -5902,7 +5900,7 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun } else { - netsh_enable_dhcp(&tt->options, tt->actual_name); + netsh_enable_dhcp(tt->actual_name); } } dhcp_masq = true; diff --git a/src/openvpn/tun.h b/src/openvpn/tun.h index 6c57ad0..54e1dfa 100644 --- a/src/openvpn/tun.h +++ b/src/openvpn/tun.h @@ -452,7 +452,7 @@ tun_write_win32(struct tuntap *tt, struct buffer *buf) } static inline int -read_tun_buffered(struct tuntap *tt, struct buffer *buf, int maxsize) +read_tun_buffered(struct tuntap *tt, struct buffer *buf) { return tun_finalize(tt->hand, &tt->reads, buf); } diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index 29bbb84..f13807f 100644 --- a/src/openvpn/win32.c +++ b/src/openvpn/win32.c @@ -685,11 +685,10 @@ win32_pause(struct win32_signal *ws) { if (ws->mode == WSO_MODE_CONSOLE && HANDLE_DEFINED(ws->in.read)) { - int status; msg(M_INFO|M_NOPREFIX, "Press any key to continue..."); do { - status = WaitForSingleObject(ws->in.read, INFINITE); + WaitForSingleObject(ws->in.read, INFINITE); } while (!win32_keyboard_get(ws)); } } @@ -1088,7 +1087,7 @@ wide_cmd_line(const struct argv *a, struct gc_arena *gc) int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags) { - int ret = -1; + int ret = OPENVPN_EXECVE_ERROR; static bool exec_warn = false; if (a && a->argv[0]) @@ -1137,10 +1136,14 @@ openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned in free(env); gc_free(&gc); } - else if (!exec_warn && (script_security < SSEC_SCRIPTS)) + else { - msg(M_WARN, SCRIPT_SECURITY_WARNING); - exec_warn = true; + ret = OPENVPN_EXECVE_NOT_ALLOWED; + if (!exec_warn && (script_security < SSEC_SCRIPTS)) + { + msg(M_WARN, SCRIPT_SECURITY_WARNING); + exec_warn = true; + } } } else |