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 | 
