From 91ec580beceb3d6c723d2ade85436374992526f7 Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Tue, 3 Jun 2014 23:23:30 +0200 Subject: Import new openvpn -master version --- .hgignore | 1 + main/openvpn/README.ec | 14 +- main/openvpn/config-msvc.h | 3 + main/openvpn/config-version.h | 4 +- main/openvpn/configure.ac | 10 + main/openvpn/contrib/OCSP_check/OCSP_check.sh | 8 +- main/openvpn/doc/openvpn.8 | 52 ++++-- main/openvpn/src/openvpn/crypto_openssl.c | 38 +--- main/openvpn/src/openvpn/forward.c | 1 + main/openvpn/src/openvpn/init.c | 7 +- main/openvpn/src/openvpn/multi.c | 1 + main/openvpn/src/openvpn/options.c | 18 +- main/openvpn/src/openvpn/options.h | 2 + main/openvpn/src/openvpn/pf.c | 2 +- main/openvpn/src/openvpn/proto.c | 2 +- main/openvpn/src/openvpn/push.c | 1 + main/openvpn/src/openvpn/route.c | 248 +++---------------------- main/openvpn/src/openvpn/socket.c | 8 +- main/openvpn/src/openvpn/ssl.c | 25 ++- main/openvpn/src/openvpn/ssl.h | 1 - main/openvpn/src/openvpn/ssl_backend.h | 2 +- main/openvpn/src/openvpn/ssl_openssl.c | 17 +- main/openvpn/src/openvpn/ssl_polarssl.c | 19 +- main/openvpn/src/openvpn/ssl_verify.c | 5 + main/openvpn/src/openvpn/ssl_verify.h | 25 +-- main/openvpn/src/openvpn/ssl_verify_backend.h | 19 +- main/openvpn/src/openvpn/ssl_verify_openssl.c | 16 +- main/openvpn/src/openvpn/ssl_verify_polarssl.c | 42 ++++- main/openvpn/src/openvpn/ssl_verify_polarssl.h | 2 - main/openvpn/src/plugins/auth-pam/Makefile.am | 5 +- main/openvpn/src/plugins/down-root/Makefile.am | 3 +- 31 files changed, 251 insertions(+), 350 deletions(-) diff --git a/.hgignore b/.hgignore index 1949913a..6840f004 100644 --- a/.hgignore +++ b/.hgignore @@ -75,5 +75,6 @@ cache.properties *.iml main/openvpn3 +main/openssl/.git main/boost_1_55_0 diff --git a/main/openvpn/README.ec b/main/openvpn/README.ec index bea3ce19..32938017 100644 --- a/main/openvpn/README.ec +++ b/main/openvpn/README.ec @@ -6,20 +6,18 @@ in OpenVPN; the data channel (encrypting the actual network traffic) uses symmetric encryption. ECC can be used in TLS for authentication (ECDSA) and key exchange (ECDH). -Note: ECC is available in OpenSSL builds of OpenVPN only. ECC for PolarSSL -builds will follow soon. - Key exchange (ECDH) ------------------- OpenVPN 2.4.0 and newer automatically initialize ECDH parameters. When ECDSA is used for authentication, the curve used for the server certificate will be used for ECDH too. When autodetection fails (e.g. when using RSA certificates) -OpenVPN falls back to the secp384r1 curve. +OpenVPN lets the crypto library decide if possible, or falls back to the +secp384r1 curve. -An administrator can force an OpenVPN server to use a specific curve using the ---ecdh-curve option with one of the curves listed as available by -the --show-curves option. Clients will use the same curve as selected by the -server. +An administrator can force an OpenVPN/OpenSSL server to use a specific curve +using the --ecdh-curve option with one of the curves listed as +available by the --show-curves option. Clients will use the same curve as +selected by the server. Note that not all curves listed by --show-curves are available for use with TLS; in that case connecting will fail with a 'no shared cipher' TLS error. diff --git a/main/openvpn/config-msvc.h b/main/openvpn/config-msvc.h index 9a95ae65..fa993843 100644 --- a/main/openvpn/config-msvc.h +++ b/main/openvpn/config-msvc.h @@ -76,6 +76,9 @@ #define HAVE_OPENSSL_ENGINE 1 +#define PATH_SEPARATOR '\\' +#define PATH_SEPARATOR_STR "\\" + #ifndef __cplusplus #define inline __inline #endif diff --git a/main/openvpn/config-version.h b/main/openvpn/config-version.h index 60276cd8..ac6ff482 100644 --- a/main/openvpn/config-version.h +++ b/main/openvpn/config-version.h @@ -1,2 +1,2 @@ -#define CONFIGURE_GIT_REVISION "icsopenvpn_612-757f9467b41fb40e" -#define CONFIGURE_GIT_FLAGS "+" +#define CONFIGURE_GIT_REVISION "icsopenvpn_613-86da111e79f644a7" +#define CONFIGURE_GIT_FLAGS "" diff --git a/main/openvpn/configure.ac b/main/openvpn/configure.ac index 70c0c8b5..55c40847 100644 --- a/main/openvpn/configure.ac +++ b/main/openvpn/configure.ac @@ -229,6 +229,13 @@ AC_ARG_ENABLE( [enable_pedantic="no"] ) +AC_ARG_ENABLE( + [werror], + [AS_HELP_STRING([--enable-werror], [promote compiler warnings to errors, will cause builds to fail is the compiler issues warnings (debugging option) @<:@default=no@:>@])], + , + [enable_werror="no"] +) + AC_ARG_ENABLE( [strict-options], [AS_HELP_STRING([--enable-strict-options], [enable strict options check between peers (debugging option) @<:@default=no@:>@])], @@ -1121,6 +1128,9 @@ fi if test "${enable_strict}" = "yes"; then CFLAGS="${CFLAGS} -Wall -Wno-unused-parameter -Wno-unused-function" fi +if test "${enable_werror}" = "yes"; then + CFLAGS="${CFLAGS} -Werror" +fi if test "${WIN32}" = "yes"; then test -z "${MAN2HTML}" && AC_MSG_ERROR([man2html is required for win32]) diff --git a/main/openvpn/contrib/OCSP_check/OCSP_check.sh b/main/openvpn/contrib/OCSP_check/OCSP_check.sh index 847be450..553c3dce 100644 --- a/main/openvpn/contrib/OCSP_check/OCSP_check.sh +++ b/main/openvpn/contrib/OCSP_check/OCSP_check.sh @@ -71,7 +71,7 @@ if [ $check_depth -eq -1 ] || [ $cur_depth -eq $check_depth ]; then # - The serial number must not be empty # - The exit status of "openssl ocsp" must be zero # - The output of the above command must contain the line - # "0x${serial}: good" + # "${serial}: good" # # Everything else fails with exit status 1. @@ -83,7 +83,7 @@ if [ $check_depth -eq -1 ] || [ $cur_depth -eq $check_depth ]; then # Sample output that is assumed here: # # Response verify OK - # 0x428740A5: good + # 4287405: good # This Update: Apr 24 19:38:49 2010 GMT # Next Update: May 2 14:23:42 2010 GMT # @@ -97,11 +97,11 @@ if [ $check_depth -eq -1 ] || [ $cur_depth -eq $check_depth ]; then "$nonce" \ -CAfile "$verify" \ -url "$ocsp_url" \ - -serial "0x${serial}" 2>/dev/null) + -serial "${serial}" 2>/dev/null) if [ $? -eq 0 ]; then # check that it's good - if echo "$status" | grep -Fq "0x${serial}: good"; then + if echo "$status" | grep -Fq "^${serial}: good"; then exit 0 fi fi diff --git a/main/openvpn/doc/openvpn.8 b/main/openvpn/doc/openvpn.8 index b7d6a3d7..34894e5a 100644 --- a/main/openvpn/doc/openvpn.8 +++ b/main/openvpn/doc/openvpn.8 @@ -2343,18 +2343,23 @@ is NOT specified. .\"********************************************************* .TP .B \-\-multihome -Configure a multi-homed UDP server. This option can be used when -OpenVPN has been configured to listen on all interfaces, and will -attempt to bind client sessions to the interface on which packets -are being received, so that outgoing packets will be sent out -of the same interface. Note that this option is only relevant for -UDP servers and currently is only implemented on Linux. - -Note: clients connecting to a -.B \-\-multihome -server should always use the -.B \-\-nobind -option. +Configure a multi-homed UDP server. This option needs to be used when +a server has more than one IP address (e.g. multiple interfaces, or +secondary IP addresses), and is not using +.B \-\-local +to force binding to one specific address only. This option will +add some extra lookups to the packet path to ensure that the UDP reply +packets are always sent from the address that the client is +talking to. This is not supported on all platforms, and it adds more +processing, so it's not enabled by default. + +Note: this option is only relevant for UDP servers. + +Note 2: if you do an IPv6+IPv4 dual-stack bind on a Linux machine with +multiple IPv4 address, connections to IPv4 addresses will not work +right on kernels before 3.15, due to missing kernel support for the +IPv4-mapped case (some distributions have ported this to earlier kernel +versions, though). .\"********************************************************* .TP .B \-\-echo [parms...] @@ -5467,9 +5472,11 @@ option can be used BEFORE this option to produce debugging information. .SS IPv6 Related Options .\"********************************************************* The following options exist to support IPv6 tunneling in peer-to-peer -and client-server mode. As of now, this is just very basic -documentation of the IPv6-related options. More documentation can be -found on http://www.greenie.net/ipv6/openvpn.html. +and client-server mode. All options are modeled after their IPv4 +counterparts, so more detailed explanations given there apply here +as well (except for +.B \-\-topology +, which has no effect on IPv6). .TP .B --ifconfig-ipv6 ipv6addr/bits ipv6remote configure IPv6 address @@ -5500,7 +5507,8 @@ pool starts at .B ipv6addr and increments by +1 for every new client (linear mode). The .B /bits -setting controls the size of the pool. +setting controls the size of the pool. Due to implementation details, +the pool size must be between /64 and /112. .TP .B --ifconfig-ipv6-push ipv6addr/bits ipv6remote for ccd/ per-client static IPv6 interface configuration, see @@ -6094,14 +6102,20 @@ where is the verification level. Only set for TLS connections. Set prior to execution of .B \-\-tls-verify -script. This is in the form of a hex string like "37AB46E0", which is -suitable for doing serial-based OCSP queries (with OpenSSL, you have -to prepend "0x" to the string). If something goes wrong while reading +script. This is in the form of a decimal string like "933971680", which is +suitable for doing serial-based OCSP queries (with OpenSSL, do not +prepend "0x" to the string) If something goes wrong while reading the value from the certificate it will be an empty string, so your code should check that. See the contrib/OCSP_check/OCSP_check.sh script for an example. .\"********************************************************* .TP +.B tls_serial_hex_{n} +Like +.B tls_serial_{n}\fR, +but in hex form (e.g. "12:34:56:78:9A"). +.\"********************************************************* +.TP .B tun_mtu The MTU of the TUN/TAP device. Set prior to diff --git a/main/openvpn/src/openvpn/crypto_openssl.c b/main/openvpn/src/openvpn/crypto_openssl.c index 6199e618..c3480e02 100644 --- a/main/openvpn/src/openvpn/crypto_openssl.c +++ b/main/openvpn/src/openvpn/crypto_openssl.c @@ -57,32 +57,6 @@ #warning Some OpenSSL HMAC message digests now support key lengths greater than MAX_HMAC_KEY_LENGTH -- consider increasing MAX_HMAC_KEY_LENGTH #endif -static inline int -EVP_CipherInit_ov (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, uint8_t *key, uint8_t *iv, int enc) -{ - return EVP_CipherInit (ctx, type, key, iv, enc); -} - -static inline int -EVP_CipherUpdate_ov (EVP_CIPHER_CTX *ctx, uint8_t *out, int *outl, uint8_t *in, int inl) -{ - return EVP_CipherUpdate (ctx, out, outl, in, inl); -} - -static inline bool -cipher_ok (const char* name) -{ - return true; -} - -#ifndef EVP_CIPHER_name -#define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e)) -#endif - -#ifndef EVP_MD_name -#define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_type(e)) -#endif - #if HAVE_OPENSSL_ENGINE #include @@ -285,7 +259,7 @@ show_available_ciphers () for (nid = 0; nid < 10000; ++nid) /* is there a better way to get the size of the nid list? */ { const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid); - if (cipher && cipher_ok (OBJ_nid2sn (nid))) + if (cipher) { const unsigned int mode = EVP_CIPHER_mode (cipher); if (mode == EVP_CIPH_CBC_MODE @@ -464,7 +438,7 @@ cipher_kt_get (const char *ciphername) cipher = EVP_get_cipherbyname (ciphername); - if ((NULL == cipher) || !cipher_ok (OBJ_nid2sn (EVP_CIPHER_nid (cipher)))) + if (NULL == cipher) msg (M_SSLERR, "Cipher algorithm '%s' not found", ciphername); if (EVP_CIPHER_key_length (cipher) > MAX_CIPHER_KEY_LENGTH) @@ -525,13 +499,13 @@ cipher_ctx_init (EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, CLEAR (*ctx); EVP_CIPHER_CTX_init (ctx); - if (!EVP_CipherInit_ov (ctx, kt, NULL, NULL, enc)) + if (!EVP_CipherInit (ctx, kt, NULL, NULL, enc)) msg (M_SSLERR, "EVP cipher init #1"); #ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH if (!EVP_CIPHER_CTX_set_key_length (ctx, key_len)) msg (M_SSLERR, "EVP set key size"); #endif - if (!EVP_CipherInit_ov (ctx, NULL, key, NULL, enc)) + if (!EVP_CipherInit (ctx, NULL, key, NULL, enc)) msg (M_SSLERR, "EVP cipher init #2"); /* make sure we used a big enough key */ @@ -565,14 +539,14 @@ cipher_ctx_mode (const EVP_CIPHER_CTX *ctx) int cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf) { - return EVP_CipherInit_ov (ctx, NULL, NULL, iv_buf, -1); + return EVP_CipherInit (ctx, NULL, NULL, iv_buf, -1); } int cipher_ctx_update (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len, uint8_t *src, int src_len) { - return EVP_CipherUpdate_ov (ctx, dst, dst_len, src, src_len); + return EVP_CipherUpdate (ctx, dst, dst_len, src, src_len); } int diff --git a/main/openvpn/src/openvpn/forward.c b/main/openvpn/src/openvpn/forward.c index f78f5f0a..a43361b4 100644 --- a/main/openvpn/src/openvpn/forward.c +++ b/main/openvpn/src/openvpn/forward.c @@ -39,6 +39,7 @@ #include "ps.h" #include "dhcp.h" #include "common.h" +#include "ssl_verify.h" #include "memdbg.h" diff --git a/main/openvpn/src/openvpn/init.c b/main/openvpn/src/openvpn/init.c index 425c077b..ede955a1 100644 --- a/main/openvpn/src/openvpn/init.c +++ b/main/openvpn/src/openvpn/init.c @@ -43,6 +43,7 @@ #include "lladdr.h" #include "ping.h" #include "mstats.h" +#include "ssl_verify.h" #include "memdbg.h" @@ -1823,14 +1824,8 @@ do_hold (struct context *c) static void socket_restart_pause (struct context *c) { - bool proxy = false; int sec = 2; - if (c->options.ce.http_proxy_options) - proxy = true; - if (c->options.ce.socks_proxy_server) - proxy = true; - switch (c->options.ce.proto) { case PROTO_TCP_SERVER: diff --git a/main/openvpn/src/openvpn/multi.c b/main/openvpn/src/openvpn/multi.c index b0119181..16250dc2 100644 --- a/main/openvpn/src/openvpn/multi.c +++ b/main/openvpn/src/openvpn/multi.c @@ -38,6 +38,7 @@ #include "otime.h" #include "gremlin.h" #include "mstats.h" +#include "ssl_verify.h" #include "memdbg.h" diff --git a/main/openvpn/src/openvpn/options.c b/main/openvpn/src/openvpn/options.c index f0e94770..fc764616 100644 --- a/main/openvpn/src/openvpn/options.c +++ b/main/openvpn/src/openvpn/options.c @@ -56,6 +56,7 @@ #include "helper.h" #include "manage.h" #include "forward.h" +#include "ssl_verify.h" #include #include "memdbg.h" @@ -3403,18 +3404,21 @@ usage_small (void) void show_library_versions(const unsigned int flags) { - msg (flags, "library versions: %s%s%s", #ifdef ENABLE_SSL - get_ssl_library_version(), +#define SSL_LIB_VER_STR get_ssl_library_version() #else - "", +#define SSL_LIB_VER_STR "" #endif #ifdef ENABLE_LZO - ", LZO ", lzo_version_string() +#define LZO_LIB_VER_STR ", LZO ", lzo_version_string() #else - "", "" +#define LZO_LIB_VER_STR "", "" #endif - ); + + msg (flags, "library versions: %s%s%s", SSL_LIB_VER_STR, LZO_LIB_VER_STR); + +#undef SSL_LIB_VER_STR +#undef LZO_LIB_VER_STR } static void @@ -4108,7 +4112,7 @@ add_option (struct options *options, read_config_file (options, p[1], level, file, line, msglevel, permission_mask, option_types_found, es); } -#ifdef ENABLE_DEBUG +#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL) else if (streq (p[0], "show-gateway")) { struct route_gateway_info rgi; diff --git a/main/openvpn/src/openvpn/options.h b/main/openvpn/src/openvpn/options.h index 06874ccd..21c210ee 100644 --- a/main/openvpn/src/openvpn/options.h +++ b/main/openvpn/src/openvpn/options.h @@ -680,6 +680,8 @@ void notnull (const char *arg, const char *description); void usage_small (void); +void show_library_versions(const unsigned int flags); + void init_options (struct options *o, const bool init_gc); void uninit_options (struct options *o); diff --git a/main/openvpn/src/openvpn/pf.c b/main/openvpn/src/openvpn/pf.c index 461beed7..a3208db1 100644 --- a/main/openvpn/src/openvpn/pf.c +++ b/main/openvpn/src/openvpn/pf.c @@ -35,8 +35,8 @@ #if defined(ENABLE_PF) #include "init.h" - #include "memdbg.h" +#include "ssl_verify.h" #include "pf-inline.h" diff --git a/main/openvpn/src/openvpn/proto.c b/main/openvpn/src/openvpn/proto.c index b437f1ad..7b58e6ab 100644 --- a/main/openvpn/src/openvpn/proto.c +++ b/main/openvpn/src/openvpn/proto.c @@ -60,7 +60,7 @@ is_ipv_X ( int tunnel_type, struct buffer *buf, int ip_ver ) + sizeof (struct openvpn_iphdr))) return false; eh = (const struct openvpn_ethhdr *) BPTR (buf); - if (ntohs (eh->proto) != OPENVPN_ETH_P_IPV4) + if (ntohs (eh->proto) != (ip_ver == 6 ? OPENVPN_ETH_P_IPV6 : OPENVPN_ETH_P_IPV4)) return false; offset = sizeof (struct openvpn_ethhdr); } diff --git a/main/openvpn/src/openvpn/push.c b/main/openvpn/src/openvpn/push.c index 92e3abbb..24d12c7b 100644 --- a/main/openvpn/src/openvpn/push.c +++ b/main/openvpn/src/openvpn/push.c @@ -33,6 +33,7 @@ #include "push.h" #include "options.h" #include "ssl.h" +#include "ssl_verify.h" #include "manage.h" #include "memdbg.h" diff --git a/main/openvpn/src/openvpn/route.c b/main/openvpn/src/openvpn/route.c index 7ea791b8..bcc6fcee 100644 --- a/main/openvpn/src/openvpn/route.c +++ b/main/openvpn/src/openvpn/route.c @@ -628,7 +628,7 @@ init_route_list (struct route_list *rl, if (rl->rgi.flags & RGI_ADDR_DEFINED) { setenv_route_addr (es, "net_gateway", rl->rgi.gateway.addr, -1); -#ifdef ENABLE_DEBUG +#if defined(ENABLE_DEBUG) && !defined(ENABLE_SMALL) print_default_gateway (D_ROUTE, &rl->rgi); #endif } @@ -2636,118 +2636,9 @@ get_default_gateway (struct route_gateway_info *rgi) gc_free (&gc); } -#elif defined(TARGET_FREEBSD)||defined(TARGET_DRAGONFLY) - -#include -#include -#include -#include - -struct { - struct rt_msghdr m_rtm; - char m_space[512]; -} m_rtmsg; - -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) - -/* - * FIXME -- add support for netmask, hwaddr, and iface - */ -void -get_default_gateway (struct route_gateway_info *rgi) -{ - struct gc_arena gc = gc_new (); - int s, seq, l, pid, rtm_addrs, i; - struct sockaddr so_dst, so_mask; - char *cp = m_rtmsg.m_space; - struct sockaddr *gate = NULL, *sa; - struct rt_msghdr *rtm_aux; - -#define NEXTADDR(w, u) \ - if (rtm_addrs & (w)) {\ - l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\ - } - -#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) - -#define rtm m_rtmsg.m_rtm - - CLEAR(*rgi); - - pid = getpid(); - seq = 0; - rtm_addrs = RTA_DST | RTA_NETMASK; - - bzero(&so_dst, sizeof(so_dst)); - bzero(&so_mask, sizeof(so_mask)); - bzero(&rtm, sizeof(struct rt_msghdr)); - - rtm.rtm_type = RTM_GET; - rtm.rtm_flags = RTF_UP | RTF_GATEWAY; - rtm.rtm_version = RTM_VERSION; - rtm.rtm_seq = ++seq; - rtm.rtm_addrs = rtm_addrs; - - so_dst.sa_family = AF_INET; - so_dst.sa_len = sizeof(struct sockaddr_in); - so_mask.sa_family = AF_INET; - so_mask.sa_len = sizeof(struct sockaddr_in); - - NEXTADDR(RTA_DST, so_dst); - NEXTADDR(RTA_NETMASK, so_mask); - - rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; - - s = socket(PF_ROUTE, SOCK_RAW, 0); - - if (write(s, (char *)&m_rtmsg, l) < 0) - { - msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:"); - gc_free (&gc); - close(s); - return; - } - - do { - l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); - } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); - - close(s); - - rtm_aux = &rtm; - - cp = ((char *)(rtm_aux + 1)); - if (rtm_aux->rtm_addrs) { - for (i = 1; i; i <<= 1) - if (i & rtm_aux->rtm_addrs) { - sa = (struct sockaddr *)cp; - if (i == RTA_GATEWAY ) - gate = sa; - ADVANCE(cp, sa); - } - } - else - { - gc_free (&gc); - return; - } - - - if (gate != NULL ) - { - rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr); - rgi->flags |= RGI_ADDR_DEFINED; - - gc_free (&gc); - } - else - { - gc_free (&gc); - } -} - -#elif defined(TARGET_DARWIN) +#elif defined(TARGET_DARWIN) || \ + defined(TARGET_FREEBSD) || defined(TARGET_DRAGONFLY) || \ + defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) #include #include @@ -2760,8 +2651,25 @@ struct rtmsg { char m_space[512]; }; -#define ROUNDUP(a) \ +/* the route socket code is identical for all 4 supported BSDs and for + * MacOS X (Darwin), with one crucial difference: when going from + * 32 bit to 64 bit, the BSDs increased the structure size but kept + * source code compatibility by keeping the use of "long", while + * MacOS X decided to keep binary compatibility by *changing* the API + * to use "uint32_t", thus 32 bit on all OS X variants + * + * We used to have a large amount of duplicate code here which really + * differed only in this (long) vs. (uint32_t) - IMHO, worse than + * having a combined block for all BSDs with this single #ifdef inside + */ + +#if defined(TARGET_DARWIN) +# define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t)) +#else +# define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#endif #define NEXTADDR(w, u) \ if (rtm_addrs & (w)) {\ @@ -2955,118 +2863,6 @@ get_default_gateway (struct route_gateway_info *rgi) #undef max -#elif defined(TARGET_OPENBSD) || defined(TARGET_NETBSD) - -#include -#include -#include -#include - -struct { - struct rt_msghdr m_rtm; - char m_space[512]; -} m_rtmsg; - -#define ROUNDUP(a) \ - ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) - -/* - * FIXME -- add support for netmask, hwaddr, and iface - */ -void -get_default_gateway (struct route_gateway_info *rgi) -{ - struct gc_arena gc = gc_new (); - int s, seq, l, rtm_addrs, i; - pid_t pid; - struct sockaddr so_dst, so_mask; - char *cp = m_rtmsg.m_space; - struct sockaddr *gate = NULL, *sa; - struct rt_msghdr *rtm_aux; - -#define NEXTADDR(w, u) \ - if (rtm_addrs & (w)) {\ - l = ROUNDUP(u.sa_len); memmove(cp, &(u), l); cp += l;\ - } - -#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) - -#define rtm m_rtmsg.m_rtm - - CLEAR(*rgi); - - pid = getpid(); - seq = 0; - rtm_addrs = RTA_DST | RTA_NETMASK; - - bzero(&so_dst, sizeof(so_dst)); - bzero(&so_mask, sizeof(so_mask)); - bzero(&rtm, sizeof(struct rt_msghdr)); - - rtm.rtm_type = RTM_GET; - rtm.rtm_flags = RTF_UP | RTF_GATEWAY; - rtm.rtm_version = RTM_VERSION; - rtm.rtm_seq = ++seq; - rtm.rtm_addrs = rtm_addrs; - - so_dst.sa_family = AF_INET; - so_dst.sa_len = sizeof(struct sockaddr_in); - so_mask.sa_family = AF_INET; - so_mask.sa_len = sizeof(struct sockaddr_in); - - NEXTADDR(RTA_DST, so_dst); - NEXTADDR(RTA_NETMASK, so_mask); - - rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; - - s = socket(PF_ROUTE, SOCK_RAW, 0); - - if (write(s, (char *)&m_rtmsg, l) < 0) - { - msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:"); - gc_free (&gc); - close(s); - return; - } - - do { - l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); - } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); - - close(s); - - rtm_aux = &rtm; - - cp = ((char *)(rtm_aux + 1)); - if (rtm_aux->rtm_addrs) { - for (i = 1; i; i <<= 1) - if (i & rtm_aux->rtm_addrs) { - sa = (struct sockaddr *)cp; - if (i == RTA_GATEWAY ) - gate = sa; - ADVANCE(cp, sa); - } - } - else - { - gc_free (&gc); - return; - } - - - if (gate != NULL ) - { - rgi->gateway.addr = ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr); - rgi->flags |= RGI_ADDR_DEFINED; - - gc_free (&gc); - } - else - { - gc_free (&gc); - } -} - #else /* diff --git a/main/openvpn/src/openvpn/socket.c b/main/openvpn/src/openvpn/socket.c index 6f822e7d..9e6bd10c 100644 --- a/main/openvpn/src/openvpn/socket.c +++ b/main/openvpn/src/openvpn/socket.c @@ -2967,11 +2967,11 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock, mesg.msg_name = &to->dest.addr.sa; mesg.msg_namelen = sizeof (struct sockaddr_in); mesg.msg_control = &opi; - mesg.msg_controllen = sizeof (struct openvpn_in4_pktinfo); mesg.msg_flags = 0; +#ifdef HAVE_IN_PKTINFO + mesg.msg_controllen = sizeof (struct openvpn_in4_pktinfo); cmsg = CMSG_FIRSTHDR (&mesg); cmsg->cmsg_len = sizeof (struct openvpn_in4_pktinfo); -#ifdef HAVE_IN_PKTINFO cmsg->cmsg_level = SOL_IP; cmsg->cmsg_type = IP_PKTINFO; { @@ -2982,6 +2982,10 @@ link_socket_write_udp_posix_sendmsg (struct link_socket *sock, pkti->ipi_addr.s_addr = 0; } #elif defined(IP_RECVDSTADDR) + ASSERT( CMSG_SPACE(sizeof (struct in_addr)) <= sizeof(opi) ); + mesg.msg_controllen = CMSG_SPACE(sizeof (struct in_addr)); + cmsg = CMSG_FIRSTHDR (&mesg); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_RECVDSTADDR; *(struct in_addr *) CMSG_DATA (cmsg) = to->pi.in4; diff --git a/main/openvpn/src/openvpn/ssl.c b/main/openvpn/src/openvpn/ssl.c index 9bcb2acb..95bbb277 100644 --- a/main/openvpn/src/openvpn/ssl.c +++ b/main/openvpn/src/openvpn/ssl.c @@ -35,7 +35,6 @@ * Both the TLS session and the data channel are multiplexed * over the same TCP/UDP port. */ - #ifdef HAVE_CONFIG_H #include "config.h" #elif defined(_MSC_VER) @@ -48,7 +47,6 @@ #include "error.h" #include "common.h" -#include "integer.h" #include "socket.h" #include "misc.h" #include "fdmisc.h" @@ -57,8 +55,6 @@ #include "status.h" #include "gremlin.h" #include "pkcs11.h" -#include "list.h" -#include "base64.h" #include "route.h" #include "ssl.h" @@ -841,6 +837,25 @@ static inline void tls_session_set_self_referential_pointers (struct tls_session session->tls_auth.packet_id = &session->tls_auth_pid; } +/** + * Returns whether or not the server should check for username/password + * + * @param session The current TLS session + * + * @return true if username and password verification is enabled, + * false if not. + */ +static inline bool +tls_session_user_pass_enabled(struct tls_session *session) +{ + return (session->opt->auth_user_pass_verify_script + || plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) +#ifdef MANAGEMENT_DEF_AUTH + || management_enable_def_auth (management) +#endif + ); +} + /** @addtogroup control_processor * @{ */ @@ -2073,7 +2088,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi output_peer_info_env (session->opt->es, multi->peer_info); #endif - if (verify_user_pass_enabled(session)) + if (tls_session_user_pass_enabled(session)) { /* Perform username/password authentication */ if (!username_status || !password_status) diff --git a/main/openvpn/src/openvpn/ssl.h b/main/openvpn/src/openvpn/ssl.h index cd7cae2e..aaecff43 100644 --- a/main/openvpn/src/openvpn/ssl.h +++ b/main/openvpn/src/openvpn/ssl.h @@ -44,7 +44,6 @@ #include "plugin.h" #include "ssl_common.h" -#include "ssl_verify.h" #include "ssl_backend.h" /* Used in the TLS PRF function */ diff --git a/main/openvpn/src/openvpn/ssl_backend.h b/main/openvpn/src/openvpn/ssl_backend.h index 37a458cc..bfd15496 100644 --- a/main/openvpn/src/openvpn/ssl_backend.h +++ b/main/openvpn/src/openvpn/ssl_backend.h @@ -485,6 +485,6 @@ void get_highest_preference_tls_cipher (char *buf, int size); * return a pointer to a static memory area containing the * name and version number of the SSL library in use */ -char * get_ssl_library_version(void); +const char * get_ssl_library_version(void); #endif /* SSL_BACKEND_H_ */ diff --git a/main/openvpn/src/openvpn/ssl_openssl.c b/main/openvpn/src/openvpn/ssl_openssl.c index 5ab34151..c9d2d26d 100644 --- a/main/openvpn/src/openvpn/ssl_openssl.c +++ b/main/openvpn/src/openvpn/ssl_openssl.c @@ -56,7 +56,9 @@ #include #include #include +#ifndef OPENSSL_NO_EC #include +#endif /* * Allocate space in SSL objects in which to store a struct tls_session @@ -196,6 +198,9 @@ tls_ctx_set_options (struct tls_root_ctx *ctx, unsigned int ssl_flags) SSL_CTX_set_options (ctx->ctx, sslopt); } +#ifdef SSL_MODE_RELEASE_BUFFERS + SSL_CTX_set_mode (ctx->ctx, SSL_MODE_RELEASE_BUFFERS); +#endif SSL_CTX_set_session_cache_mode (ctx->ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_default_passwd_cb (ctx->ctx, pem_password_callback); @@ -334,6 +339,7 @@ void tls_ctx_load_ecdh_params (struct tls_root_ctx *ctx, const char *curve_name ) { +#ifndef OPENSSL_NO_EC int nid = NID_undef; EC_KEY *ecdh = NULL; const char *sname = NULL; @@ -395,6 +401,10 @@ tls_ctx_load_ecdh_params (struct tls_root_ctx *ctx, const char *curve_name msg (D_TLS_DEBUG_LOW, "ECDH curve %s added", sname); EC_KEY_free(ecdh); +#else + msg (M_DEBUG, "Your OpenSSL library was built without elliptic curve support." + " Skipping ECDH parameter loading."); +#endif /* OPENSSL_NO_EC */ } int @@ -1374,6 +1384,7 @@ show_available_tls_ciphers (const char *cipher_list) void show_available_curves() { +#ifndef OPENSSL_NO_EC EC_builtin_curve *curves = NULL; size_t crv_len = 0; size_t n = 0; @@ -1404,6 +1415,10 @@ show_available_curves() } OPENSSL_free(curves); } +#else + msg (M_WARN, "Your OpenSSL library was built without elliptic curve support. " + "No curves available."); +#endif } void @@ -1427,7 +1442,7 @@ get_highest_preference_tls_cipher (char *buf, int size) SSL_CTX_free (ctx); } -char * +const char * get_ssl_library_version(void) { return SSLeay_version(SSLEAY_VERSION); diff --git a/main/openvpn/src/openvpn/ssl_polarssl.c b/main/openvpn/src/openvpn/ssl_polarssl.c index 79c5087b..ddccf1d9 100644 --- a/main/openvpn/src/openvpn/ssl_polarssl.c +++ b/main/openvpn/src/openvpn/ssl_polarssl.c @@ -232,7 +232,9 @@ void tls_ctx_load_ecdh_params (struct tls_root_ctx *ctx, const char *curve_name ) { - msg(M_WARN, "Elliptic Curves not yet supported by PolarSSL"); + if (NULL != curve_name) + msg(M_WARN, "WARNING: PolarSSL builds do not support specifying an ECDH " + "curve, using default curves."); } int @@ -1093,7 +1095,18 @@ show_available_tls_ciphers (const char *cipher_list) void show_available_curves (void) { - printf("The PolarSSL build of OpenVPN does not support elliptic curves yet"); + const ecp_curve_info *pcurve = ecp_curve_list(); + + if (NULL == pcurve) + msg (M_FATAL, "Cannot retrieve curve list from PolarSSL"); + + /* Print curve list */ + printf ("Available Elliptic curves, listed in order of preference:\n\n"); + while (POLARSSL_ECP_DP_NONE != pcurve->grp_id) + { + printf("%s\n", pcurve->name); + pcurve++; + } } void @@ -1108,7 +1121,7 @@ get_highest_preference_tls_cipher (char *buf, int size) strncpynt (buf, cipher_name, size); } -char * +const char * get_ssl_library_version(void) { static char polar_version[30]; diff --git a/main/openvpn/src/openvpn/ssl_verify.c b/main/openvpn/src/openvpn/ssl_verify.c index 7a9a56ef..2d10d155 100644 --- a/main/openvpn/src/openvpn/ssl_verify.c +++ b/main/openvpn/src/openvpn/ssl_verify.c @@ -435,6 +435,11 @@ verify_cert_set_env(struct env_set *es, openvpn_x509_cert_t *peer_cert, int cert openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", cert_depth); setenv_str (es, envname, serial); + /* export serial number in hex as environmental variable */ + serial = backend_x509_get_serial_hex(peer_cert, &gc); + openvpn_snprintf (envname, sizeof(envname), "tls_serial_hex_%d", cert_depth); + setenv_str (es, envname, serial); + gc_free(&gc); } diff --git a/main/openvpn/src/openvpn/ssl_verify.h b/main/openvpn/src/openvpn/ssl_verify.h index e0bcba42..84554f89 100644 --- a/main/openvpn/src/openvpn/ssl_verify.h +++ b/main/openvpn/src/openvpn/ssl_verify.h @@ -30,9 +30,10 @@ #ifndef SSL_VERIFY_H_ #define SSL_VERIFY_H_ +#if defined(ENABLE_CRYPTO) && defined(ENABLE_SSL) + #include "syshead.h" #include "misc.h" -#include "manage.h" #include "ssl_common.h" /* Include OpenSSL-specific code */ @@ -165,25 +166,6 @@ tls_common_name_hash (const struct tls_multi *multi, const char **cn, uint32_t * #endif -/** - * Returns whether or not the server should check for username/password - * - * @param session The current TLS session - * - * @return true if username and password verification is enabled, - * false if not. - * - */ -static inline bool verify_user_pass_enabled(struct tls_session *session) -{ - return (session->opt->auth_user_pass_verify_script - || plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) -#ifdef MANAGEMENT_DEF_AUTH - || management_enable_def_auth (management) -#endif - ); -} - /** * Verify the given username and password, using either an external script, a * plugin, or the management interface. @@ -254,5 +236,6 @@ tls_client_reason (struct tls_multi *multi) #endif } -#endif /* SSL_VERIFY_H_ */ +#endif /* defined(ENABLE_CRYPTO) && defined(ENABLE_SSL) */ +#endif /* SSL_VERIFY_H_ */ diff --git a/main/openvpn/src/openvpn/ssl_verify_backend.h b/main/openvpn/src/openvpn/ssl_verify_backend.h index fa4369d2..4e9ad60f 100644 --- a/main/openvpn/src/openvpn/ssl_verify_backend.h +++ b/main/openvpn/src/openvpn/ssl_verify_backend.h @@ -113,17 +113,32 @@ result_t backend_x509_get_username (char *common_name, int cn_len, char * x509_username_field, openvpn_x509_cert_t *peer_cert); /* - * Return the certificate's serial number. + * Return the certificate's serial number in decimal string representation. * * The serial number is returned as a string, since it might be a bignum. * * @param cert Certificate to retrieve the serial number from. * @param gc Garbage collection arena to use when allocating string. * - * @return The certificate's serial number. + * @return String representation of the certificate's serial number + * in decimal notation, or NULL on error. */ char *backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc); +/* + * Return the certificate's serial number in hex string representation. + * + * The serial number is returned as a string, since it might be a bignum. + * + * @param cert Certificate to retrieve the serial number from. + * @param gc Garbage collection arena to use when allocating string. + * + * @return String representation of the certificate's serial number + * in hex notation, or NULL on error. + */ +char *backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, + struct gc_arena *gc); + /* * Save X509 fields to environment, using the naming convention: * diff --git a/main/openvpn/src/openvpn/ssl_verify_openssl.c b/main/openvpn/src/openvpn/ssl_verify_openssl.c index a9205f31..2482eaa4 100644 --- a/main/openvpn/src/openvpn/ssl_verify_openssl.c +++ b/main/openvpn/src/openvpn/ssl_verify_openssl.c @@ -37,9 +37,13 @@ #if defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_OPENSSL) +#include "ssl_verify_openssl.h" + +#include "error.h" +#include "ssl_openssl.h" #include "ssl_verify.h" #include "ssl_verify_backend.h" -#include "ssl_openssl.h" + #include #include @@ -238,10 +242,18 @@ backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc) return serial; } +char * +backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, struct gc_arena *gc) +{ + const ASN1_INTEGER *asn1_i = X509_get_serialNumber(cert); + + return format_hex_ex(asn1_i->data, asn1_i->length, 0, 1, ":", gc); +} + unsigned char * x509_get_sha1_hash (X509 *cert, struct gc_arena *gc) { - char *hash = gc_malloc(SHA_DIGEST_LENGTH, false, gc); + unsigned char *hash = gc_malloc(SHA_DIGEST_LENGTH, false, gc); memcpy(hash, cert->sha1_hash, SHA_DIGEST_LENGTH); return hash; } diff --git a/main/openvpn/src/openvpn/ssl_verify_polarssl.c b/main/openvpn/src/openvpn/ssl_verify_polarssl.c index 1b2990c7..71d38a9d 100644 --- a/main/openvpn/src/openvpn/ssl_verify_polarssl.c +++ b/main/openvpn/src/openvpn/ssl_verify_polarssl.c @@ -38,6 +38,8 @@ #if defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_POLARSSL) #include "ssl_verify.h" +#include +#include #include #include @@ -124,7 +126,45 @@ backend_x509_get_username (char *cn, int cn_len, } char * -backend_x509_get_serial (x509_crt *cert, struct gc_arena *gc) +backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc) +{ + char *buf = NULL; + size_t buflen = 0; + mpi serial_mpi = { 0 }; + int retval = 0; + + /* Transform asn1 integer serial into PolarSSL MPI */ + mpi_init(&serial_mpi); + retval = mpi_read_binary(&serial_mpi, cert->serial.p, cert->serial.len); + if (retval < 0) + { + char errbuf[128]; + polarssl_strerror(retval, errbuf, sizeof(errbuf)); + + msg(M_WARN, "Failed to retrieve serial from certificate: %s.", errbuf); + return NULL; + } + + /* Determine decimal representation length, allocate buffer */ + mpi_write_string(&serial_mpi, 10, buf, &buflen); + buf = gc_malloc(buflen, true, gc); + + /* Write MPI serial as decimal string into buffer */ + retval = mpi_write_string(&serial_mpi, 10, buf, &buflen); + if (retval < 0) + { + char errbuf[128]; + polarssl_strerror(retval, errbuf, sizeof(errbuf)); + + msg(M_WARN, "Failed to write serial to string: %s.", errbuf); + return NULL; + } + + return buf; +} + +char * +backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, struct gc_arena *gc) { char *buf = NULL; size_t len = cert->serial.len * 3 + 1; diff --git a/main/openvpn/src/openvpn/ssl_verify_polarssl.h b/main/openvpn/src/openvpn/ssl_verify_polarssl.h index b5157ed1..2076f2ef 100644 --- a/main/openvpn/src/openvpn/ssl_verify_polarssl.h +++ b/main/openvpn/src/openvpn/ssl_verify_polarssl.h @@ -31,8 +31,6 @@ #define SSL_VERIFY_POLARSSL_H_ #include "syshead.h" -#include "misc.h" -#include "manage.h" #include #ifndef __OPENVPN_X509_CERT_T_DECLARED diff --git a/main/openvpn/src/plugins/auth-pam/Makefile.am b/main/openvpn/src/plugins/auth-pam/Makefile.am index 701a7497..2aef311a 100644 --- a/main/openvpn/src/plugins/auth-pam/Makefile.am +++ b/main/openvpn/src/plugins/auth-pam/Makefile.am @@ -8,8 +8,9 @@ MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in AM_CFLAGS = \ - -I$(top_srcdir)/include - $(PLUGIN_AUTH_PAM_CFLAGS) + -I$(top_srcdir)/include \ + $(PLUGIN_AUTH_PAM_CFLAGS) \ + $(OPTIONAL_CRYPTO_CFLAGS) if ENABLE_PLUGIN_AUTH_PAM plugin_LTLIBRARIES = openvpn-plugin-auth-pam.la diff --git a/main/openvpn/src/plugins/down-root/Makefile.am b/main/openvpn/src/plugins/down-root/Makefile.am index 064aa30c..7ca5a4e1 100644 --- a/main/openvpn/src/plugins/down-root/Makefile.am +++ b/main/openvpn/src/plugins/down-root/Makefile.am @@ -8,7 +8,8 @@ MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in AM_CFLAGS = \ - -I$(top_srcdir)/include + -I$(top_srcdir)/include \ + $(OPTIONAL_CRYPTO_CFLAGS) if ENABLE_PLUGIN_DOWN_ROOT plugin_LTLIBRARIES = openvpn-plugin-down-root.la -- cgit v1.2.3