diff options
Diffstat (limited to 'openvpn/src')
-rw-r--r-- | openvpn/src/compat/compat-rsa_generate_key.c | 49 | ||||
-rw-r--r-- | openvpn/src/openvpn/buffer.h | 2 | ||||
-rw-r--r-- | openvpn/src/openvpn/init.c | 21 | ||||
-rw-r--r-- | openvpn/src/openvpn/openvpn.h | 4 | ||||
-rw-r--r-- | openvpn/src/openvpn/options.c | 112 | ||||
-rw-r--r-- | openvpn/src/openvpn/pkcs11_openssl.c | 14 | ||||
-rw-r--r-- | openvpn/src/openvpn/proxy.c | 2 | ||||
-rw-r--r-- | openvpn/src/openvpn/proxy.h | 2 | ||||
-rw-r--r-- | openvpn/src/openvpn/socket.c | 196 | ||||
-rw-r--r-- | openvpn/src/openvpn/socket.h | 10 | ||||
-rw-r--r-- | openvpn/src/openvpn/ssl.c | 5 | ||||
-rw-r--r-- | openvpn/src/openvpn/ssl_backend.h | 9 | ||||
-rw-r--r-- | openvpn/src/openvpn/ssl_openssl.c | 171 | ||||
-rw-r--r-- | openvpn/src/openvpn/ssl_polarssl.c | 15 | ||||
-rw-r--r-- | openvpn/src/openvpn/win32.c | 34 |
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 |