diff options
Diffstat (limited to 'main/openvpn')
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 |