From 5304543ebd60778ad46123cd63142e27627fa150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parm=C3=A9nides=20GV?= Date: Tue, 4 Nov 2014 20:45:42 +0100 Subject: Update ics-openvpn to rev 906. --- app/openvpn/config-version.h | 2 +- app/openvpn/config.h | 2 + app/openvpn/configure.ac | 27 +++++++++- app/openvpn/contrib/OCSP_check/OCSP_check.sh | 13 +++-- app/openvpn/distro/systemd/openvpn@.service | 19 +++++++ app/openvpn/doc/android.txt | 24 +++++---- app/openvpn/src/openvpn/Makefile.am | 1 + app/openvpn/src/openvpn/base64.c | 2 +- app/openvpn/src/openvpn/console.c | 16 +++--- app/openvpn/src/openvpn/crypto.c | 80 ++++++++++------------------ app/openvpn/src/openvpn/crypto_backend.h | 4 +- app/openvpn/src/openvpn/forward.c | 9 ++++ app/openvpn/src/openvpn/init.c | 12 ++++- app/openvpn/src/openvpn/misc.c | 21 +++++--- app/openvpn/src/openvpn/mudp.c | 37 +++++-------- app/openvpn/src/openvpn/multi.c | 26 ++++----- app/openvpn/src/openvpn/options.c | 22 ++++---- app/openvpn/src/openvpn/options.h | 4 ++ app/openvpn/src/openvpn/plugin.c | 2 +- app/openvpn/src/openvpn/push.c | 14 +++-- app/openvpn/src/openvpn/route.c | 24 +++++++-- app/openvpn/src/openvpn/sig.c | 2 +- app/openvpn/src/openvpn/socket.c | 4 +- app/openvpn/src/openvpn/ssl.c | 13 +++-- app/openvpn/src/openvpn/ssl.h | 2 +- app/openvpn/src/openvpn/ssl_common.h | 4 +- app/openvpn/src/openvpn/ssl_polarssl.c | 32 ++++++----- app/openvpn/src/openvpn/ssl_verify_openssl.c | 6 +-- app/openvpn/src/openvpn/tun.h | 19 +++++++ 29 files changed, 271 insertions(+), 172 deletions(-) create mode 100644 app/openvpn/distro/systemd/openvpn@.service (limited to 'app/openvpn') diff --git a/app/openvpn/config-version.h b/app/openvpn/config-version.h index 762b9dc6..6e78aeaf 100644 --- a/app/openvpn/config-version.h +++ b/app/openvpn/config-version.h @@ -1,2 +1,2 @@ -#define CONFIGURE_GIT_REVISION "icsopenvpn_618-e63b88d330782d14" +#define CONFIGURE_GIT_REVISION "icsopenvpn_620-df00abd6979b7376" #define CONFIGURE_GIT_FLAGS "" diff --git a/app/openvpn/config.h b/app/openvpn/config.h index b825e2bd..6b699028 100644 --- a/app/openvpn/config.h +++ b/app/openvpn/config.h @@ -631,3 +631,5 @@ #define IPPROTO_IP IPPROTO_IP #define IPPROTO_TCP IPPROTO_TCP + +#define HAVE_AEAD_CIPHER_MODES 1 diff --git a/app/openvpn/configure.ac b/app/openvpn/configure.ac index ffba3749..608ab6d1 100644 --- a/app/openvpn/configure.ac +++ b/app/openvpn/configure.ac @@ -368,15 +368,18 @@ AC_ARG_VAR([IPROUTE], [full path to ip utility]) AC_ARG_VAR([NETSTAT], [path to netstat utility]) # tests AC_ARG_VAR([MAN2HTML], [path to man2html utility]) AC_ARG_VAR([GIT], [path to git utility]) +AC_ARG_VAR([SYSTEMD_ASK_PASSWORD], [path to systemd-ask-password utility]) AC_PATH_PROGS([IFCONFIG], [ifconfig],, [$PATH:/usr/local/sbin:/usr/sbin:/sbin]) AC_PATH_PROGS([ROUTE], [route],, [$PATH:/usr/local/sbin:/usr/sbin:/sbin]) AC_PATH_PROGS([IPROUTE], [ip],, [$PATH:/usr/local/sbin:/usr/sbin:/sbin]) +AC_PATH_PROGS([SYSTEMD_ASK_PASSWORD], [systemd-ask-password],, [$PATH:/usr/local/bin:/usr/bin:/bin]) AC_CHECK_PROGS([NETSTAT], [netstat], [netstat], [$PATH:/usr/local/sbin:/usr/sbin:/sbin:/etc]) # tests AC_CHECK_PROGS([MAN2HTML], [man2html]) AC_CHECK_PROGS([GIT], [git]) # optional AC_DEFINE_UNQUOTED([IFCONFIG_PATH], ["$IFCONFIG"], [Path to ifconfig tool]) AC_DEFINE_UNQUOTED([IPROUTE_PATH], ["$IPROUTE"], [Path to iproute tool]) AC_DEFINE_UNQUOTED([ROUTE_PATH], ["$ROUTE"], [Path to route tool]) +AC_DEFINE_UNQUOTED([SYSTEMD_ASK_PASSWORD_PATH], ["$SYSTEMD_ASK_PASSWORD"], [Path to systemd-ask-password tool]) # # Libtool @@ -994,6 +997,28 @@ if test "$enable_lz4" = "yes" && test "$enable_comp_stub" = "no"; then fi +dnl +dnl Check for systemd +dnl + +if test "$enable_systemd" = "yes" ; then + PKG_CHECK_MODULES([libsystemd], [systemd libsystemd], + [], + [PKG_CHECK_MODULES([libsystemd], [libsystemd-daemon])] + ) + AC_CHECK_HEADERS(systemd/sd-daemon.h, + , + [ + AC_MSG_ERROR([systemd development headers not found.]) + ]) + + saved_LIBS="${LIBS}" + LIBS="${LIBS} ${libsystemd_LIBS}" + AC_CHECK_FUNCS([sd_booted], [], [AC_MSG_ERROR([systemd library is missing sd_booted()])]) + OPTIONAL_SYSTEMD_LIBS="${libsystemd_LIBS}" + AC_DEFINE(ENABLE_SYSTEMD, 1, [Enable systemd integration]) + LIBS="${saved_LIBS}" +fi AC_MSG_CHECKING([git checkout]) @@ -1034,7 +1059,6 @@ test "${enable_def_auth}" = "yes" && AC_DEFINE([ENABLE_DEF_AUTH], [1], [Enable d test "${enable_pf}" = "yes" && AC_DEFINE([ENABLE_PF], [1], [Enable internal packet filter]) test "${enable_strict_options}" = "yes" && AC_DEFINE([ENABLE_STRICT_OPTIONS_CHECK], [1], [Enable strict options check between peers]) test "${enable_password_save}" = "yes" && AC_DEFINE([ENABLE_PASSWORD_SAVE], [1], [Allow --askpass and --auth-user-pass passwords to be read from a file]) -test "${enable_systemd}" = "yes" && AC_DEFINE([ENABLE_SYSTEMD], [1], [Enable systemd support]) case "${with_crypto_library}" in openssl) @@ -1167,6 +1191,7 @@ AC_SUBST([OPTIONAL_SNAPPY_CFLAGS]) AC_SUBST([OPTIONAL_SNAPPY_LIBS]) AC_SUBST([OPTIONAL_LZ4_CFLAGS]) AC_SUBST([OPTIONAL_LZ4_LIBS]) +AC_SUBST([OPTIONAL_SYSTEMD_LIBS]) AC_SUBST([OPTIONAL_PKCS11_HELPER_CFLAGS]) AC_SUBST([OPTIONAL_PKCS11_HELPER_LIBS]) diff --git a/app/openvpn/contrib/OCSP_check/OCSP_check.sh b/app/openvpn/contrib/OCSP_check/OCSP_check.sh index 553c3dce..6876c6d8 100644 --- a/app/openvpn/contrib/OCSP_check/OCSP_check.sh +++ b/app/openvpn/contrib/OCSP_check/OCSP_check.sh @@ -97,12 +97,19 @@ if [ $check_depth -eq -1 ] || [ $cur_depth -eq $check_depth ]; then "$nonce" \ -CAfile "$verify" \ -url "$ocsp_url" \ - -serial "${serial}" 2>/dev/null) + -serial "${serial}" 2>&1) if [ $? -eq 0 ]; then - # check that it's good + # check if ocsp didn't report any errors + if echo "$status" | grep -Eq "(error|fail)"; then + exit 1 + fi + # check that the reported status of certificate is ok if echo "$status" | grep -Fq "^${serial}: good"; then - exit 0 + # check if signature on the OCSP response verified correctly + if echo "$status" | grep -Fq "^Response verify OK"; then + exit 0 + fi fi fi fi diff --git a/app/openvpn/distro/systemd/openvpn@.service b/app/openvpn/distro/systemd/openvpn@.service new file mode 100644 index 00000000..7cd36c36 --- /dev/null +++ b/app/openvpn/distro/systemd/openvpn@.service @@ -0,0 +1,19 @@ +[Unit] +Description=OpenVPN tunnel for %I +After=syslog.target network.target +Documentation=man:openvpn(8) +Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn23ManPage +Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO + +[Service] +PrivateTmp=true +Type=forking +PIDFile=/var/run/openvpn/%i.pid +ExecStart=/usr/sbin/openvpn --daemon --writepid /var/run/openvpn/%i.pid --cd /etc/openvpn/ --config %i.conf +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_READ_SEARCH +LimitNPROC=10 +DeviceAllow=/dev/null rw +DeviceAllow=/dev/net/tun rw + +[Install] +WantedBy=multi-user.target diff --git a/app/openvpn/doc/android.txt b/app/openvpn/doc/android.txt index cf8b3c79..137edfc5 100644 --- a/app/openvpn/doc/android.txt +++ b/app/openvpn/doc/android.txt @@ -55,6 +55,21 @@ To set the DNS server and search domain. The GUI will then respond with a "needok 'command' ok' or "needok 'command' cancel', e.g. "needok 'IFCONFIG' ok". +PERSIST_TUN_ACTION + +In Android 4.4-4.4.2 a bug exists that does not allow to open a new tun fd +while a tun fd is still open. When OpenVPN wants to open an fd it will do +this query. The UI should compare the last configuration of +the tun device with the current tun configuration and reply with either (or +always respond with OPEN_AFTER_BEFORE/OPEN_BEFORE_CLOSE) + +- NOACTION: Keep using the old fd +- OPEN_AFTER_CLOSE: First close the old fd and then open a new to workaround the bug +- OPEN_BEFORE_CLOSE: the normal behaviour when the VPN configuration changed + +For example the UI could respond with +needok 'PERSIST_TUN_ACTION' OPEN_AFTER_CLOSE + To protect a socket the OpenVPN will send a PROTECTFD to the UI. When sending the PROTECTFD command command to the UI it will send the fd of the socket as ancillary message over the UNIX socket. @@ -74,12 +89,3 @@ are not specific to Android but are rarely used on other platform. For example using SIGUSR1 and management-hold to restart, pause, continue the VPN on network changes or the external key management --management-external-key option and inline files. - -Due to a bug in Android 4.4-4.4.2 there the Android Control will also -query what action the daemon should take when opening the fd. The GUI -should compare the last configuration of the tun device with the current -tun configuration and reply with either - -- NOACTION: Keep using the old fd -- OPEN_AFTER_CLOSE: First close the old fd and then open a new to workaround the bug -- OPEN_BEFORE_CLOSE: the normal behaviour when the VPN configuration changed diff --git a/app/openvpn/src/openvpn/Makefile.am b/app/openvpn/src/openvpn/Makefile.am index fd593c57..d089f50f 100644 --- a/app/openvpn/src/openvpn/Makefile.am +++ b/app/openvpn/src/openvpn/Makefile.am @@ -126,6 +126,7 @@ openvpn_LDADD = \ $(OPTIONAL_PKCS11_HELPER_LIBS) \ $(OPTIONAL_CRYPTO_LIBS) \ $(OPTIONAL_SELINUX_LIBS) \ + $(OPTIONAL_SYSTEMD_LIBS) \ $(OPTIONAL_DL_LIBS) if WIN32 openvpn_SOURCES += openvpn_win32_resources.rc diff --git a/app/openvpn/src/openvpn/base64.c b/app/openvpn/src/openvpn/base64.c index 6dc8479f..258b258e 100644 --- a/app/openvpn/src/openvpn/base64.c +++ b/app/openvpn/src/openvpn/base64.c @@ -108,7 +108,7 @@ token_decode(const char *token) int i; unsigned int val = 0; int marker = 0; - if (strlen(token) < 4) + if (!token[0] || !token[1] || !token[2] || !token[3]) return DECODE_ERROR; for (i = 0; i < 4; i++) { val *= 64; diff --git a/app/openvpn/src/openvpn/console.c b/app/openvpn/src/openvpn/console.c index afda8ca3..d66d4087 100644 --- a/app/openvpn/src/openvpn/console.c +++ b/app/openvpn/src/openvpn/console.c @@ -34,6 +34,10 @@ #include "buffer.h" #include "misc.h" +#ifdef ENABLE_SYSTEMD +#include +#endif + #ifdef WIN32 #include "win32.h" @@ -143,14 +147,14 @@ close_tty (FILE *fp) static bool check_systemd_running () { - struct stat a, b; + struct stat c; /* We simply test whether the systemd cgroup hierarchy is - * mounted */ + * mounted, as well as the systemd-ask-password executable + * being available */ - return (lstat("/sys/fs/cgroup", &a) == 0) - && (lstat("/sys/fs/cgroup/systemd", &b) == 0) - && (a.st_dev != b.st_dev); + return (sd_booted() > 0) + && (stat(SYSTEMD_ASK_PASSWORD_PATH, &c) == 0); } @@ -162,7 +166,7 @@ get_console_input_systemd (const char *prompt, const bool echo, char *input, con struct argv argv; argv_init (&argv); - argv_printf (&argv, "/bin/systemd-ask-password"); + argv_printf (&argv, SYSTEMD_ASK_PASSWORD_PATH); argv_printf_cat (&argv, "%s", prompt); if ((std_out = openvpn_popen (&argv, NULL)) < 0) { diff --git a/app/openvpn/src/openvpn/crypto.c b/app/openvpn/src/openvpn/crypto.c index 62c4ab28..69df29de 100644 --- a/app/openvpn/src/openvpn/crypto.c +++ b/app/openvpn/src/openvpn/crypto.c @@ -223,6 +223,30 @@ err: return; } +int verify_hmac(struct buffer *buf, struct key_ctx *ctx, int offset) +{ + uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ + int hmac_len = 0; + + hmac_ctx_reset(ctx->hmac); + /* Assume the length of the input HMAC */ + hmac_len = hmac_ctx_size (ctx->hmac); + + /* Authentication fails if insufficient data in packet for HMAC */ + if (buf->len - offset < hmac_len) + return 0; + + hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len + offset, + BLEN (buf) - hmac_len - offset); + hmac_ctx_final (ctx->hmac, local_hmac); + + /* Compare locally computed HMAC with packet HMAC */ + if (memcmp_constant_time (local_hmac, BPTR (buf) + offset, hmac_len) == 0) + return hmac_len; + + return 0; +} + /* * If (opt->flags & CO_USE_IV) is not NULL, we will read an IV from the packet. * @@ -249,25 +273,9 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, /* Verify the HMAC */ if (ctx->hmac) { - int hmac_len; - uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ - - hmac_ctx_reset(ctx->hmac); - - /* Assume the length of the input HMAC */ - hmac_len = hmac_ctx_size (ctx->hmac); - - /* Authentication fails if insufficient data in packet for HMAC */ - if (buf->len < hmac_len) - CRYPT_ERROR ("missing authentication info"); - - hmac_ctx_update (ctx->hmac, BPTR (buf) + hmac_len, BLEN (buf) - hmac_len); - hmac_ctx_final (ctx->hmac, local_hmac); - - /* Compare locally computed HMAC with packet HMAC */ - if (memcmp_constant_time (local_hmac, BPTR (buf), hmac_len)) + int hmac_len = verify_hmac(buf, ctx, 0); + if (hmac_len == 0) CRYPT_ERROR ("packet HMAC authentication failed"); - ASSERT (buf_advance (buf, hmac_len)); } @@ -399,10 +407,6 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, bool crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt) { - struct gc_arena gc; - gc_init (&gc); - int offset = 4; /* 1 byte opcode + 3 bytes session-id */ - if (buf->len > 0 && opt->key_ctx_bi) { struct key_ctx *ctx = &opt->key_ctx_bi->decrypt; @@ -410,38 +414,10 @@ crypto_test_hmac (struct buffer *buf, const struct crypto_options *opt) /* Verify the HMAC */ if (ctx->hmac) { - int hmac_len; - uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */ - - hmac_ctx_reset(ctx->hmac); - - /* Assume the length of the input HMAC */ - hmac_len = hmac_ctx_size (ctx->hmac); - - /* Authentication fails if insufficient data in packet for HMAC */ - if ((buf->len - offset) < hmac_len) - { - gc_free (&gc); - return false; - } - - hmac_ctx_update (ctx->hmac, BPTR (buf) + offset + hmac_len, - BLEN (buf) - offset - hmac_len); - hmac_ctx_final (ctx->hmac, local_hmac); - - /* Compare locally computed HMAC with packet HMAC */ - if (memcmp (local_hmac, BPTR (buf) + offset, hmac_len)) - { - gc_free (&gc); - return false; - } - - gc_free (&gc); - return true; + /* sizeof(uint32_t) comes from peer_id (3 bytes) and opcode (1 byte) */ + return verify_hmac(buf, ctx, sizeof(uint32_t)) != 0; } } - - gc_free (&gc); return false; } diff --git a/app/openvpn/src/openvpn/crypto_backend.h b/app/openvpn/src/openvpn/crypto_backend.h index a48ad6c5..bc067a7d 100644 --- a/app/openvpn/src/openvpn/crypto_backend.h +++ b/app/openvpn/src/openvpn/crypto_backend.h @@ -231,7 +231,7 @@ 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. + * Check if the supplied cipher is a supported CBC mode cipher. * * @param cipher Static cipher parameters. May not be NULL. * @@ -241,7 +241,7 @@ 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. + * Check if the supplied cipher is a supported OFB or CFB mode cipher. * * @param cipher Static cipher parameters. May not be NULL. * diff --git a/app/openvpn/src/openvpn/forward.c b/app/openvpn/src/openvpn/forward.c index a43361b4..0bbdedb0 100644 --- a/app/openvpn/src/openvpn/forward.c +++ b/app/openvpn/src/openvpn/forward.c @@ -948,6 +948,15 @@ read_incoming_tun (struct context *c) return; } + /* Was TUN/TAP I/O operation aborted? */ + if (tuntap_abort(c->c2.buf.len)) + { + register_signal(c, SIGTERM, "tun-abort"); + msg(M_FATAL, "TUN/TAP I/O operation aborted, exiting"); + perf_pop(); + return; + } + /* Check the status return from read() */ check_status (c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap); diff --git a/app/openvpn/src/openvpn/init.c b/app/openvpn/src/openvpn/init.c index 6137588d..7cec8d9b 100644 --- a/app/openvpn/src/openvpn/init.c +++ b/app/openvpn/src/openvpn/init.c @@ -1718,7 +1718,8 @@ pull_permission_mask (const struct context *c) | OPT_P_MESSAGES | OPT_P_EXPLICIT_NOTIFY | OPT_P_ECHO - | OPT_P_PULL_MODE; + | OPT_P_PULL_MODE + | OPT_P_PEER_ID; if (!c->options.route_nopull) flags |= (OPT_P_ROUTE | OPT_P_IPWIN32); @@ -1795,6 +1796,13 @@ do_deferred_options (struct context *c, const unsigned int found) msg (D_PUSH, "OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified"); if (found & OPT_P_SETENV) msg (D_PUSH, "OPTIONS IMPORT: environment modified"); + + if (found & OPT_P_PEER_ID) + { + msg (D_PUSH, "OPTIONS IMPORT: peer-id set"); + c->c2.tls_multi->use_peer_id = true; + c->c2.tls_multi->peer_id = c->options.peer_id; + } } /* @@ -3179,7 +3187,7 @@ managmenet_callback_network_change (void *arg) reestablishing the connection is required */ socketfd = c->c2.link_socket->sd; - if (!c->options.pull || c->c2.tls_multi->use_session_id) + if (!c->options.pull || c->c2.tls_multi->use_peer_id) return socketfd; else return -2; diff --git a/app/openvpn/src/openvpn/misc.c b/app/openvpn/src/openvpn/misc.c index 63b4c1cf..61bc523d 100644 --- a/app/openvpn/src/openvpn/misc.c +++ b/app/openvpn/src/openvpn/misc.c @@ -365,24 +365,29 @@ openvpn_popen (const struct argv *a, const struct env_set *es) pid = fork (); if (pid == (pid_t)0) /* child side */ { - close (pipe_stdout[0]); + close (pipe_stdout[0]); /* Close read end */ dup2 (pipe_stdout[1],1); execve (cmd, argv, envp); exit (127); } - else if (pid < (pid_t)0) /* fork failed */ + else if (pid > (pid_t)0) /* parent side */ { - msg (M_ERR, "openvpn_popen: unable to fork"); + int status = 0; + + close (pipe_stdout[1]); /* Close write end */ + waitpid(pid, &status, 0); + ret = pipe_stdout[0]; } - else /* parent side */ + else /* fork failed */ { - ret=pipe_stdout[0]; - close (pipe_stdout[1]); + close (pipe_stdout[0]); + close (pipe_stdout[1]); + msg (M_ERR, "openvpn_popen: unable to fork %s", cmd); } } else { - msg (M_WARN, "openvpn_popen: unable to create stdout pipe"); - ret = -1; + msg (M_WARN, "openvpn_popen: unable to create stdout pipe for %s", cmd); + ret = -1; } } else if (!warn_shown && (script_security < SSEC_SCRIPTS)) diff --git a/app/openvpn/src/openvpn/mudp.c b/app/openvpn/src/openvpn/mudp.c index f7ab6253..51227a90 100644 --- a/app/openvpn/src/openvpn/mudp.c +++ b/app/openvpn/src/openvpn/mudp.c @@ -105,29 +105,29 @@ multi_get_create_instance_udp (struct multi_context *m) struct hash_element *he; const uint32_t hv = hash_value (hash, &real); struct hash_bucket *bucket = hash_bucket (hash, hv); - uint8_t* ptr = BPTR(&m->top.c2.buf); + uint8_t* ptr = BPTR(&m->top.c2.buf); uint8_t op = ptr[0] >> P_OPCODE_SHIFT; - uint32_t sess_id; - bool session_forged = false; + uint32_t peer_id; + bool hmac_mismatch = false; if (op == P_DATA_V2) { - sess_id = (*(uint32_t*)ptr) >> 8; - if ((sess_id < m->max_clients) && (m->instances[sess_id])) + peer_id = ntohl((*(uint32_t*)ptr)) & 0xFFFFFF; + if ((peer_id < m->max_clients) && (m->instances[peer_id])) { - mi = m->instances[sess_id]; + mi = m->instances[peer_id]; if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from)) { - msg(D_MULTI_MEDIUM, "floating detected from %s to %s", - print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc)); + msg(D_MULTI_MEDIUM, "float from %s to %s", + print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc)); - /* session-id is not trusted, so check hmac */ - session_forged = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options)); - if (session_forged) + /* peer-id is not trusted, so check hmac */ + hmac_mismatch = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options)); + if (hmac_mismatch) { mi = NULL; - msg (D_MULTI_MEDIUM, "hmac verification failed, session forge detected!"); + msg (D_MULTI_MEDIUM, "HMAC mismatch for peer-id %d", peer_id); } else { @@ -144,7 +144,7 @@ multi_get_create_instance_udp (struct multi_context *m) mi = (struct multi_instance *) he->value; } } - if (!mi && !session_forged) + if (!mi && !hmac_mismatch) { if (!m->top.c2.tls_auth_standalone || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf)) @@ -162,7 +162,7 @@ multi_get_create_instance_udp (struct multi_context *m) { if (!m->instances[i]) { - mi->context.c2.tls_multi->vpn_session_id = i; + mi->context.c2.tls_multi->peer_id = i; m->instances[i] = mi; break; } @@ -183,15 +183,6 @@ multi_get_create_instance_udp (struct multi_context *m) { const char *status = mi ? "[ok]" : "[failed]"; - /* - if (he && mi) - status = "[succeeded]"; - else if (!he && mi) - status = "[created]"; - else - status = "[failed]"; - */ - dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s", mroute_addr_print (&real, &gc), status); diff --git a/app/openvpn/src/openvpn/multi.c b/app/openvpn/src/openvpn/multi.c index a4289ac7..bd5948c8 100644 --- a/app/openvpn/src/openvpn/multi.c +++ b/app/openvpn/src/openvpn/multi.c @@ -303,7 +303,6 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa cid_compare_function); #endif - /* * This is our scheduler, for time-based wakeup * events. @@ -374,12 +373,7 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa */ m->max_clients = t->options.max_clients; - int i; - m->instances = malloc(sizeof(struct multi_instance*) * m->max_clients); - for (i = 0; i < m->max_clients; ++ i) - { - m->instances[i] = NULL; - } + m->instances = calloc(m->max_clients, sizeof(struct multi_instance*)); /* * Initialize multi-socket TCP I/O wait object @@ -561,7 +555,7 @@ multi_close_instance (struct multi_context *m, } #endif - m->instances[mi->context.c2.tls_multi->vpn_session_id] = NULL; + m->instances[mi->context.c2.tls_multi->peer_id] = NULL; schedule_remove_entry (m->schedule, (struct schedule_entry *) mi); @@ -664,6 +658,8 @@ multi_create_instance (struct multi_context *m, const struct mroute_addr *real) perf_push (PERF_MULTI_CREATE_INSTANCE); + msg (D_MULTI_MEDIUM, "MULTI: multi_create_instance called"); + ALLOC_OBJ_CLEAR (mi, struct multi_instance); mi->gc = gc_new (); @@ -1467,10 +1463,6 @@ multi_client_connect_post (struct multi_context *m, option_types_found, mi->context.c2.es); - if (!platform_unlink (dc_file)) - msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", - dc_file); - /* * If the --client-connect script generates a config file * with an --ifconfig-push directive, it will override any @@ -1713,6 +1705,11 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi multi_client_connect_post (m, mi, dc_file, option_permissions_mask, &option_types_found); ++cc_succeeded_count; } + + if (!platform_unlink (dc_file)) + msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", + dc_file); + script_depr_failed: argv_reset (&argv); } @@ -1766,6 +1763,11 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi } else cc_succeeded = false; + + if (!platform_unlink (dc_file)) + msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s", + dc_file); + script_failed: argv_reset (&argv); } diff --git a/app/openvpn/src/openvpn/options.c b/app/openvpn/src/openvpn/options.c index 9ff2db5a..1ca4ad57 100644 --- a/app/openvpn/src/openvpn/options.c +++ b/app/openvpn/src/openvpn/options.c @@ -2926,8 +2926,8 @@ options_string (const struct options *o, o->ifconfig_ipv6_local, o->ifconfig_ipv6_netbits, o->ifconfig_ipv6_remote, - (in_addr_t)0, - (in_addr_t)0, + NULL, + NULL, false, NULL); if (tt) @@ -3913,17 +3913,7 @@ apply_push_options (struct options *options, ++line_num; if (parse_line (line, p, SIZE (p), file, line_num, msglevel, &options->gc)) { - if (streq(p[0], "session_id")) - { - /* Server supports P_DATA_V2 */ - tls_multi->vpn_session_id = atoi(p[1]); - tls_multi->use_session_id = true; - msg(D_PUSH, "session id: %d", tls_multi->vpn_session_id); - } - else - { - add_option (options, p, file, line_num, 0, msglevel, permission_mask, option_types_found, es); - } + add_option (options, p, file, line_num, 0, msglevel, permission_mask, option_types_found, es); } } return true; @@ -6986,6 +6976,12 @@ add_option (struct options *options, options->persist_mode = 1; } #endif + else if (streq (p[0], "peer-id")) + { + VERIFY_PERMISSION (OPT_P_PEER_ID); + options->use_peer_id = true; + options->peer_id = atoi(p[1]); + } else { int i; diff --git a/app/openvpn/src/openvpn/options.h b/app/openvpn/src/openvpn/options.h index 77c942ca..d5f7e95d 100644 --- a/app/openvpn/src/openvpn/options.h +++ b/app/openvpn/src/openvpn/options.h @@ -591,6 +591,9 @@ struct options bool show_net_up; int route_method; #endif + + bool use_peer_id; + uint32_t peer_id; }; #define streq(x, y) (!strcmp((x), (y))) @@ -626,6 +629,7 @@ struct options #define OPT_P_SOCKBUF (1<<25) #define OPT_P_SOCKFLAGS (1<<26) #define OPT_P_CONNECTION (1<<27) +#define OPT_P_PEER_ID (1<<28) #define OPT_P_DEFAULT (~(OPT_P_INSTANCE|OPT_P_PULL_MODE)) diff --git a/app/openvpn/src/openvpn/plugin.c b/app/openvpn/src/openvpn/plugin.c index 0948f238..54c5b52d 100644 --- a/app/openvpn/src/openvpn/plugin.c +++ b/app/openvpn/src/openvpn/plugin.c @@ -291,7 +291,7 @@ plugin_init_item (struct plugin *p, const struct plugin_option *o) static void plugin_vlog (openvpn_plugin_log_flags_t flags, const char *name, const char *format, va_list arglist) { - unsigned int msg_flags; + unsigned int msg_flags = 0; if (!format) return; diff --git a/app/openvpn/src/openvpn/push.c b/app/openvpn/src/openvpn/push.c index 028d838e..c7844499 100644 --- a/app/openvpn/src/openvpn/push.c +++ b/app/openvpn/src/openvpn/push.c @@ -303,9 +303,17 @@ send_push_reply (struct context *c) if (multi_push) buf_printf (&buf, ",push-continuation 1"); - /* Send session_id if client supports it */ - if (c->c2.tls_multi->peer_info && strstr(c->c2.tls_multi->peer_info, "IV_PROTO=2")) { - buf_printf(&buf, ",session_id %d", c->c2.tls_multi->vpn_session_id); + /* Send peer-id if client supports it */ + if (c->c2.tls_multi->peer_info) + { + const char* proto_str = strstr(c->c2.tls_multi->peer_info, "IV_PROTO="); + if (proto_str) + { + int proto = 0; + int r = sscanf(proto_str, "IV_PROTO=%d", &proto); + if ((r == 1) && (proto >= 2)) + buf_printf(&buf, ",peer-id %d", c->c2.tls_multi->peer_id); + } } if (BLEN (&buf) > sizeof(cmd)-1) diff --git a/app/openvpn/src/openvpn/route.c b/app/openvpn/src/openvpn/route.c index 562af9fe..c330169a 100644 --- a/app/openvpn/src/openvpn/route.c +++ b/app/openvpn/src/openvpn/route.c @@ -863,10 +863,12 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u { msg (M_WARN, "%s VPN gateway parameter (--route-gateway or --ifconfig) is missing", err); } +#ifndef TARGET_ANDROID else if (!(rl->rgi.flags & RGI_ADDR_DEFINED)) { msg (M_WARN, "%s Cannot read current default gateway from system", err); } +#endif else if (!(rl->spec.flags & RTSA_REMOTE_HOST)) { msg (M_WARN, "%s Cannot obtain current remote host address", err); @@ -913,6 +915,16 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u if (rl->flags & RG_REROUTE_GW) { +#ifdef TARGET_ANDROID + add_route3 (0, + 0, + rl->spec.remote_endpoint, + tt, + flags, + &rl->rgi, + es); + +#else if (rl->flags & RG_DEF1) { /* add new default route (1st component) */ @@ -953,6 +965,7 @@ redirect_default_route_to_vpn (struct route_list *rl, const struct tuntap *tt, u &rl->rgi, es); } +#endif } /* set a flag so we can undo later */ @@ -1338,15 +1351,18 @@ add_route (struct route_ipv4 *r, #if defined(TARGET_LINUX) #ifdef ENABLE_IPROUTE - /* FIXME -- add on-link support for ENABLE_IPROUTE */ - argv_printf (&argv, "%s route add %s/%d via %s", + argv_printf (&argv, "%s route add %s/%d", iproute_path, network, - count_netmask_bits(netmask), - gateway); + count_netmask_bits(netmask)); + if (r->flags & RT_METRIC_DEFINED) argv_printf_cat (&argv, "metric %d", r->metric); + if (is_on_link (is_local_route, flags, rgi)) + argv_printf_cat (&argv, "dev %s", rgi->iface); + else + argv_printf_cat (&argv, "via %s", gateway); #else argv_printf (&argv, "%s add -net %s netmask %s", ROUTE_PATH, diff --git a/app/openvpn/src/openvpn/sig.c b/app/openvpn/src/openvpn/sig.c index 90e39a42..a3d29de0 100644 --- a/app/openvpn/src/openvpn/sig.c +++ b/app/openvpn/src/openvpn/sig.c @@ -126,7 +126,7 @@ print_signal (const struct signal_info *si, const char *title, int msglevel) { const char *type = (si->signal_text ? si->signal_text : ""); const char *t = (title ? title : "process"); - const char *hs; + const char *hs = NULL; switch (si->source) { case SIG_SOURCE_SOFT: diff --git a/app/openvpn/src/openvpn/socket.c b/app/openvpn/src/openvpn/socket.c index 9e6bd10c..c649d627 100644 --- a/app/openvpn/src/openvpn/socket.c +++ b/app/openvpn/src/openvpn/socket.c @@ -2354,12 +2354,12 @@ print_sockaddr_ex (const struct sockaddr *sa, struct gc_arena *gc) { struct buffer out = alloc_buf_gc (128, gc); - bool addr_is_defined; + bool addr_is_defined = false; char hostaddr[NI_MAXHOST] = ""; char servname[NI_MAXSERV] = ""; int status; - socklen_t salen; + socklen_t salen = 0; switch(sa->sa_family) { case AF_INET: diff --git a/app/openvpn/src/openvpn/ssl.c b/app/openvpn/src/openvpn/ssl.c index 929f95fa..94b7b6d9 100644 --- a/app/openvpn/src/openvpn/ssl.c +++ b/app/openvpn/src/openvpn/ssl.c @@ -1056,7 +1056,7 @@ tls_multi_init (struct tls_options *tls_options) ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK]; /* By default not use P_DATA_V2 */ - ret->use_session_id = false; + ret->use_peer_id = false; return ret; } @@ -2826,7 +2826,7 @@ tls_pre_decrypt (struct tls_multi *multi, opt->flags &= multi->opt.crypto_flags_and; opt->flags |= multi->opt.crypto_flags_or; - ASSERT (buf_advance (buf, op == P_DATA_V1 ? 1 : 4)); + ASSERT (buf_advance (buf, (op == P_DATA_V2) ? 4 : 1)); ++ks->n_packets; ks->n_bytes += buf->len; @@ -3324,7 +3324,6 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, return ret; error: - tls_clear_error(); gc_free (&gc); return ret; @@ -3393,7 +3392,7 @@ tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) { struct key_state *ks; uint8_t *op; - uint32_t sess; + uint32_t peer; ks = multi->save_ks; multi->save_ks = NULL; @@ -3401,10 +3400,10 @@ tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) { ASSERT (ks); - if (!multi->opt.server && multi->use_session_id) + if (!multi->opt.server && multi->use_peer_id) { - sess = ((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) | (multi->vpn_session_id << 8); - ASSERT (buf_write_prepend (buf, &sess, 4)); + peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->peer_id & 0xFFFFFF)); + ASSERT (buf_write_prepend (buf, &peer, 4)); } else { diff --git a/app/openvpn/src/openvpn/ssl.h b/app/openvpn/src/openvpn/ssl.h index 9bdd641f..a338745e 100644 --- a/app/openvpn/src/openvpn/ssl.h +++ b/app/openvpn/src/openvpn/ssl.h @@ -60,7 +60,7 @@ #define P_CONTROL_V1 4 /* control channel packet (usually TLS ciphertext) */ #define P_ACK_V1 5 /* acknowledgement for packets received */ #define P_DATA_V1 6 /* data channel packet */ -#define P_DATA_V2 9 /* data channel packet with session_id */ +#define P_DATA_V2 9 /* data channel packet with peer-id */ /* indicates key_method >= 2 */ #define P_CONTROL_HARD_RESET_CLIENT_V2 7 /* initial key from client, forget previous state */ diff --git a/app/openvpn/src/openvpn/ssl_common.h b/app/openvpn/src/openvpn/ssl_common.h index 2fc72aa6..cb0ba628 100644 --- a/app/openvpn/src/openvpn/ssl_common.h +++ b/app/openvpn/src/openvpn/ssl_common.h @@ -496,8 +496,8 @@ struct tls_multi #endif /* For P_DATA_V2 */ - uint32_t vpn_session_id; - int use_session_id; + uint32_t peer_id; + bool use_peer_id; /* * Our session objects. diff --git a/app/openvpn/src/openvpn/ssl_polarssl.c b/app/openvpn/src/openvpn/ssl_polarssl.c index ddccf1d9..387e6369 100644 --- a/app/openvpn/src/openvpn/ssl_polarssl.c +++ b/app/openvpn/src/openvpn/ssl_polarssl.c @@ -40,6 +40,7 @@ #include "errlevel.h" #include "ssl_backend.h" +#include "base64.h" #include "buffer.h" #include "misc.h" #include "manage.h" @@ -49,8 +50,10 @@ #include "ssl_verify_polarssl.h" #include +#include #include #include +#include void tls_init_lib() @@ -210,12 +213,13 @@ tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers) void tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const char *dh_file, - const char *dh_file_inline + const char *dh_inline ) { - if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_file_inline) + if (!strcmp (dh_file, INLINE_FILE_TAG) && dh_inline) { - if (0 != dhm_parse_dhm(ctx->dhm_ctx, dh_file_inline, strlen(dh_file_inline))) + if (0 != dhm_parse_dhm(ctx->dhm_ctx, (const unsigned char *) dh_inline, + strlen(dh_inline))) msg (M_FATAL, "Cannot read inline DH parameters"); } else @@ -257,15 +261,15 @@ tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert) void tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, - const char *cert_file_inline + const char *cert_inline ) { ASSERT(NULL != ctx); - if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_file_inline) + if (!strcmp (cert_file, INLINE_FILE_TAG) && cert_inline) { - if (0 != x509_crt_parse(ctx->crt_chain, cert_file_inline, - strlen(cert_file_inline))) + if (0 != x509_crt_parse(ctx->crt_chain, + (const unsigned char *) cert_inline, strlen(cert_inline))) msg (M_FATAL, "Cannot load inline certificate file"); } else @@ -282,31 +286,31 @@ tls_ctx_load_cert_file (struct tls_root_ctx *ctx, const char *cert_file, int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, - const char *priv_key_file_inline + const char *priv_key_inline ) { int status; ASSERT(NULL != ctx); - if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_file_inline) + if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_inline) { status = pk_parse_key(ctx->priv_key, - priv_key_file_inline, strlen(priv_key_file_inline), + (const unsigned char *) priv_key_inline, strlen(priv_key_inline), NULL, 0); - if (POLARSSL_ERR_PEM_PASSWORD_REQUIRED == status) + if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); status = pk_parse_key(ctx->priv_key, - priv_key_file_inline, strlen(priv_key_file_inline), + (const unsigned char *) priv_key_inline, strlen(priv_key_inline), (unsigned char *) passbuf, strlen(passbuf)); } } else { status = pk_parse_keyfile(ctx->priv_key, priv_key_file, NULL); - if (POLARSSL_ERR_PEM_PASSWORD_REQUIRED == status) + if (POLARSSL_ERR_PK_PASSWORD_REQUIRED == status) { char passbuf[512] = {0}; pem_password_callback(passbuf, 512, 0, NULL); @@ -316,7 +320,7 @@ tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_file, if (0 != status) { #ifdef ENABLE_MANAGEMENT - if (management && (POLARSSL_ERR_PEM_PASSWORD_MISMATCH == status)) + if (management && (POLARSSL_ERR_PK_PASSWORD_MISMATCH == status)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif msg (M_WARN, "Cannot load private key file %s", priv_key_file); diff --git a/app/openvpn/src/openvpn/ssl_verify_openssl.c b/app/openvpn/src/openvpn/ssl_verify_openssl.c index cbcff022..33cd757d 100644 --- a/app/openvpn/src/openvpn/ssl_verify_openssl.c +++ b/app/openvpn/src/openvpn/ssl_verify_openssl.c @@ -101,9 +101,7 @@ static bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size) { bool retval = false; - X509_EXTENSION *pExt; char *buf = 0; - int length = 0; GENERAL_NAMES *extensions; int nid = OBJ_txt2nid(fieldname); @@ -140,8 +138,8 @@ bool extract_x509_extension(X509 *cert, char *fieldname, char *out, int size) } break; default: - msg (D_TLS_ERRORS, "ASN1 ERROR: can not handle field type %i", - name->type); + msg (D_TLS_DEBUG, "%s: ignoring general name field type %i", + __func__, name->type); break; } } diff --git a/app/openvpn/src/openvpn/tun.h b/app/openvpn/src/openvpn/tun.h index 631b53c6..79e2d188 100644 --- a/app/openvpn/src/openvpn/tun.h +++ b/app/openvpn/src/openvpn/tun.h @@ -391,6 +391,19 @@ tuntap_stop (int status) return false; } +static inline bool +tuntap_abort(int status) +{ + /* + * Typically generated when driver is halted. + */ + if (status < 0) + { + return openvpn_errno() == ERROR_OPERATION_ABORTED; + } + return false; +} + static inline int tun_write_win32 (struct tuntap *tt, struct buffer *buf) { @@ -432,6 +445,12 @@ tuntap_stop (int status) return false; } +static inline bool +tuntap_abort(int status) +{ + return false; +} + static inline void tun_standby_init (struct tuntap *tt) { -- cgit v1.2.3