diff options
24 files changed, 505 insertions, 104 deletions
diff --git a/main/openvpn/config-version.h b/main/openvpn/config-version.h index b9bd0a00..762b9dc6 100644 --- a/main/openvpn/config-version.h +++ b/main/openvpn/config-version.h @@ -1,2 +1,2 @@ -#define CONFIGURE_GIT_REVISION "icsopenvpn_615-c430ab0e0cef9994" -#define CONFIGURE_GIT_FLAGS "+" +#define CONFIGURE_GIT_REVISION "icsopenvpn_618-e63b88d330782d14" +#define CONFIGURE_GIT_FLAGS "" diff --git a/main/openvpn/configure.ac b/main/openvpn/configure.ac index cb7a5d33..ffba3749 100644 --- a/main/openvpn/configure.ac +++ b/main/openvpn/configure.ac @@ -72,6 +72,13 @@ AC_ARG_ENABLE(  )  AC_ARG_ENABLE( +	[ofb-cfb], +	[AS_HELP_STRING([--enable-ofb-cfb], [enable support for OFB and CFB cipher modes @<:@default=yes@:>@])], +	, +	[enable_crypto_ofb_cfb="yes"] +) + +AC_ARG_ENABLE(  	[ssl],  	[AS_HELP_STRING([--disable-ssl], [disable SSL support for TLS-based key exchange @<:@default=yes@:>@])],  	, @@ -335,6 +342,13 @@ case "$host" in  		AC_DEFINE([TARGET_DRAGONFLY], [1], [Are we running on DragonFlyBSD?])  		AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["D"], [Target prefix])  		;; +	*-aix*) +		AC_DEFINE([TARGET_AIX], [1], [Are we running AIX?]) +		AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["A"], [Target prefix]) +		ROUTE="/usr/sbin/route" +		have_tap_header="yes" +		ac_cv_header_net_if_h="no"	# exists, but breaks things +		;;  	*)  		AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["X"], [Target prefix])  		have_tap_header="yes" @@ -786,25 +800,6 @@ if test "${have_openssl_crypto}" = "yes"; then  	LIBS="${saved_LIBS}"  fi -if test "${enable_ssl}" = "yes" && test "${with_crypto_library}" = "openssl"; -then -    saved_CPPFLAGS="${CPPFLAGS}" -    CPPFLAGS="${CPPFLAGS} ${OPENSSL_CRYPTO_CFLAGS}" -    AC_MSG_CHECKING([for SSL_OP_NO_TICKET flag in OpenSSL]) -    AC_EGREP_CPP(have_ssl_op_no_ticket, [ -    #include <openssl/ssl.h> -    #ifdef SSL_OP_NO_TICKET -    have_ssl_op_no_ticket -    #endif -    ], [ -        AC_MSG_RESULT([yes]) -    ], [ -        AC_MSG_RESULT([no]) -        AC_ERROR([OpenVPN 2.4+ requires SSL_OP_NO_TICKET in OpenSSL]) -    ]) -    CPPFLAGS="${saved_CPPFLAGS}" -fi -  AC_ARG_VAR([POLARSSL_CFLAGS], [C compiler flags for polarssl])  AC_ARG_VAR([POLARSSL_LIBS], [linker flags for polarssl])  have_polarssl_ssl="yes" @@ -1071,6 +1066,7 @@ fi  if test "${enable_crypto}" = "yes"; then  	test "${have_crypto_crypto}" != "yes" && AC_MSG_ERROR([${with_crypto_library} crypto is required but missing]) +	test "${enable_crypto_ofb_cfb}" = "yes" && AC_DEFINE([ENABLE_OFB_CFB_MODE], [1], [Enable OFB and CFB cipher modes])  	OPTIONAL_CRYPTO_CFLAGS="${OPTIONAL_CRYPTO_CFLAGS} ${CRYPTO_CRYPTO_CFLAGS}"  	OPTIONAL_CRYPTO_LIBS="${OPTIONAL_CRYPTO_LIBS} ${CRYPTO_CRYPTO_LIBS}"  	AC_DEFINE([ENABLE_CRYPTO], [1], [Enable crypto library]) diff --git a/main/openvpn/distro/rpm/openvpn.init.d.rhel b/main/openvpn/distro/rpm/openvpn.init.d.rhel index 821abd58..cdf3e9de 100755 --- a/main/openvpn/distro/rpm/openvpn.init.d.rhel +++ b/main/openvpn/distro/rpm/openvpn.init.d.rhel @@ -148,7 +148,7 @@ case "$1" in  	for c in `/bin/ls *.conf 2>/dev/null`; do  	    bn=${c%%.conf}  	    if [ -f "$bn.sh" ]; then -		. $bn.sh +		. ./$bn.sh  	    fi  	    rm -f $piddir/$bn.pid  	    $openvpn --daemon --writepid $piddir/$bn.pid --config $c --cd $work diff --git a/main/openvpn/distro/rpm/openvpn.init.d.suse b/main/openvpn/distro/rpm/openvpn.init.d.suse index 2bac7f32..270024e8 100644 --- a/main/openvpn/distro/rpm/openvpn.init.d.suse +++ b/main/openvpn/distro/rpm/openvpn.init.d.suse @@ -161,7 +161,7 @@ case "$1" in  	for c in `/bin/ls *.conf 2>/dev/null`; do  	    bn=${c%%.conf}  	    if [ -f "$bn.sh" ]; then -		. $bn.sh +		. ./$bn.sh  	    fi  	    rm -f $piddir/$bn.pid  	    $openvpn --daemon --writepid $piddir/$bn.pid --config $c --cd $work diff --git a/main/openvpn/doc/openvpn.8 b/main/openvpn/doc/openvpn.8 index 76b7bfd4..aee0bc83 100644 --- a/main/openvpn/doc/openvpn.8 +++ b/main/openvpn/doc/openvpn.8 @@ -2704,7 +2704,7 @@ on sufficiently fast hardware.  SSL/TLS authentication must  be used in this mode.  .\"*********************************************************  .TP -.B \-\-server network netmask +.B \-\-server network netmask ['nopool']  A helper directive designed to simplify the configuration  of OpenVPN's server mode.  This directive will set up an  OpenVPN server which will allocate addresses to clients @@ -2739,6 +2739,9 @@ expands as follows:     if !nopool:       ifconfig-pool 10.8.0.2 10.8.0.254 255.255.255.0     push "route-gateway 10.8.0.1" +   if route-gateway unset: +     route-gateway 10.8.0.2 +  .in -4  .ft  .fi @@ -4790,12 +4793,44 @@ the tls-verify script returns.  The file name used for the certificate  is available via the peer_cert environment variable.  .\"*********************************************************  .TP -.B \-\-x509-username-field fieldname -Field in x509 certificate subject to be used as username (default=CN). -.B Fieldname -will be uppercased before matching. When this option is used, the -.B \-\-verify-x509-username -option will match against the chosen fieldname instead of the CN. +.B \-\-x509-username-field [ext:\]fieldname +Field in the X.509 certificate subject to be used as the username (default=CN). +Typically, this option is specified with +.B fieldname +as either of the following: + +.B \-\-x509-username-field +emailAddress +.br +.B \-\-x509-username-field ext:\fRsubjectAltName + +The first example uses the value of the "emailAddress" attribute in the +certificate's Subject field as the username.  The second example uses +the +.B ext: +prefix to signify that the X.509 extension +.B fieldname +"subjectAltName" be searched for an rfc822Name (email) field to be used +as the username.  In cases where there are multiple email addresses +in +.B ext:fieldname\fR, +the last occurrence is chosen. + +When this option is used, the +.B \-\-verify-x509-name +option will match against the chosen +.B fieldname +instead of the Common Name. + +.B Please note: +This option has a feature which will convert an all-lowercase +.B fieldname +to uppercase characters, e.g., ou -> OU.  A mixed-case +.B fieldname +or one having the +.B ext: +prefix will be left as-is.  This automatic upcasing feature +is deprecated and will be removed in a future release.  .\"*********************************************************  .TP  .B \-\-tls-remote name (DEPRECATED) diff --git a/main/openvpn/sample/sample-config-files/server.conf b/main/openvpn/sample/sample-config-files/server.conf index f483b6bb..467d5b8a 100644 --- a/main/openvpn/sample/sample-config-files/server.conf +++ b/main/openvpn/sample/sample-config-files/server.conf @@ -83,9 +83,16 @@ key server.key  # This file should be kept secret  # Generate your own with:  #   openssl dhparam -out dh1024.pem 1024  # Substitute 2048 for 1024 if you are using -# 2048 bit keys.  +# 2048 bit keys.  dh dh1024.pem +# Network topology +# Should be subnet (addressing via IP) +# unless Windows clients v2.0.9 and lower have to +# be supported (then net30, i.e. a /30 per client) +# Defaults to net30 (not recommended) +;topology subnet +  # Configure server mode and supply a VPN subnet  # for OpenVPN to draw client addresses from.  # The server will take 10.8.0.1 for itself, diff --git a/main/openvpn/src/openvpn/crypto.c b/main/openvpn/src/openvpn/crypto.c index 8201708a..62c4ab28 100644 --- a/main/openvpn/src/openvpn/crypto.c +++ b/main/openvpn/src/openvpn/crypto.c @@ -100,10 +100,10 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	{  	  uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH];  	  const int iv_size = cipher_ctx_iv_length (ctx->cipher); -	  const unsigned int mode = cipher_ctx_mode (ctx->cipher); +	  const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher);  	  int outlen; -	  if (mode == OPENVPN_MODE_CBC) +	  if (cipher_kt_mode_cbc(cipher_kt))  	    {  	      CLEAR (iv_buf); @@ -119,7 +119,7 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  		  ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true));  		}  	    } -	  else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB) +	  else if (cipher_kt_mode_ofb_cfb(cipher_kt))  	    {  	      struct packet_id_net pin;  	      struct buffer b; @@ -171,7 +171,10 @@ openvpn_encrypt (struct buffer *buf, struct buffer work,  	  /* Flush the encryption buffer */  	  ASSERT(cipher_ctx_final(ctx->cipher, BPTR (&work) + outlen, &outlen));  	  work.len += outlen; -	  ASSERT (mode != OPENVPN_MODE_CBC || outlen == iv_size); + +	  /* For all CBC mode ciphers, check the last block is complete */ +	  ASSERT (cipher_kt_mode (cipher_kt) != OPENVPN_MODE_CBC || +	      outlen == iv_size);  	  /* prepend the IV to the ciphertext */  	  if (opt->flags & CO_USE_IV) @@ -272,8 +275,8 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,        if (ctx->cipher)  	{ -	  const unsigned int mode = cipher_ctx_mode (ctx->cipher);  	  const int iv_size = cipher_ctx_iv_length (ctx->cipher); +	  const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher);  	  uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH];  	  int outlen; @@ -320,7 +323,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,  	  /* Get packet ID from plaintext buffer or IV, depending on cipher mode */  	  { -	    if (mode == OPENVPN_MODE_CBC) +	    if (cipher_kt_mode_cbc(cipher_kt))  	      {  		if (opt->packet_id)  		  { @@ -329,7 +332,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work,  		    have_pin = true;  		  }  	      } -	    else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB) +	    else if (cipher_kt_mode_ofb_cfb(cipher_kt))  	      {  		struct buffer b; @@ -480,17 +483,12 @@ init_key_type (struct key_type *kt, const char *ciphername,        /* check legal cipher mode */        { -	const unsigned int mode = cipher_kt_mode (kt->cipher); -	if (!(mode == OPENVPN_MODE_CBC -#ifdef ALLOW_NON_CBC_CIPHERS -	      || (cfb_ofb_allowed && (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB)) +	if (!(cipher_kt_mode_cbc(kt->cipher) +#ifdef ENABLE_OFB_CFB_MODE +	      || (cfb_ofb_allowed && cipher_kt_mode_ofb_cfb(kt->cipher))  #endif  	      )) -#ifdef ENABLE_SMALL  	  msg (M_FATAL, "Cipher '%s' mode not supported", ciphername); -#else -	  msg (M_FATAL, "Cipher '%s' uses a mode not supported by " PACKAGE_NAME " in your current configuration.  CBC mode is always supported, while CFB and OFB modes are supported only when using SSL/TLS authentication and key exchange mode, and when " PACKAGE_NAME " has been built with ALLOW_NON_CBC_CIPHERS.", ciphername); -#endif        }      }    else @@ -660,18 +658,10 @@ fixup_key (struct key *key, const struct key_type *kt)  void  check_replay_iv_consistency (const struct key_type *kt, bool packet_id, bool use_iv)  { -  if (cfb_ofb_mode (kt) && !(packet_id && use_iv)) -    msg (M_FATAL, "--no-replay or --no-iv cannot be used with a CFB or OFB mode cipher"); -} +  ASSERT(kt); -bool -cfb_ofb_mode (const struct key_type* kt) -{ -  if (kt && kt->cipher) { -      const unsigned int mode = cipher_kt_mode (kt->cipher); -      return mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB; -  } -  return false; +  if (cipher_kt_mode_ofb_cfb(kt->cipher) && !(packet_id && use_iv)) +    msg (M_FATAL, "--no-replay or --no-iv cannot be used with a CFB or OFB mode cipher");  }  /* diff --git a/main/openvpn/src/openvpn/crypto.h b/main/openvpn/src/openvpn/crypto.h index 68cdf162..3c4e59d7 100644 --- a/main/openvpn/src/openvpn/crypto.h +++ b/main/openvpn/src/openvpn/crypto.h @@ -32,8 +32,6 @@  #ifdef ENABLE_CRYPTO -#define ALLOW_NON_CBC_CIPHERS -  #include "crypto_backend.h"  #include "basic.h"  #include "buffer.h" @@ -189,8 +187,6 @@ bool write_key (const struct key *key, const struct key_type *kt,  int read_key (struct key *key, const struct key_type *kt, struct buffer *buf); -bool cfb_ofb_mode (const struct key_type* kt); -  void init_key_type (struct key_type *kt, const char *ciphername,      bool ciphername_defined, const char *authname, bool authname_defined,      int keysize, bool cfb_ofb_allowed, bool warn); diff --git a/main/openvpn/src/openvpn/crypto_backend.h b/main/openvpn/src/openvpn/crypto_backend.h index 5ae47e6c..a48ad6c5 100644 --- a/main/openvpn/src/openvpn/crypto_backend.h +++ b/main/openvpn/src/openvpn/crypto_backend.h @@ -230,6 +230,26 @@ int cipher_kt_block_size (const cipher_kt_t *cipher_kt);   */  int cipher_kt_mode (const cipher_kt_t *cipher_kt); +/** + * Check of the supplied cipher is a supported CBC mode cipher. + * + * @param cipher	Static cipher parameters. May not be NULL. + * + * @return		true iff the cipher is a CBC mode cipher. + */ +bool cipher_kt_mode_cbc(const cipher_kt_t *cipher) +  __attribute__((nonnull)); + +/** + * Check of the supplied cipher is a supported OFB or CFB mode cipher. + * + * @param cipher	Static cipher parameters. May not be NULL. + * + * @return		true iff the cipher is a OFB or CFB mode cipher. + */ +bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher) +  __attribute__((nonnull)); +  /**   * @@ -288,6 +308,16 @@ int cipher_ctx_block_size (const cipher_ctx_t *ctx);  int cipher_ctx_mode (const cipher_ctx_t *ctx);  /** + * Returns the static cipher parameters for this context. + * + * @param ctx 		Cipher's context. May not be NULL. + * + * @return 		Static cipher parameters for the supplied context. + */ +const cipher_kt_t *cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) +  __attribute__((nonnull)); + +/**   * Resets the given cipher context, setting the IV to the specified value.   * Preserves the associated key information.   * diff --git a/main/openvpn/src/openvpn/crypto_openssl.c b/main/openvpn/src/openvpn/crypto_openssl.c index c3480e02..0ac89a19 100644 --- a/main/openvpn/src/openvpn/crypto_openssl.c +++ b/main/openvpn/src/openvpn/crypto_openssl.c @@ -40,6 +40,7 @@  #include "basic.h"  #include "buffer.h"  #include "integer.h" +#include "crypto.h"  #include "crypto_backend.h"  #include <openssl/objects.h>  #include <openssl/evp.h> @@ -253,7 +254,7 @@ show_available_ciphers ()  	  "used as a parameter to the --cipher option.  The default\n"  	  "key size is shown as well as whether or not it can be\n"            "changed with the --keysize directive.  Using a CBC mode\n" -	  "is recommended.\n\n"); +	  "is recommended. In static key mode only CBC mode is allowed.\n\n");  #endif    for (nid = 0; nid < 10000; ++nid)	/* is there a better way to get the size of the nid list? */ @@ -261,17 +262,22 @@ show_available_ciphers ()        const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid);        if (cipher)  	{ -	  const unsigned int mode = EVP_CIPHER_mode (cipher); -	  if (mode == EVP_CIPH_CBC_MODE -#ifdef ALLOW_NON_CBC_CIPHERS -	      || mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE +	  if (cipher_kt_mode_cbc(cipher) +#ifdef ENABLE_OFB_CFB_MODE +	      || cipher_kt_mode_ofb_cfb(cipher)  #endif  	      ) -	    printf ("%s %d bit default key (%s)\n", -		    OBJ_nid2sn (nid), -		    EVP_CIPHER_key_length (cipher) * 8, -		    ((EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ? -		     "variable" : "fixed")); +	    { +	      const char *var_key_size = +		  (EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ? +		       "variable" : "fixed"; +	      const char *ssl_only = cipher_kt_mode_ofb_cfb(cipher) ? +		  " (TLS client/server mode)" : ""; + +	      printf ("%s %d bit default key (%s)%s\n", OBJ_nid2sn (nid), +		      EVP_CIPHER_key_length (cipher) * 8, var_key_size, +		      ssl_only); +	    }  	}      }    printf ("\n"); @@ -483,6 +489,29 @@ cipher_kt_mode (const EVP_CIPHER *cipher_kt)    return EVP_CIPHER_mode (cipher_kt);  } +bool +cipher_kt_mode_cbc(const cipher_kt_t *cipher) +{ +  return cipher_kt_mode(cipher) == OPENVPN_MODE_CBC +#ifdef EVP_CIPH_FLAG_AEAD_CIPHER +      /* Exclude AEAD cipher modes, they require a different API */ +      && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) +#endif +    ; +} + +bool +cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher) +{ +  return (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB || +	  cipher_kt_mode(cipher) == OPENVPN_MODE_CFB) +#ifdef EVP_CIPH_FLAG_AEAD_CIPHER +      /* Exclude AEAD cipher modes, they require a different API */ +      && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) +#endif +    ; +} +  /*   *   * Generic cipher context functions @@ -536,6 +565,13 @@ cipher_ctx_mode (const EVP_CIPHER_CTX *ctx)    return EVP_CIPHER_CTX_mode (ctx);  } +const cipher_kt_t * +cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) +{ +  return EVP_CIPHER_CTX_cipher(ctx); +} + +  int  cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf)  { diff --git a/main/openvpn/src/openvpn/crypto_polarssl.c b/main/openvpn/src/openvpn/crypto_polarssl.c index 7dc8aa5b..1a986dbd 100644 --- a/main/openvpn/src/openvpn/crypto_polarssl.c +++ b/main/openvpn/src/openvpn/crypto_polarssl.c @@ -416,6 +416,19 @@ cipher_kt_mode (const cipher_info_t *cipher_kt)    return cipher_kt->mode;  } +bool +cipher_kt_mode_cbc(const cipher_kt_t *cipher) +{ +  return cipher_kt_mode(cipher) == OPENVPN_MODE_CBC; +} + +bool +cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher) +{ +  return (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB || +	  cipher_kt_mode(cipher) == OPENVPN_MODE_CFB); +} +  /*   * @@ -464,6 +477,14 @@ int cipher_ctx_mode (const cipher_context_t *ctx)    return cipher_kt_mode(ctx->cipher_info);  } +const cipher_kt_t * +cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) +{ +  ASSERT(NULL != ctx); + +  return ctx->cipher_info; +} +  int cipher_ctx_reset (cipher_context_t *ctx, uint8_t *iv_buf)  {    int retval = cipher_reset(ctx); diff --git a/main/openvpn/src/openvpn/helper.c b/main/openvpn/src/openvpn/helper.c index d9eef03b..0ed0b2ba 100644 --- a/main/openvpn/src/openvpn/helper.c +++ b/main/openvpn/src/openvpn/helper.c @@ -232,6 +232,8 @@ helper_client_server (struct options *o)     *   if !nopool:      *     ifconfig-pool 10.8.0.2 10.8.0.254 255.255.255.0     *   push "route-gateway 10.8.0.1" +   *   if route-gateway unset: +   *     route-gateway 10.8.0.2     */    if (o->server_defined) @@ -311,8 +313,10 @@ helper_client_server (struct options *o)  		  ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);  		}  	      o->ifconfig_pool_netmask = o->server_netmask; -		   +  	      push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE); +	      if (!o->route_default_gateway) +		o->route_default_gateway = print_in_addr_t (o->server_network + 2, 0, &o->gc);  	    }  	  else  	    ASSERT (0); diff --git a/main/openvpn/src/openvpn/init.c b/main/openvpn/src/openvpn/init.c index 7dd61a20..6137588d 100644 --- a/main/openvpn/src/openvpn/init.c +++ b/main/openvpn/src/openvpn/init.c @@ -2150,7 +2150,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags)  			       options->use_iv);    /* In short form, unique datagram identifier is 32 bits, in long form 64 bits */ -  packet_id_long_form = cfb_ofb_mode (&c->c1.ks.key_type); +  packet_id_long_form = cipher_kt_mode_ofb_cfb (c->c1.ks.key_type.cipher);    /* Compute MTU parameters */    crypto_adjust_frame_parameters (&c->c2.frame, @@ -3172,10 +3172,10 @@ managmenet_callback_network_change (void *arg)    if (c->c2.link_socket->sd == SOCKET_UNDEFINED)      return -1; -  /* Check if the client should translate the network change to a SIGUSR1 to  +  /* Check if the client should translate the network change to a SIGUSR1 to       reestablish the connection or just reprotect the socket */ -  /* At the moment just assume that, for all settings that use pull  +  /* At the moment just assume that, for all settings that use pull       reestablishing the connection is required */    socketfd = c->c2.link_socket->sd; diff --git a/main/openvpn/src/openvpn/options.c b/main/openvpn/src/openvpn/options.c index addca14a..9ff2db5a 100644 --- a/main/openvpn/src/openvpn/options.c +++ b/main/openvpn/src/openvpn/options.c @@ -575,8 +575,8 @@ static const char usage_message[] =    "                  and optionally the root CA certificate.\n"  #endif  #ifdef ENABLE_X509ALTUSERNAME -  "--x509-username-field : Field used in x509 certificate to be username.\n" -  "                        Default is CN.\n" +  "--x509-username-field : Field in x509 certificate containing the username.\n" +  "                        Default is CN in the Subject field.\n"  #endif    "--verify-hash   : Specify SHA1 fingerprint for level-1 cert.\n"  #ifdef WIN32 @@ -6881,10 +6881,28 @@ add_option (struct options *options,  #ifdef ENABLE_X509ALTUSERNAME    else if (streq (p[0], "x509-username-field") && p[1])      { +      /* This option used to automatically upcase the fieldname passed as the +       * option argument, e.g., "ou" became "OU". Now, this "helpfulness" is +       * fine-tuned by only upcasing Subject field attribute names which consist +       * of all lower-case characters. Mixed-case attributes such as +       * "emailAddress" are left as-is. An option parameter having the "ext:" +       * prefix for matching X.509v3 extended fields will also remain unchanged. +       */        char *s = p[1]; +        VERIFY_PERMISSION (OPT_P_GENERAL); -      if( strncmp ("ext:",s,4) != 0 ) -        while ((*s = toupper(*s)) != '\0') s++; /* Uppercase if necessary */ +      if (strncmp("ext:", s, 4) != 0) +	{ +	  size_t i = 0; +	  while (s[i] && !isupper(s[i])) i++; +	  if (strlen(s) == i) +	    { +	      while ((*s = toupper(*s)) != '\0') s++; +	      msg(M_WARN, "DEPRECATED FEATURE: automatically upcased the " +		  "--x509-username-field parameter to '%s'; please update your" +		  "configuration", p[1]); +	    } +	}        options->x509_username_field = p[1];      }  #endif /* ENABLE_X509ALTUSERNAME */ diff --git a/main/openvpn/src/openvpn/route.c b/main/openvpn/src/openvpn/route.c index bcc6fcee..562af9fe 100644 --- a/main/openvpn/src/openvpn/route.c +++ b/main/openvpn/src/openvpn/route.c @@ -1535,6 +1535,17 @@ add_route (struct route_ipv4 *r,    argv_msg (D_ROUTE, &argv);    status = openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route add command failed"); +#elif defined(TARGET_AIX) + +  { +  int netbits = netmask_to_netbits2(r->netmask); +  argv_printf (&argv, "%s add -net %s/%d %s", +		ROUTE_PATH, +	        network, netbits, gateway); +  argv_msg (D_ROUTE, &argv); +  status = openvpn_execve_check (&argv, es, 0, "ERROR: AIX route add command failed"); +  } +  #else    msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this operating system.  Try putting your routes in a --route-up script");  #endif @@ -1754,6 +1765,14 @@ add_route_ipv6 (struct route_ipv6 *r6, const struct tuntap *tt, unsigned int fla    argv_msg (D_ROUTE, &argv);    status = openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route add -inet6 command failed"); +#elif defined(TARGET_AIX) + +  argv_printf (&argv, "%s add -inet6 %s/%d %s", +		ROUTE_PATH, +	        network, r6->netbits, gateway); +  argv_msg (D_ROUTE, &argv); +  status = openvpn_execve_check (&argv, es, 0, "ERROR: AIX route add command failed"); +  #else    msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system.  Try putting your routes in a --route-up script");  #endif @@ -1912,8 +1931,21 @@ delete_route (struct route_ipv4 *r,    argv_msg (D_ROUTE, &argv);    openvpn_execve_check (&argv, es, 0, "ERROR: OpenBSD/NetBSD route delete command failed"); +  #elif defined(TARGET_ANDROID)    msg (M_NONFATAL, "Sorry, deleting routes on Android is not possible. The VpnService API allows routes to be set on connect only."); + +#elif defined(TARGET_AIX) + +  { +  int netbits = netmask_to_netbits2(r->netmask); +  argv_printf (&argv, "%s delete -net %s/%d %s", +		ROUTE_PATH, +	        network, netbits, gateway); +  argv_msg (D_ROUTE, &argv); +  openvpn_execve_check (&argv, es, 0, "ERROR: AIX route delete command failed"); +  } +  #else    msg (M_FATAL, "Sorry, but I don't know how to do 'route' commands on this operating system.  Try putting your routes in a --route-up script");  #endif @@ -2084,6 +2116,14 @@ delete_route_ipv6 (const struct route_ipv6 *r6, const struct tuntap *tt, unsigne    argv_msg (D_ROUTE, &argv);    openvpn_execve_check (&argv, es, 0, "ERROR: NetBSD route delete -inet6 command failed"); +#elif defined(TARGET_AIX) + +  argv_printf (&argv, "%s delete -inet6 %s/%d %s", +		ROUTE_PATH, +	        network, r6->netbits, gateway); +  argv_msg (D_ROUTE, &argv); +  openvpn_execve_check (&argv, es, 0, "ERROR: AIX route add command failed"); +  #else    msg (M_FATAL, "Sorry, but I don't know how to do 'route ipv6' commands on this operating system.  Try putting your routes in a --route-down script");  #endif @@ -2921,6 +2961,26 @@ netmask_to_netbits (const in_addr_t network, const in_addr_t netmask, int *netbi    return false;  } +/* similar to netmask_to_netbits(), but don't mess with base address + * etc., just convert to netbits - non-mappable masks are returned as "-1" + */ +int netmask_to_netbits2 (in_addr_t netmask) +{ +  int i; +  const int addrlen = sizeof (in_addr_t) * 8; + +  for (i = 0; i <= addrlen; ++i) +    { +      in_addr_t mask = netbits_to_netmask (i); +      if (mask == netmask) +	{ +	  return i; +	} +    } +  return -1; +} + +  /*   * get_bypass_addresses() is used by the redirect-gateway bypass-x   * functions to build a route bypass to selected DHCP/DNS servers, diff --git a/main/openvpn/src/openvpn/ssl.c b/main/openvpn/src/openvpn/ssl.c index 44f50808..929f95fa 100644 --- a/main/openvpn/src/openvpn/ssl.c +++ b/main/openvpn/src/openvpn/ssl.c @@ -998,22 +998,6 @@ reset_session (struct tls_multi *multi, struct tls_session *session)    tls_session_init (multi, session);  } -#if 0 -/* - * Transmit a TLS reset on our untrusted channel. - */ -static void -initiate_untrusted_session (struct tls_multi *multi, struct sockaddr_in *to) -{ -  struct tls_session *session = &multi->session[TM_UNTRUSTED]; -  struct key_state *ks = &session->key[KS_PRIMARY]; - -  reset_session (multi, session); -  ks->remote_addr = *to; -  msg (D_TLS_DEBUG_LOW, "TLS: initiate_untrusted_session: addr=%s", print_sockaddr (to)); -} -#endif -  /*   * Used to determine in how many seconds we should be   * called again. diff --git a/main/openvpn/src/openvpn/ssl_openssl.c b/main/openvpn/src/openvpn/ssl_openssl.c index c9d2d26d..adf3ae6f 100644 --- a/main/openvpn/src/openvpn/ssl_openssl.c +++ b/main/openvpn/src/openvpn/ssl_openssl.c @@ -270,7 +270,8 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)            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)) +	      0 != memcmp (&ciphers[begin_of_cipher], cipher_pair->iana_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); diff --git a/main/openvpn/src/openvpn/ssl_openssl.h b/main/openvpn/src/openvpn/ssl_openssl.h index fc2052cb..97dc7422 100644 --- a/main/openvpn/src/openvpn/ssl_openssl.h +++ b/main/openvpn/src/openvpn/ssl_openssl.h @@ -33,6 +33,17 @@  #include <openssl/ssl.h>  /** + * SSL_OP_NO_TICKET tells OpenSSL to disable "stateless session resumption", + * as this is something we do not want nor need, but could potentially be + * used for a future attack.  For compatibility reasons we keep building if the + * OpenSSL version is too old (pre-0.9.8f) to support stateless session + * resumption (and the accompanying SSL_OP_NO_TICKET flag). + */ +#ifndef SSL_OP_NO_TICKET +# define SSL_OP_NO_TICKET 0 +#endif + +/**   * Structure that wraps the TLS context. Contents differ depending on the   * SSL library used.   */ diff --git a/main/openvpn/src/openvpn/ssl_verify_openssl.c b/main/openvpn/src/openvpn/ssl_verify_openssl.c index 2482eaa4..cbcff022 100644 --- a/main/openvpn/src/openvpn/ssl_verify_openssl.c +++ b/main/openvpn/src/openvpn/ssl_verify_openssl.c @@ -591,12 +591,12 @@ x509_verify_crl(const char *crl_file, X509 *peer_cert, const char *subject)    in = BIO_new_file (crl_file, "r");    if (in == NULL) { -    msg (M_ERR, "CRL: cannot read: %s", crl_file); +    msg (M_WARN, "CRL: cannot read: %s", crl_file);      goto end;    }    crl=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);    if (crl == NULL) { -    msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file); +    msg (M_WARN, "CRL: cannot read CRL from file %s", crl_file);      goto end;    } diff --git a/main/openvpn/src/openvpn/ssl_verify_polarssl.c b/main/openvpn/src/openvpn/ssl_verify_polarssl.c index 7e8b5179..2b7c214f 100644 --- a/main/openvpn/src/openvpn/ssl_verify_polarssl.c +++ b/main/openvpn/src/openvpn/ssl_verify_polarssl.c @@ -371,9 +371,12 @@ x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject)    result_t retval = FAILURE;    x509_crl crl = {0}; -  if (x509_crl_parse_file(&crl, crl_file) != 0) +  int polar_retval = x509_crl_parse_file(&crl, crl_file); +  if (polar_retval != 0)      { -      msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file); +      char errstr[128]; +      polarssl_strerror(polar_retval, errstr, sizeof(errstr)); +      msg (M_WARN, "CRL: cannot read CRL from file %s (%s)", crl_file, errstr);        goto end;      } diff --git a/main/openvpn/src/openvpn/syshead.h b/main/openvpn/src/openvpn/syshead.h index 771c4fc1..dc511cbc 100644 --- a/main/openvpn/src/openvpn/syshead.h +++ b/main/openvpn/src/openvpn/syshead.h @@ -349,6 +349,14 @@  #endif /* TARGET_DRAGONFLY */ +#ifdef TARGET_DARWIN + +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +#endif /* TARGET_DARWIN */ +  #ifdef WIN32  #include <iphlpapi.h>  #include <ntddndis.h> diff --git a/main/openvpn/src/openvpn/tun.c b/main/openvpn/src/openvpn/tun.c index 482f6402..e92edc2f 100644 --- a/main/openvpn/src/openvpn/tun.c +++ b/main/openvpn/src/openvpn/tun.c @@ -1194,6 +1194,43 @@ do_ifconfig (struct tuntap *tt,  	  openvpn_execve_check (&argv, es, S_FATAL, "FreeBSD ifconfig inet6 failed");  	} +#elif defined(TARGET_AIX) +      { +	/* AIX ifconfig will complain if it can't find ODM path in env */ +	struct env_set *aix_es = env_set_create (NULL); +	env_set_add( aix_es, "ODMDIR=/etc/objrepos" ); + +	if (tun) +	  msg(M_FATAL, "no tun support on AIX (canthappen)"); + +	/* example: ifconfig tap0 172.30.1.1 netmask 255.255.254.0 up */ +	argv_printf (&argv, +		     "%s %s %s netmask %s mtu %d up", +			    IFCONFIG_PATH, +			    actual, +			    ifconfig_local, +			    ifconfig_remote_netmask, +			    tun_mtu +			    ); + +	argv_msg (M_INFO, &argv); +	openvpn_execve_check (&argv, aix_es, S_FATAL, "AIX ifconfig failed"); +	tt->did_ifconfig = true; + +	if ( do_ipv6 ) +	  { +	    argv_printf (&argv, +				"%s %s inet6 %s/%d", +				IFCONFIG_PATH, +				actual, +				ifconfig_ipv6_local, +				tt->netbits_ipv6 +				); +	    argv_msg (M_INFO, &argv); +	    openvpn_execve_check (&argv, aix_es, S_FATAL, "AIX ifconfig inet6 failed"); +	  } +	env_set_destroy (aix_es); +      }  #elif defined (WIN32)        {  	/* @@ -2825,6 +2862,139 @@ read_tun (struct tuntap* tt, uint8_t *buf, int len)      return read (tt->fd, buf, len);  } +#elif defined(TARGET_AIX) + +void +open_tun (const char *dev, const char *dev_type, const char *dev_node, struct tuntap *tt) +{ +  char tunname[256]; +  char dynamic_name[20]; +  const char *p; +  struct argv argv; + +  if (tt->type == DEV_TYPE_NULL) +    { +      open_null (tt); +      return; +    } + +  if ( tt->type == DEV_TYPE_TUN) +    { +      msg(M_FATAL, "no support for 'tun' devices on AIX" ); +    } + +  if ( strncmp( dev, "tap", 3 ) != 0 || dev_node ) +    { +      msg(M_FATAL, "'--dev %s' and/or '--dev-node' not supported on AIX, use '--dev tap0', 'tap1', etc.", dev ); +    } + +  if ( strcmp( dev, "tap" ) == 0 )		/* find first free tap dev */ +    {						/* (= no /dev/tapN node) */ +      int i; +      for (i=0; i<99; i++ ) +	{ +	  openvpn_snprintf (tunname, sizeof (tunname), "/dev/tap%d", i); +	  if ( access( tunname, F_OK ) < 0 && errno == ENOENT ) +	    { break; } +	} +      if ( i >= 99 ) +	msg( M_FATAL, "cannot find unused tap device" ); + +      openvpn_snprintf( dynamic_name, sizeof(dynamic_name), "tap%d", i ); +      dev = dynamic_name; +    } +  else						/* name given, sanity check */ +    { +      /* ensure that dev name is "tap+<digits>" *only* */ +      p = &dev[3]; +      while( isdigit(*p) ) p++; +      if ( *p != '\0' ) +	msg( M_FATAL, "TAP device name must be '--dev tapNNNN'" ); + +      openvpn_snprintf (tunname, sizeof (tunname), "/dev/%s", dev); +    } + +  /* pre-existing device? +   */ +  if ( access( tunname, F_OK ) < 0 && errno == ENOENT ) +    { + +      /* tunnel device must be created with 'ifconfig tapN create' +       */ +      struct env_set *es = env_set_create (NULL); +      argv_init (&argv); +      argv_printf (&argv, "%s %s create", IFCONFIG_PATH, dev); +      argv_msg (M_INFO, &argv); +      env_set_add( es, "ODMDIR=/etc/objrepos" ); +      openvpn_execve_check (&argv, es, S_FATAL, "AIX 'create tun interface' failed"); +      env_set_destroy (es); +    } +  else +    { +      /* we didn't make it, we're not going to break it */ +      tt->persistent_if = TRUE; +    } + +  if ((tt->fd = open (tunname, O_RDWR)) < 0) +    { +      msg (M_ERR, "Cannot open TAP device '%s'", tunname); +    } + +  set_nonblock (tt->fd); +  set_cloexec (tt->fd); /* don't pass fd to scripts */ +  msg (M_INFO, "TUN/TAP device %s opened", tunname); + +  /* tt->actual_name is passed to up and down scripts and used as the ifconfig dev name */ +  tt->actual_name = string_alloc(dev, NULL); +} + +/* tap devices need to be manually destroyed on AIX + */ +void +close_tun (struct tuntap* tt) +{ +  struct gc_arena gc = gc_new (); +  struct argv argv; +  struct env_set *es = env_set_create (NULL); + +  if (!tt) return; + +  /* persistent devices need IP address unconfig, others need destroyal +   */ +  argv_init (&argv); + +  if (tt->persistent_if) +    { +      argv_printf (&argv, "%s %s 0.0.0.0 down", +                          IFCONFIG_PATH, tt->actual_name); +    } +  else +    { +      argv_printf (&argv, "%s %s destroy", +                          IFCONFIG_PATH, tt->actual_name); +    } + +  close_tun_generic (tt); +  argv_msg (M_INFO, &argv); +  env_set_add( es, "ODMDIR=/etc/objrepos" ); +  openvpn_execve_check (&argv, es, 0, "AIX 'destroy tap interface' failed (non-critical)"); + +  free(tt); +  env_set_destroy (es); +} + +int +write_tun (struct tuntap* tt, uint8_t *buf, int len) +{ +    return write (tt->fd, buf, len); +} + +int +read_tun (struct tuntap* tt, uint8_t *buf, int len) +{ +    return read (tt->fd, buf, len); +} +  #elif defined(WIN32)  int diff --git a/main/openvpn/tests/t_client.sh.in b/main/openvpn/tests/t_client.sh.in index 52c5ed1a..d4f7c4ab 100755 --- a/main/openvpn/tests/t_client.sh.in +++ b/main/openvpn/tests/t_client.sh.in @@ -134,6 +134,12 @@ get_ifconfig_route()  	   @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }'  	   return  	   ;; +	AIX) +	   echo "-- AIX --" +	   @IFCONFIG@ -a | egrep "(flags=|inet)" +	   @NETSTAT@ -rn | awk '$3 !~ /^UHL/ { print $1,$2,$3,$6 }' +	   return +	   ;;      esac      echo "get_ifconfig_route(): no idea how to get info on your OS.  FAIL." >&2 diff --git a/main/openvpn/tests/t_lpback.sh b/main/openvpn/tests/t_lpback.sh index 40767a1b..8f88ad92 100755 --- a/main/openvpn/tests/t_lpback.sh +++ b/main/openvpn/tests/t_lpback.sh @@ -2,6 +2,7 @@  #  # t_lpback.sh - script to test OpenVPN's crypto loopback  # Copyright (C) 2005  Matthias Andree +# Copyright (C) 2014  Steffan Karger  #  # This program is free software; you can redistribute it and/or  # modify it under the terms of the GNU General Public License @@ -18,15 +19,39 @@  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  # 02110-1301, USA. -set -e +set -eu  top_builddir="${top_builddir:-..}"  trap "rm -f key.$$ log.$$ ; trap 0 ; exit 77" 1 2 15  trap "rm -f key.$$ log.$$ ; exit 1" 0 3 + +# Get list of supported ciphers from openvpn --show-ciphers output +CIPHERS=$(${top_builddir}/src/openvpn/openvpn --show-ciphers | \ +            sed -e '1,/^$/d' -e s'/ .*//' -e '/^\s*$/d' | sort) + +# SK, 2014-06-04: currently the DES-EDE3-CFB1 implementation of OpenSSL is +# broken (see http://rt.openssl.org/Ticket/Display.html?id=2867), so exclude +# that cipher from this test. +# GD, 2014-07-06 so is DES-CFB1 +# GD, 2014-07-06 do not test RC5-* either (fails on NetBSD w/o libcrypto_rc5) +CIPHERS=$(echo "$CIPHERS" | egrep -v '^(DES-EDE3-CFB1|DES-CFB1|RC5-)' ) +  "${top_builddir}/src/openvpn/openvpn" --genkey --secret key.$$  set +e -( "${top_builddir}/src/openvpn/openvpn" --test-crypto --secret key.$$ ) >log.$$ 2>&1 -e=$? -if [ $e != 0 ] ; then cat log.$$ ; fi + +e=0 +for cipher in ${CIPHERS} +do +    echo -n "Testing cipher ${cipher}... " +    ( "${top_builddir}/src/openvpn/openvpn" --test-crypto --secret key.$$ --cipher ${cipher} ) >log.$$ 2>&1 +    if [ $? != 0 ] ; then +        echo "FAILED" +        cat log.$$ +        e=1 +    else +        echo "OK" +    fi +done +  rm key.$$ log.$$  trap 0  exit $e  | 
