summaryrefslogtreecommitdiff
path: root/openvpn/src
diff options
context:
space:
mode:
Diffstat (limited to 'openvpn/src')
-rw-r--r--openvpn/src/compat/compat-rsa_generate_key.c49
-rw-r--r--openvpn/src/openvpn/buffer.h2
-rw-r--r--openvpn/src/openvpn/init.c21
-rw-r--r--openvpn/src/openvpn/openvpn.h4
-rw-r--r--openvpn/src/openvpn/options.c112
-rw-r--r--openvpn/src/openvpn/pkcs11_openssl.c14
-rw-r--r--openvpn/src/openvpn/proxy.c2
-rw-r--r--openvpn/src/openvpn/proxy.h2
-rw-r--r--openvpn/src/openvpn/socket.c196
-rw-r--r--openvpn/src/openvpn/socket.h10
-rw-r--r--openvpn/src/openvpn/ssl.c5
-rw-r--r--openvpn/src/openvpn/ssl_backend.h9
-rw-r--r--openvpn/src/openvpn/ssl_openssl.c171
-rw-r--r--openvpn/src/openvpn/ssl_polarssl.c15
-rw-r--r--openvpn/src/openvpn/win32.c34
15 files changed, 334 insertions, 312 deletions
diff --git a/openvpn/src/compat/compat-rsa_generate_key.c b/openvpn/src/compat/compat-rsa_generate_key.c
deleted file mode 100644
index 87dd1ccb..00000000
--- a/openvpn/src/compat/compat-rsa_generate_key.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include <stdio.h>
-#include <time.h>
-#include "cryptlib.h"
-#include <openssl/bn.h>
-#include <openssl/rsa.h>
-
-#ifdef ENABLE_CRYPTO_OPENSSL
-RSA *RSA_generate_key(int bits, unsigned long e_value,
- void (*callback)(int,int,void *), void *cb_arg)
-{
- BN_GENCB cb;
- int i;
- RSA *rsa = RSA_new();
- BIGNUM *e = BN_new();
-
- if(!rsa || !e) goto err;
-
- /* The problem is when building with 8, 16, or 32 BN_ULONG,
- * unsigned long can be larger */
- for (i=0; i<(int)sizeof(unsigned long)*8; i++)
- {
- if (e_value & (1UL<<i))
- if (BN_set_bit(e,i) == 0)
- goto err;
- }
-
- BN_GENCB_set_old(&cb, callback, cb_arg);
-
- if(RSA_generate_key_ex(rsa, bits, e, &cb)) {
- BN_free(e);
- return rsa;
- }
- err:
- if(e) BN_free(e);
- if(rsa) RSA_free(rsa);
- return 0;
-}
-
-
-
-void mlockall(){}
-char *
-getpass (prompt)
- const char *prompt;
-{
- return "";
-}
-
-#endif
diff --git a/openvpn/src/openvpn/buffer.h b/openvpn/src/openvpn/buffer.h
index 425d0eb6..0010c771 100644
--- a/openvpn/src/openvpn/buffer.h
+++ b/openvpn/src/openvpn/buffer.h
@@ -93,7 +93,7 @@ struct gc_entry
/**
* Gargabe collection entry for a specially allocated structure that needs
- * a custom free function to be freed like struct addrinfo
+ * a custom free function to be freed like struct addrinfo
*
*/
struct gc_entry_special
diff --git a/openvpn/src/openvpn/init.c b/openvpn/src/openvpn/init.c
index c42c0f78..d5597362 100644
--- a/openvpn/src/openvpn/init.c
+++ b/openvpn/src/openvpn/init.c
@@ -130,25 +130,16 @@ management_callback_proxy_cmd (void *arg, const char **p)
#ifndef ENABLE_HTTP_PROXY
msg (M_WARN, "HTTP proxy support is not available");
#else
- struct http_proxy_options *ho, *oldho;
+ struct http_proxy_options *ho;
if (ce->proto != PROTO_TCP && ce->proto != PROTO_TCP_CLIENT ) {
msg (M_WARN, "HTTP proxy support only works for TCP based connections");
return false;
}
- oldho = ce->http_proxy_options;
ho = init_http_proxy_options_once (&ce->http_proxy_options, gc);
ho->server = string_alloc (p[2], gc);
ho->port = string_alloc (p[3], gc);
ho->retry = true;
ho->auth_retry = (p[4] && streq (p[4], "nct") ? PAR_NCT : PAR_ALL);
-
- /* Save the old preresolved addrinfo we are using the same proxy again */
- if (oldho &&
- oldho->preresolved_proxy &&
- streq(oldho->server, ho->server) &&
- streq(oldho->port, ho->port))
- ho->preresolved_proxy = oldho->preresolved_proxy;
-
ret = true;
#endif
}
@@ -571,8 +562,6 @@ context_init_1 (struct context *c)
}
#endif
- if (c->options.resolve_in_advance)
- do_preresolve(c);
}
void
@@ -893,7 +882,7 @@ print_openssl_info (const struct options *options)
show_available_engines ();
#ifdef ENABLE_SSL
if (options->show_tls_ciphers)
- show_available_tls_ciphers ();
+ show_available_tls_ciphers (options->cipher_list);
#endif
return true;
}
@@ -2701,7 +2690,7 @@ do_init_socket_1 (struct context *c, const int mode)
c->options.ce.local_port,
c->options.ce.remote,
c->options.ce.remote_port,
- c->c1.preresolved,
+ c->c1.dns_cache,
c->options.ce.proto,
c->options.ce.af,
c->options.ce.bind_ipv6_only,
@@ -3376,7 +3365,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
if (c->options.resolve_in_advance)
{
- do_preresolve(c);
+ do_preresolve (c);
if (IS_SIG (c))
goto sig;
}
@@ -3455,7 +3444,7 @@ init_instance (struct context *c, const struct env_set *env, const unsigned int
/* allocate our socket object */
if (c->mode == CM_P2P || c->mode == CM_TOP || c->mode == CM_CHILD_TCP)
do_link_socket_new (c);
-
+
#ifdef ENABLE_FRAGMENT
/* initialize internal fragmentation object */
if (options->ce.fragment && (c->mode == CM_P2P || child))
diff --git a/openvpn/src/openvpn/openvpn.h b/openvpn/src/openvpn/openvpn.h
index 3ed7810a..7ad6c55c 100644
--- a/openvpn/src/openvpn/openvpn.h
+++ b/openvpn/src/openvpn/openvpn.h
@@ -166,8 +166,8 @@ struct context_1
/* tunnel session keys */
struct key_schedule ks;
- /* preresolved host names */
- struct preresovled_host *preresolved;
+ /* preresolved and cached host names */
+ struct cached_dns_entry *dns_cache;
/* persist crypto sequence number to/from file */
struct packet_id_persist pid_persist;
diff --git a/openvpn/src/openvpn/options.c b/openvpn/src/openvpn/options.c
index 07a9b896..26d5aec7 100644
--- a/openvpn/src/openvpn/options.c
+++ b/openvpn/src/openvpn/options.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2013 OpenVPN Technologies, Inc. <sales@openvpn.net>
* Copyright (C) 2008-2013 David Sommerseth <dazo@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
@@ -2604,6 +2604,44 @@ check_file_access(const int type, const char *file, const int mode, const char *
return (errcode != 0 ? true : false);
}
+/* A wrapper for check_file_access() which also takes a chroot directory.
+ * If chroot is NULL, behaviour is exactly the same as calling check_file_access() directly,
+ * otherwise it will look for the file inside the given chroot directory instead.
+ */
+static bool
+check_file_access_chroot(const char *chroot, const int type, const char *file, const int mode, const char *opt)
+{
+ bool ret = false;
+
+ /* If no file configured, no errors to look for */
+ if (!file)
+ return false;
+
+ /* If chroot is set, look for the file/directory inside the chroot */
+ if( chroot )
+ {
+ struct gc_arena gc = gc_new();
+ struct buffer chroot_file;
+ int len = 0;
+
+ /* Build up a new full path including chroot directory */
+ len = strlen(chroot) + strlen(PATH_SEPARATOR_STR) + strlen(file) + 1;
+ chroot_file = alloc_buf_gc(len, &gc);
+ buf_printf(&chroot_file, "%s%s%s", chroot, PATH_SEPARATOR_STR, file);
+ ASSERT (chroot_file.len > 0);
+
+ ret = check_file_access(type, BSTR(&chroot_file), mode, opt);
+ gc_free(&gc);
+ }
+ else
+ {
+ /* No chroot in play, just call core file check function */
+ ret = check_file_access(type, file, mode, opt);
+ }
+ return ret;
+}
+
+
/*
* Verifies that the path in the "command" that comes after certain script options (e.g., --up) is a
* valid file with appropriate permissions.
@@ -2621,7 +2659,7 @@ check_file_access(const int type, const char *file, const int mode, const char *
* check_file_access() arguments.
*/
static bool
-check_cmd_access(const char *command, const char *opt)
+check_cmd_access(const char *command, const char *opt, const char *chroot)
{
struct argv argv;
bool return_code;
@@ -2640,7 +2678,7 @@ check_cmd_access(const char *command, const char *opt)
* only requires X_OK to function on Unix - a scenario not unlikely to
* be seen on suid binaries.
*/
- return_code = check_file_access(CHKACC_FILE, argv.argv[0], X_OK, opt);
+ return_code = check_file_access_chroot(chroot, CHKACC_FILE, argv.argv[0], X_OK, opt);
else
{
msg (M_NOPREFIX|M_OPTERR, "%s fails with '%s': No path to executable.",
@@ -2666,7 +2704,7 @@ options_postprocess_filechecks (struct options *options)
#ifdef ENABLE_SSL
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->dh_file, R_OK, "--dh");
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->ca_file, R_OK, "--ca");
- errs |= check_file_access (CHKACC_FILE, options->ca_path, R_OK, "--capath");
+ errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->ca_path, R_OK, "--capath");
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->cert_file, R_OK, "--cert");
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->extra_certs_file, R_OK,
"--extra-certs");
@@ -2679,10 +2717,10 @@ options_postprocess_filechecks (struct options *options)
"--pkcs12");
if (options->ssl_flags & SSLF_CRL_VERIFY_DIR)
- errs |= check_file_access (CHKACC_FILE, options->crl_file, R_OK|X_OK,
+ errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->crl_file, R_OK|X_OK,
"--crl-verify directory");
else
- errs |= check_file_access (CHKACC_FILE, options->crl_file, R_OK,
+ errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->crl_file, R_OK,
"--crl-verify");
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->tls_auth_file, R_OK,
@@ -2724,13 +2762,13 @@ options_postprocess_filechecks (struct options *options)
/* ** Config related ** */
#ifdef ENABLE_SSL
- errs |= check_file_access (CHKACC_FILE, options->tls_export_cert,
+ errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->tls_export_cert,
R_OK|W_OK|X_OK, "--tls-export-cert");
#endif /* ENABLE_SSL */
#if P2MP_SERVER
- errs |= check_file_access (CHKACC_FILE, options->client_config_dir,
+ errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->client_config_dir,
R_OK|X_OK, "--client-config-dir");
- errs |= check_file_access (CHKACC_FILE, options->tmp_dir,
+ errs |= check_file_access_chroot (options->chroot_dir, CHKACC_FILE, options->tmp_dir,
R_OK|W_OK|X_OK, "Temporary directory (--tmp-dir)");
#endif /* P2MP_SERVER */
@@ -3805,7 +3843,7 @@ read_config_string (const char *prefix,
{
bypass_doubledash (&p[0]);
check_inline_file_via_buf (&multiline, p, &options->gc);
- add_option (options, p, NULL, line_num, 0, msglevel, permission_mask, option_types_found, es);
+ add_option (options, p, prefix, line_num, 0, msglevel, permission_mask, option_types_found, es);
}
CLEAR (p);
}
@@ -3925,27 +3963,43 @@ void options_string_import (struct options *options,
#if P2MP
-#define VERIFY_PERMISSION(mask) { if (!verify_permission(p[0], file, (mask), permission_mask, option_types_found, msglevel)) goto err; }
+#define VERIFY_PERMISSION(mask) { if (!verify_permission(p[0], file, line, (mask), permission_mask, option_types_found, msglevel, options)) goto err; }
static bool
verify_permission (const char *name,
const char* file,
+ int line,
const unsigned int type,
const unsigned int allowed,
unsigned int *found,
- const int msglevel)
+ const int msglevel,
+ struct options* options)
{
if (!(type & allowed))
{
msg (msglevel, "option '%s' cannot be used in this context (%s)", name, file);
return false;
}
- else
+
+ if (found)
+ *found |= type;
+
+#ifndef ENABLE_SMALL
+ /* Check if this options is allowed in connection block,
+ * but we are currently not in a connection block
+ * Parsing a connection block uses a temporary options struct without
+ * connection_list
+ */
+
+ if ((type & OPT_P_CONNECTION) && options->connection_list)
{
- if (found)
- *found |= type;
- return true;
+ if (file)
+ msg (M_WARN, "Option '%s' in %s:%d is ignored by previous <connection> blocks ", name, file, line);
+ else
+ msg (M_WARN, "Option '%s' is ignored by previous <connection> blocks", name);
}
+#endif
+ return true;
}
#else
@@ -3995,7 +4049,8 @@ static void
set_user_script (struct options *options,
const char **script,
const char *new_script,
- const char *type)
+ const char *type,
+ bool in_chroot)
{
if (*script) {
msg (M_WARN, "Multiple --%s scripts defined. "
@@ -4010,8 +4065,9 @@ set_user_script (struct options *options,
openvpn_snprintf (script_name, sizeof(script_name),
"--%s script", type);
- if (check_cmd_access (*script, script_name))
+ if (check_cmd_access (*script, script_name, (in_chroot ? options->chroot_dir : NULL)))
msg (M_USAGE, "Please correct this error.");
+
}
#endif
}
@@ -4516,7 +4572,7 @@ add_option (struct options *options,
set_user_script (options,
&options->ipchange,
string_substitute (p[1], ',', ' ', &options->gc),
- "ipchange");
+ "ipchange", true);
}
else if (streq (p[0], "float"))
{
@@ -4562,14 +4618,14 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- set_user_script (options, &options->up_script, p[1], "up");
+ set_user_script (options, &options->up_script, p[1], "up", false);
}
else if (streq (p[0], "down") && p[1])
{
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- set_user_script (options, &options->down_script, p[1], "down");
+ set_user_script (options, &options->down_script, p[1], "down", true);
}
else if (streq (p[0], "down-pre"))
{
@@ -5250,7 +5306,7 @@ add_option (struct options *options,
VERIFY_PERMISSION (OPT_P_SCRIPT);
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
- set_user_script (options, &options->route_script, p[1], "route-up");
+ set_user_script (options, &options->route_script, p[1], "route-up", false);
}
else if (streq (p[0], "route-pre-down") && p[1])
{
@@ -5260,7 +5316,7 @@ add_option (struct options *options,
set_user_script (options,
&options->route_predown_script,
p[1],
- "route-pre-down");
+ "route-pre-down", true);
}
else if (streq (p[0], "route-noexec"))
{
@@ -5629,7 +5685,7 @@ add_option (struct options *options,
}
set_user_script (options,
&options->auth_user_pass_verify_script,
- p[1], "auth-user-pass-verify");
+ p[1], "auth-user-pass-verify", true);
}
else if (streq (p[0], "client-connect") && p[1])
{
@@ -5637,7 +5693,7 @@ add_option (struct options *options,
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
set_user_script (options, &options->client_connect_script,
- p[1], "client-connect");
+ p[1], "client-connect", true);
}
else if (streq (p[0], "client-disconnect") && p[1])
{
@@ -5645,7 +5701,7 @@ add_option (struct options *options,
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
set_user_script (options, &options->client_disconnect_script,
- p[1], "client-disconnect");
+ p[1], "client-disconnect", true);
}
else if (streq (p[0], "learn-address") && p[1])
{
@@ -5653,7 +5709,7 @@ add_option (struct options *options,
if (!no_more_than_n_args (msglevel, p, 2, NM_QUOTE_HINT))
goto err;
set_user_script (options, &options->learn_address_script,
- p[1], "learn-address");
+ p[1], "learn-address", true);
}
else if (streq (p[0], "tmp-dir") && p[1])
{
@@ -6604,7 +6660,7 @@ add_option (struct options *options,
goto err;
set_user_script (options, &options->tls_verify,
string_substitute (p[1], ',', ' ', &options->gc),
- "tls-verify");
+ "tls-verify", true);
}
#ifndef ENABLE_CRYPTO_POLARSSL
else if (streq (p[0], "tls-export-cert") && p[1])
diff --git a/openvpn/src/openvpn/pkcs11_openssl.c b/openvpn/src/openvpn/pkcs11_openssl.c
index af843b7b..87eb166e 100644
--- a/openvpn/src/openvpn/pkcs11_openssl.c
+++ b/openvpn/src/openvpn/pkcs11_openssl.c
@@ -49,7 +49,7 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate,
int ret = 1;
X509 *x509 = NULL;
- RSA *rsa = NULL;
+ EVP_PKEY *evp = NULL;
pkcs11h_openssl_session_t openssl_session = NULL;
if ((openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL)
@@ -63,9 +63,9 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate,
*/
certificate = NULL;
- if ((rsa = pkcs11h_openssl_session_getRSA (openssl_session)) == NULL)
+ if ((evp = pkcs11h_openssl_session_getEVP (openssl_session)) == NULL)
{
- msg (M_WARN, "PKCS#11: Unable get rsa object");
+ msg (M_WARN, "PKCS#11: Unable get evp object");
goto cleanup;
}
@@ -75,7 +75,7 @@ pkcs11_init_tls_session(pkcs11h_certificate_t certificate,
goto cleanup;
}
- if (!SSL_CTX_use_RSAPrivateKey (ssl_ctx->ctx, rsa))
+ if (!SSL_CTX_use_PrivateKey (ssl_ctx->ctx, evp))
{
msg (M_WARN, "PKCS#11: Cannot set private key for openssl");
goto cleanup;
@@ -108,10 +108,10 @@ cleanup:
x509 = NULL;
}
- if (rsa != NULL)
+ if (evp != NULL)
{
- RSA_free (rsa);
- rsa = NULL;
+ EVP_PKEY_free (evp);
+ evp = NULL;
}
if (openssl_session != NULL)
diff --git a/openvpn/src/openvpn/proxy.c b/openvpn/src/openvpn/proxy.c
index 53cd1cda..f7f06487 100644
--- a/openvpn/src/openvpn/proxy.c
+++ b/openvpn/src/openvpn/proxy.c
@@ -478,8 +478,6 @@ http_proxy_new (const struct http_proxy_options *o)
msg (M_FATAL, "Sorry, this version of " PACKAGE_NAME " was built without NTLM Proxy support.");
#endif
- p->preresoveld_proxy = o->preresolved_proxy;
-
p->defined = true;
return p;
}
diff --git a/openvpn/src/openvpn/proxy.h b/openvpn/src/openvpn/proxy.h
index cea910cf..0e7a6dfb 100644
--- a/openvpn/src/openvpn/proxy.h
+++ b/openvpn/src/openvpn/proxy.h
@@ -59,7 +59,6 @@ struct http_proxy_options {
const char *auth_file;
const char *http_version;
const char *user_agent;
- struct addrinfo *preresolved_proxy;
struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER];
};
@@ -74,7 +73,6 @@ struct http_proxy_info {
int auth_method;
struct http_proxy_options options;
struct user_pass up;
- struct addrinfo* preresoveld_proxy;
char *proxy_authenticate;
bool queried_creds;
};
diff --git a/openvpn/src/openvpn/socket.c b/openvpn/src/openvpn/socket.c
index e88148a0..716512df 100644
--- a/openvpn/src/openvpn/socket.c
+++ b/openvpn/src/openvpn/socket.c
@@ -130,20 +130,20 @@ streqnull (const char* a, const char* b)
}
static int
-get_preresolved_host (struct preresovled_host* preresolved,
+get_cached_dns_entry (struct cached_dns_entry* dns_cache,
const char* hostname,
const char* servname,
int ai_family,
int resolve_flags,
struct addrinfo **ai)
{
- struct preresovled_host *ph;
+ struct cached_dns_entry *ph;
int flags;
/* Only use flags that are relevant for the structure */
- flags = resolve_flags & GETADDR_PRERESOLVE_MASK;
+ flags = resolve_flags & GETADDR_CACHE_MASK;
- for (ph = preresolved; ph ; ph = ph->next)
+ for (ph = dns_cache; ph ; ph = ph->next)
{
if (streqnull (ph->hostname, hostname) &&
streqnull (ph->servname, servname) &&
@@ -166,7 +166,7 @@ do_preresolve_host (struct context *c,
const int flags)
{
struct addrinfo *ai;
- if (get_preresolved_host(c->c1.preresolved,
+ if (get_cached_dns_entry(c->c1.dns_cache,
hostname,
servname,
af,
@@ -179,19 +179,19 @@ do_preresolve_host (struct context *c,
af, &ai);
if (status == 0)
{
- struct preresovled_host *ph;
+ struct cached_dns_entry *ph;
- ALLOC_OBJ_CLEAR_GC (ph, struct preresovled_host, &c->gc);
+ ALLOC_OBJ_CLEAR_GC (ph, struct cached_dns_entry, &c->gc);
ph->ai = ai;
ph->hostname = hostname;
ph->servname = servname;
- ph->flags = flags & GETADDR_PRERESOLVE_MASK;
+ ph->flags = flags & GETADDR_CACHE_MASK;
- if (!c->c1.preresolved)
- c->c1.preresolved = ph;
+ if (!c->c1.dns_cache)
+ c->c1.dns_cache = ph;
else
{
- struct preresovled_host *prev = c->c1.preresolved;
+ struct cached_dns_entry *prev = c->c1.dns_cache;
while (prev->next)
prev = prev->next;
prev->next = ph;
@@ -204,13 +204,13 @@ do_preresolve_host (struct context *c,
}
else
{
- /* already in preresolved list, return success */
+ /* already in cached dns list, return success */
return 0;
}
}
void
-do_preresolve(struct context *c)
+do_preresolve (struct context *c)
{
int i;
struct connection_list *l = c->options.connection_list;
@@ -220,67 +220,69 @@ do_preresolve(struct context *c)
GETADDR_FATAL;
- for (i = 0; i < l->len; ++i) {
- int status;
- const char *remote;
- int flags = preresolve_flags;
+ for (i = 0; i < l->len; ++i)
+ {
+ int status;
+ const char *remote;
+ int flags = preresolve_flags;
- struct connection_entry* ce = c->options.connection_list->array[i];
+ struct connection_entry* ce = c->options.connection_list->array[i];
- if (proto_is_dgram(ce->proto))
- flags |= GETADDR_DATAGRAM;
+ if (proto_is_dgram(ce->proto))
+ flags |= GETADDR_DATAGRAM;
- if (c->options.sockflags & SF_HOST_RANDOMIZE)
- flags |= GETADDR_RANDOMIZE;
+ if (c->options.sockflags & SF_HOST_RANDOMIZE)
+ flags |= GETADDR_RANDOMIZE;
- if (c->options.ip_remote_hint)
- remote = c->options.ip_remote_hint;
- else
- remote = ce->remote;
+ if (c->options.ip_remote_hint)
+ remote = c->options.ip_remote_hint;
+ else
+ remote = ce->remote;
- /* HTTP remote hostname does not need to be resolved */
- if (! ce->http_proxy_options)
- {
- status = do_preresolve_host (c, remote, ce->remote_port, ce->af, flags);
- if (status != 0)
- goto err;
- }
+ /* HTTP remote hostname does not need to be resolved */
+ if (! ce->http_proxy_options)
+ {
+ status = do_preresolve_host (c, remote, ce->remote_port, ce->af, flags);
+ if (status != 0)
+ goto err;
+ }
- flags |= GETADDR_PASSIVE;
+ /* Preresolve proxy */
+ if (ce->http_proxy_options)
+ {
+ status = do_preresolve_host (c,
+ ce->http_proxy_options->server,
+ ce->http_proxy_options->port,
+ ce->af,
+ preresolve_flags);
+
+ if (status != 0)
+ goto err;
+ }
- if (ce->bind_local)
- {
- status = do_preresolve_host (c, ce->local, ce->local_port, ce->af, flags);
- if (status != 0)
- goto err;
+ if (ce->socks_proxy_server)
+ {
+ status = do_preresolve_host (c,
+ ce->socks_proxy_server,
+ ce->socks_proxy_port,
+ ce->af,
+ flags);
+ if (status != 0)
+ goto err;
+ }
- }
- /* Preresolve proxy */
- if (ce->http_proxy_options)
- {
- status = do_preresolve_host(c,
- ce->http_proxy_options->server,
- ce->http_proxy_options->port,
- ce->af,
- preresolve_flags);
-
- if (status != 0)
- goto err;
- }
+ if (ce->bind_local)
+ {
+ flags |= GETADDR_PASSIVE;
+ flags &= ~GETADDR_RANDOMIZE;
+ status = do_preresolve_host (c, ce->local, ce->local_port, ce->af, flags);
+ if (status != 0)
+ goto err;
- if (ce->socks_proxy_server)
- {
- status = do_preresolve_host (c,
- ce->socks_proxy_server,
- ce->socks_proxy_port,
- ce->af,
- flags);
- if (status != 0)
- goto err;
- }
+ }
- }
- return;
+ }
+ return;
err:
throw_signal_soft (SIGHUP, "Preresolving failed");
@@ -1083,8 +1085,9 @@ socket_bind (socket_descriptor_t sd,
if (ai_family == AF_INET6)
{
- int v6only = ipv6only ? 0: 1; /* setsockopt must have an "int" */
+ int v6only = ipv6only ? 1: 0; /* setsockopt must have an "int" */
+ msg (M_INFO, "setsockopt(IPV6_V6ONLY=%d)", v6only);
if (setsockopt(sd, IPPROTO_IPV6, IPV6_V6ONLY, &v6only, sizeof(v6only)))
{
msg (M_NONFATAL|M_ERRNO, "Setting IPV6_V6ONLY=%d failed", v6only);
@@ -1322,7 +1325,7 @@ resolve_bind_local (struct link_socket *sock, const sa_family_t af)
flags |= GETADDR_DATAGRAM;
/* will return AF_{INET|INET6}from local_host */
- status = get_preresolved_host (sock->preresolved,
+ status = get_cached_dns_entry (sock->dns_cache,
sock->local_host,
sock->local_port,
af,
@@ -1416,7 +1419,7 @@ resolve_remote (struct link_socket *sock,
}
- status = get_preresolved_host (sock->preresolved,
+ status = get_cached_dns_entry (sock->dns_cache,
sock->remote_host,
sock->remote_port,
sock->info.af,
@@ -1441,12 +1444,12 @@ resolve_remote (struct link_socket *sock,
if (*signal_received)
goto done;
}
- if (status!=0)
- {
- if (signal_received)
- *signal_received = SIGUSR1;
- goto done;
- }
+ if (status!=0)
+ {
+ if (signal_received)
+ *signal_received = SIGUSR1;
+ goto done;
+ }
}
}
@@ -1458,15 +1461,15 @@ resolve_remote (struct link_socket *sock,
if (remote_dynamic)
*remote_dynamic = NULL;
}
- /* else, quick hack to fix persistent-remote ....*/
- {
- CLEAR (sock->info.lsa->actual);
- if(sock->info.lsa->current_remote)
- {
- set_actual_address (&sock->info.lsa->actual,
- sock->info.lsa->current_remote);
- }
- }
+ else
+ {
+ CLEAR (sock->info.lsa->actual);
+ if(sock->info.lsa->current_remote)
+ {
+ set_actual_address (&sock->info.lsa->actual,
+ sock->info.lsa->current_remote);
+ }
+ }
done:
gc_free (&gc);
@@ -1506,21 +1509,10 @@ create_new_socket (struct link_socket* sock)
/* clear destination set by set_actual_address */
CLEAR(sock->info.lsa->actual.dest);
}
-
- /*
- * Create the socket early if socket should be bound
- */
- if (sock->bind_local)
- {
- create_socket (sock);
-
- if (sock->bind_local)
- bind_local(sock);
- }
-
}
+
/* bind socket if necessary */
void
link_socket_init_phase1 (struct link_socket *sock,
@@ -1528,7 +1520,7 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *local_port,
const char *remote_host,
const char *remote_port,
- struct preresovled_host *preresolved,
+ struct cached_dns_entry *dns_cache,
int proto,
sa_family_t af,
bool bind_ipv6_only,
@@ -1563,7 +1555,7 @@ link_socket_init_phase1 (struct link_socket *sock,
sock->local_port = local_port;
sock->remote_host = remote_host;
sock->remote_port = remote_port;
- sock->preresolved = preresolved;
+ sock->dns_cache = dns_cache;
#ifdef ENABLE_HTTP_PROXY
sock->http_proxy = http_proxy;
@@ -1742,6 +1734,7 @@ linksock_print_addr (struct link_socket *sock)
struct gc_arena gc = gc_new ();
const int msglevel = (sock->mode == LS_MODE_TCP_ACCEPT_FROM) ? D_INIT_MEDIUM : M_INFO;
+ /* print local address */
if (sock->inetd)
msg (msglevel, "%s link local: [inetd]", proto2ascii (sock->info.proto, sock->info.af, true));
else if (sock->bind_local)
@@ -1942,6 +1935,17 @@ link_socket_init_phase2 (struct link_socket *sock,
/* If socket has not already been created create it now */
if (sock->sd == SOCKET_UNDEFINED)
{
+ /* If we have no --remote and have still not figured out the
+ * protocol family to use we will use the first of the bind */
+ if (sock->bind_local && sock->info.lsa->bind_local
+ && !sock->info.lsa->actual.ai_family && !sock->remote_host)
+ {
+ msg (M_WARN, "Could not determine IPv4/IPv6 protocol. Using %s",
+ addr_family_name(sock->info.lsa->bind_local->ai_family));
+ set_actual_address(&sock->info.lsa->actual, sock->info.lsa->bind_local);
+
+ }
+
if (sock->info.lsa->actual.ai_family)
{
create_socket (sock);
diff --git a/openvpn/src/openvpn/socket.h b/openvpn/src/openvpn/socket.h
index 7c0b040c..8d4316ba 100644
--- a/openvpn/src/openvpn/socket.h
+++ b/openvpn/src/openvpn/socket.h
@@ -78,13 +78,13 @@ struct openvpn_sockaddr
};
/* struct to hold preresolved host names */
-struct preresovled_host {
+struct cached_dns_entry {
const char *hostname;
const char *servname;
int ai_family;
int flags;
struct addrinfo *ai;
- struct preresovled_host *next;
+ struct cached_dns_entry *next;
};
/* actual address of remote, based on source address of received packets */
@@ -198,7 +198,7 @@ struct link_socket
const char *remote_port;
const char *local_host;
const char *local_port;
- struct preresovled_host *preresolved;
+ struct cached_dns_entry *dns_cache;
bool bind_local;
# define INETD_NONE 0
@@ -319,7 +319,7 @@ link_socket_init_phase1 (struct link_socket *sock,
const char *local_port,
const char *remote_host,
const char *remote_port,
- struct preresovled_host *preresolved,
+ struct cached_dns_entry *dns_cache,
int proto,
sa_family_t af,
bool bind_ipv6_only,
@@ -528,7 +528,7 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *
#define GETADDR_PASSIVE (1<<10)
#define GETADDR_DATAGRAM (1<<11)
-#define GETADDR_PRERESOLVE_MASK GETADDR_DATAGRAM|GETADDR_PASSIVE
+#define GETADDR_CACHE_MASK GETADDR_DATAGRAM|GETADDR_PASSIVE
in_addr_t getaddr (unsigned int flags,
const char *hostname,
diff --git a/openvpn/src/openvpn/ssl.c b/openvpn/src/openvpn/ssl.c
index bd19d754..93222c47 100644
--- a/openvpn/src/openvpn/ssl.c
+++ b/openvpn/src/openvpn/ssl.c
@@ -543,10 +543,7 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx)
}
/* Allowable ciphers */
- if (options->cipher_list)
- {
- tls_ctx_restrict_ciphers(new_ctx, options->cipher_list);
- }
+ tls_ctx_restrict_ciphers(new_ctx, options->cipher_list);
#ifdef ENABLE_CRYPTO_POLARSSL
/* Personalise the random by mixing in the certificate */
diff --git a/openvpn/src/openvpn/ssl_backend.h b/openvpn/src/openvpn/ssl_backend.h
index 07cb9abc..a6fc3bdb 100644
--- a/openvpn/src/openvpn/ssl_backend.h
+++ b/openvpn/src/openvpn/ssl_backend.h
@@ -167,8 +167,9 @@ void tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags);
/**
* Restrict the list of ciphers that can be used within the TLS context.
*
- * @param ctx TLS context to restrict
- * @param ciphers String containing : delimited cipher names.
+ * @param ctx TLS context to restrict, must be valid.
+ * @param ciphers String containing : delimited cipher names, or NULL to use
+ * sane defaults.
*/
void tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers);
@@ -454,8 +455,10 @@ void print_details (struct key_state_ssl * ks_ssl, const char *prefix);
/*
* Show the TLS ciphers that are available for us to use in the OpenSSL
* library.
+ *
+ * @param - list of allowed TLS cipher, or NULL.
*/
-void show_available_tls_ciphers ();
+void show_available_tls_ciphers (const char *tls_ciphers);
/*
* The OpenSSL library has a notion of preference in TLS ciphers. Higher
diff --git a/openvpn/src/openvpn/ssl_openssl.c b/openvpn/src/openvpn/ssl_openssl.c
index f41bb711..9dced724 100644
--- a/openvpn/src/openvpn/ssl_openssl.c
+++ b/openvpn/src/openvpn/ssl_openssl.c
@@ -93,22 +93,6 @@ tls_clear_error()
ERR_clear_error ();
}
-/*
- * OpenSSL callback to get a temporary RSA key, mostly
- * used for export ciphers.
- */
-static RSA *
-tmp_rsa_cb (SSL * s, int is_export, int keylength)
-{
- static RSA *rsa_tmp = NULL;
- if (rsa_tmp == NULL)
- {
- msg (D_HANDSHAKE, "Generating temp (%d bit) RSA key", keylength);
- rsa_tmp = RSA_generate_key (keylength, RSA_F4, NULL, NULL);
- }
- return (rsa_tmp);
-}
-
void
tls_ctx_server_new(struct tls_root_ctx *ctx)
{
@@ -117,9 +101,7 @@ tls_ctx_server_new(struct tls_root_ctx *ctx)
ctx->ctx = SSL_CTX_new (SSLv23_server_method ());
if (ctx->ctx == NULL)
- msg (M_SSLERR, "SSL_CTX_new TLSv1_server_method");
-
- SSL_CTX_set_tmp_rsa_callback (ctx->ctx, tmp_rsa_cb);
+ msg (M_SSLERR, "SSL_CTX_new SSLv23_server_method");
}
void
@@ -130,7 +112,7 @@ tls_ctx_client_new(struct tls_root_ctx *ctx)
ctx->ctx = SSL_CTX_new (SSLv23_client_method ());
if (ctx->ctx == NULL)
- msg (M_SSLERR, "SSL_CTX_new TLSv1_client_method");
+ msg (M_SSLERR, "SSL_CTX_new SSLv23_client_method");
}
void
@@ -235,71 +217,93 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags)
void
tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)
{
- size_t begin_of_cipher, end_of_cipher;
-
- const char *current_cipher;
- size_t current_cipher_len;
+ if (ciphers == NULL)
+ {
+ /* Use sane default */
+ if(!SSL_CTX_set_cipher_list(ctx->ctx, "DEFAULT:!EXP"))
+ msg(M_SSLERR, "Failed to set default TLS cipher list.");
+ return;
+ }
+ else
+ {
+ /* Parse supplied cipher list and pass on to OpenSSL */
+ size_t begin_of_cipher, end_of_cipher;
- const tls_cipher_name_pair *cipher_pair;
+ const char *current_cipher;
+ size_t current_cipher_len;
- char openssl_ciphers[4096];
- size_t openssl_ciphers_len = 0;
- openssl_ciphers[0] = '\0';
+ const tls_cipher_name_pair *cipher_pair;
- ASSERT(NULL != ctx);
+ char openssl_ciphers[4096];
+ size_t openssl_ciphers_len = 0;
+ openssl_ciphers[0] = '\0';
- // Translate IANA cipher suite names to OpenSSL names
- begin_of_cipher = end_of_cipher = 0;
- for (; begin_of_cipher < strlen(ciphers); begin_of_cipher = end_of_cipher) {
- end_of_cipher += strcspn(&ciphers[begin_of_cipher], ":");
- cipher_pair = tls_get_cipher_name_pair(&ciphers[begin_of_cipher], end_of_cipher - begin_of_cipher);
+ ASSERT(NULL != ctx);
- if (NULL == cipher_pair)
+ // Translate IANA cipher suite names to OpenSSL names
+ begin_of_cipher = end_of_cipher = 0;
+ for (; begin_of_cipher < strlen(ciphers); begin_of_cipher = end_of_cipher)
{
- // No translation found, use original
- current_cipher = &ciphers[begin_of_cipher];
- current_cipher_len = end_of_cipher - begin_of_cipher;
-
- // Issue warning on missing translation
- // %.*s format specifier expects length of type int, so guarantee
- // that length is small enough and cast to int.
- msg (M_WARN, "No valid translation found for TLS cipher '%.*s'",
- constrain_int(current_cipher_len, 0, 256), current_cipher);
- }
- else
- {
- // Use OpenSSL name
- current_cipher = cipher_pair->openssl_name;
- current_cipher_len = strlen(current_cipher);
+ end_of_cipher += strcspn(&ciphers[begin_of_cipher], ":");
+ cipher_pair = tls_get_cipher_name_pair(&ciphers[begin_of_cipher],
+ end_of_cipher - begin_of_cipher);
- if (end_of_cipher - begin_of_cipher == current_cipher_len &&
- 0 == memcmp (&ciphers[begin_of_cipher], cipher_pair->openssl_name, end_of_cipher - begin_of_cipher))
- {
- // Non-IANA name used, show warning
- msg (M_WARN, "Deprecated TLS cipher name '%s', please use IANA name '%s'", cipher_pair->openssl_name, cipher_pair->iana_name);
- }
- }
-
- // Make sure new cipher name fits in cipher string
- 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
- memcpy(&openssl_ciphers[openssl_ciphers_len], current_cipher, current_cipher_len);
- openssl_ciphers_len += current_cipher_len;
- openssl_ciphers[openssl_ciphers_len] = ':';
- openssl_ciphers_len++;
+ if (NULL == cipher_pair)
+ {
+ // No translation found, use original
+ current_cipher = &ciphers[begin_of_cipher];
+ current_cipher_len = end_of_cipher - begin_of_cipher;
+
+ // Issue warning on missing translation
+ // %.*s format specifier expects length of type int, so guarantee
+ // that length is small enough and cast to int.
+ msg (M_WARN, "No valid translation found for TLS cipher '%.*s'",
+ constrain_int(current_cipher_len, 0, 256), current_cipher);
+ }
+ else
+ {
+ // Use OpenSSL name
+ current_cipher = cipher_pair->openssl_name;
+ current_cipher_len = strlen(current_cipher);
+
+ if (end_of_cipher - begin_of_cipher == current_cipher_len &&
+ 0 == memcmp (&ciphers[begin_of_cipher],
+ cipher_pair->openssl_name,
+ end_of_cipher - begin_of_cipher))
+ {
+ // Non-IANA name used, show warning
+ msg (M_WARN, "Deprecated TLS cipher name '%s', "
+ "please use IANA name '%s'", cipher_pair->openssl_name,
+ cipher_pair->iana_name);
+ }
+ }
- end_of_cipher++;
- }
+ // Make sure new cipher name fits in cipher string
+ 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
+ memcpy(&openssl_ciphers[openssl_ciphers_len], current_cipher,
+ current_cipher_len);
+ openssl_ciphers_len += current_cipher_len;
+ openssl_ciphers[openssl_ciphers_len] = ':';
+ openssl_ciphers_len++;
+
+ end_of_cipher++;
+ }
- if (openssl_ciphers_len > 0)
- openssl_ciphers[openssl_ciphers_len-1] = '\0';
+ if (openssl_ciphers_len > 0)
+ openssl_ciphers[openssl_ciphers_len-1] = '\0';
- // Set OpenSSL cipher list
- if(!SSL_CTX_set_cipher_list(ctx->ctx, openssl_ciphers))
- msg(M_SSLERR, "Failed to set restricted TLS cipher list: %s", openssl_ciphers);
+ // Set OpenSSL cipher list
+ if(!SSL_CTX_set_cipher_list(ctx->ctx, openssl_ciphers))
+ msg(M_SSLERR, "Failed to set restricted TLS cipher list: %s",
+ openssl_ciphers);
+ }
}
void
@@ -1274,22 +1278,25 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix)
}
void
-show_available_tls_ciphers ()
+show_available_tls_ciphers (const char *cipher_list)
{
- SSL_CTX *ctx;
+ struct tls_root_ctx tls_ctx;
SSL *ssl;
const char *cipher_name;
const tls_cipher_name_pair *pair;
int priority = 0;
- ctx = SSL_CTX_new (TLSv1_method ());
- if (!ctx)
+ tls_ctx.ctx = SSL_CTX_new (SSLv23_method ());
+ if (!tls_ctx.ctx)
msg (M_SSLERR, "Cannot create SSL_CTX object");
- ssl = SSL_new (ctx);
+ ssl = SSL_new (tls_ctx.ctx);
if (!ssl)
msg (M_SSLERR, "Cannot create SSL object");
+ if (cipher_list)
+ tls_ctx_restrict_ciphers(&tls_ctx, cipher_list);
+
printf ("Available TLS Ciphers,\n");
printf ("listed in order of preference:\n\n");
while ((cipher_name = SSL_get_cipher_list (ssl, priority++)))
@@ -1307,7 +1314,7 @@ show_available_tls_ciphers ()
printf ("\n");
SSL_free (ssl);
- SSL_CTX_free (ctx);
+ SSL_CTX_free (tls_ctx.ctx);
}
void
@@ -1317,7 +1324,7 @@ get_highest_preference_tls_cipher (char *buf, int size)
SSL *ssl;
const char *cipher_name;
- ctx = SSL_CTX_new (TLSv1_method ());
+ ctx = SSL_CTX_new (SSLv23_method ());
if (!ctx)
msg (M_SSLERR, "Cannot create SSL_CTX object");
ssl = SSL_new (ctx);
diff --git a/openvpn/src/openvpn/ssl_polarssl.c b/openvpn/src/openvpn/ssl_polarssl.c
index cdd91890..d964b918 100644
--- a/openvpn/src/openvpn/ssl_polarssl.c
+++ b/openvpn/src/openvpn/ssl_polarssl.c
@@ -173,7 +173,12 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)
{
char *tmp_ciphers, *tmp_ciphers_orig, *token;
int i, cipher_count;
- int ciphers_len = strlen (ciphers);
+ int ciphers_len;
+
+ if (NULL == ciphers)
+ return; // Nothing to do
+
+ ciphers_len = strlen (ciphers);
ASSERT (NULL != ctx);
ASSERT (0 != ciphers_len);
@@ -1033,10 +1038,16 @@ print_details (struct key_state_ssl * ks_ssl, const char *prefix)
}
void
-show_available_tls_ciphers ()
+show_available_tls_ciphers (const char *cipher_list)
{
+ struct tls_root_ctx tls_ctx;
const int *ciphers = ssl_list_ciphersuites();
+ if (cipher_list) {
+ tls_ctx_restrict_ciphers(&tls_ctx, cipher_list);
+ ciphers = tls_ctx.allowed_ciphers;
+ }
+
#ifndef ENABLE_SMALL
printf ("Available TLS Ciphers,\n");
printf ("listed in order of preference:\n\n");
diff --git a/openvpn/src/openvpn/win32.c b/openvpn/src/openvpn/win32.c
index 022eec5c..f35c96be 100644
--- a/openvpn/src/openvpn/win32.c
+++ b/openvpn/src/openvpn/win32.c
@@ -996,19 +996,27 @@ set_win_sys_path_via_env (struct env_set *es)
const char *
win_get_tempdir()
{
- static char buf[MAX_PATH];
- char *tmpdir = buf;
-
- CLEAR(buf);
-
- if (!GetTempPath(sizeof(buf),buf)) {
- /* Warn if we can't find a valid temporary directory, which should
- * be unlikely.
- */
- msg (M_WARN, "Could not find a suitable temporary directory."
- " (GetTempPath() failed). Consider to use --tmp-dir");
- tmpdir = NULL;
- }
+ static char tmpdir[MAX_PATH];
+ WCHAR wtmpdir[MAX_PATH];
+
+ if (!GetTempPathW(_countof(wtmpdir), wtmpdir))
+ {
+ /* Warn if we can't find a valid temporary directory, which should
+ * be unlikely.
+ */
+ msg (M_WARN, "Could not find a suitable temporary directory."
+ " (GetTempPath() failed). Consider using --tmp-dir");
+ return NULL;
+ }
+
+ if (WideCharToMultiByte (CP_UTF8, 0, wtmpdir, -1, NULL, 0, NULL, NULL) > sizeof (tmpdir))
+ {
+ msg (M_WARN, "Could not get temporary directory. Path is too long."
+ " Consider using --tmp-dir");
+ return NULL;
+ }
+
+ WideCharToMultiByte (CP_UTF8, 0, wtmpdir, -1, tmpdir, sizeof (tmpdir), NULL, NULL);
return tmpdir;
}
#endif