Hello community, here is the log from the commit of package openvpn for openSUSE:Factory checked in at 2020-09-23 18:37:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/openvpn (Old) and /work/SRC/openSUSE:Factory/.openvpn.new.4249 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "openvpn" Wed Sep 23 18:37:47 2020 rev:89 rq:834319 version:2.4.9 Changes: -------- --- /work/SRC/openSUSE:Factory/openvpn/openvpn.changes 2020-09-03 01:13:17.376451479 +0200 +++ /work/SRC/openSUSE:Factory/.openvpn.new.4249/openvpn.changes 2020-09-23 18:38:27.605215278 +0200 @@ -1,0 +2,19 @@ +Fri Sep 11 11:52:54 UTC 2020 - Dirk Mueller <[email protected]> + +- update to 2.4.9 (CVE-2020-11810, bsc#1169925O): + * Allow unicode search string in --cryptoapicert option (Windows) + * Skip expired certificates in Windows certificate store (Windows) (trac #966) + * OpenSSL: Fix --crl-verify not loading multiple CRLs in one file (trac #623) + * fix condition where a client's session could "float" to a new IP address that is not authorized ("fix illegal client float"). + This can be used to disrupt service to a freshly connected client (no session + keys negotiated yet). It can not be used to inject or steal VPN traffic. + CVE-2020-11810). + * fix combination of async push (deferred auth) and NCP (trac #1259) + * Fix OpenSSL 1.1.1 not using auto elliptic curve selection (trac #1228) + * Fix OpenSSL error stack handling of tls_ctx_add_extra_certs + * mbedTLS: Make sure TLS session survives move (trac #880) + * Fix OpenSSL private key passphrase notices + * Fix building with --enable-async-push in FreeBSD (trac #1256) + * Fix broken fragmentation logic when using NCP (trac #1140) + +------------------------------------------------------------------- Old: ---- openvpn-2.4.8.tar.xz openvpn-2.4.8.tar.xz.asc New: ---- openvpn-2.4.9.tar.xz openvpn-2.4.9.tar.xz.asc ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ openvpn.spec ++++++ --- /var/tmp/diff_new_pack.PFTb7F/_old 2020-09-23 18:38:32.077219174 +0200 +++ /var/tmp/diff_new_pack.PFTb7F/_new 2020-09-23 18:38:32.077219174 +0200 @@ -29,7 +29,7 @@ %define _rundir %{_localstatedir}/run %endif Name: openvpn -Version: 2.4.8 +Version: 2.4.9 Release: 0 Summary: Full-featured SSL VPN solution using a TUN/TAP Interface License: SUSE-GPL-2.0-with-openssl-exception AND LGPL-2.1-only ++++++ openvpn-2.4.8.tar.xz -> openvpn-2.4.9.tar.xz ++++++ ++++ 4805 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/ChangeLog new/openvpn-2.4.9/ChangeLog --- old/openvpn-2.4.8/ChangeLog 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/ChangeLog 2020-04-16 15:26:45.000000000 +0200 @@ -1,6 +1,43 @@ OpenVPN Change Log Copyright (C) 2002-2018 OpenVPN Inc <[email protected]> +2020.04.16 -- Version 2.4.9 +Antonio Quartulli (1): + socks: use the right function when printing struct openvpn_sockaddr + +Arne Schwabe (3): + Fetch OpenSSL versions via source/old links + Fix OpenSSL error stack handling of tls_ctx_add_extra_certs + Fix OpenSSL 1.1.1 not using auto elliptic curve selection + +Lev Stipakov (4): + Fix broken fragmentation logic when using NCP + Fix building with --enable-async-push in FreeBSD + Fix broken async push with NCP is used + Fix illegal client float (CVE-2020-11810) + +Maxim Plotnikov (1): + OpenSSL: Fix --crl-verify not loading multiple CRLs in one file + +Santtu Lakkala (1): + Fix OpenSSL private key passphrase notices + +Selva Nair (7): + Swap the order of checks for validating interactive service user + Move querying username/password from management interface to a function + When auth-user-pass file has no password query the management interface (if available). + Fix possibly uninitialized return value in GetOpenvpnSettings() + Fix possible access of uninitialized pipe handles + Skip expired certificates in Windows certificate store + Allow unicode search string in --cryptoapicert option + +Tom van Leeuwen (1): + mbedTLS: Make sure TLS session survives move + +WGH (1): + docs: Add reference to X509_LOOKUP_hash_dir(3) + + 2019.10.30 -- Version 2.4.8 Antonio Quartulli (1): mbedtls: fix segfault by calling mbedtls_cipher_free() in cipher_ctx_free() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/Changes.rst new/openvpn-2.4.9/Changes.rst --- old/openvpn-2.4.8/Changes.rst 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/Changes.rst 2020-04-16 15:26:45.000000000 +0200 @@ -321,6 +321,56 @@ i386/i686 builds on RHEL5. +Version 2.4.9 +============= +This is primarily a maintenance release with minor bugfixes and improvements. + +New features +------------ +- Allow unicode search string in --cryptoapicert option (Windows) + +User visible changes +-------------------- +- Skip expired certificates in Windows certificate store (Windows) (trac #966) + +- OpenSSL: Fix --crl-verify not loading multiple CRLs in one file (trac #623) + +- When using "--auth-user-pass file" with just a username and no password + in the file, OpenVPN now queries the management interface (if active) + for the credentials. Previously it would query the console for the + password, and fail if no console available (normal case on Windows) + (trac #757) + +- Swap the order of checks for validating interactive service user + (Windows: check config location before querying domain controller for + group membership, which can be slow) + + +Bug fixes +--------- +- fix condition where a client's session could "float" to a new IP address + that is not authorized ("fix illegal client float"). + + This can be used to disrupt service to a freshly connected client (no + session keys negotiated yet). It can not be used to inject or steal + VPN traffic. CVE-2020-11810, trac #1272). + +- fix combination of async push (deferred auth) and NCP (trac #1259) + +- Fix OpenSSL 1.1.1 not using auto elliptic curve selection (trac #1228) + +- Fix OpenSSL error stack handling of tls_ctx_add_extra_certs + +- mbedTLS: Make sure TLS session survives move (trac #880) + +- Fix OpenSSL private key passphrase notices + +- Fix building with --enable-async-push in FreeBSD (trac #1256) + +- Fix broken fragmentation logic when using NCP (trac #1140) + + + Version 2.4.8 ============= This is primarily a maintenance release with minor bugfixes and improvements. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/configure.ac new/openvpn-2.4.9/configure.ac --- old/openvpn-2.4.8/configure.ac 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/configure.ac 2020-04-16 15:26:45.000000000 +0200 @@ -1328,11 +1328,25 @@ fi if test "${enable_async_push}" = "yes"; then - AC_CHECK_HEADERS( - [sys/inotify.h], - AC_DEFINE([ENABLE_ASYNC_PUSH], [1], [Enable async push]), - AC_MSG_ERROR([inotify.h not found.]) - ) + case "$host" in + *-*-freebsd*) + PKG_CHECK_MODULES( + [OPTIONAL_INOTIFY], + [libinotify], + [ + AC_DEFINE([HAVE_SYS_INOTIFY_H]) + AC_DEFINE([ENABLE_ASYNC_PUSH], [1], [Enable async push]) + ] + ) + ;; + *) + AC_CHECK_HEADERS( + [sys/inotify.h], + AC_DEFINE([ENABLE_ASYNC_PUSH], [1], [Enable async push]), + AC_MSG_ERROR([inotify.h not found.]) + ) + ;; + esac fi CONFIGURE_DEFINES="`set | grep '^enable_.*=' ; set | grep '^with_.*='`" @@ -1359,6 +1373,8 @@ AC_SUBST([OPTIONAL_SYSTEMD_LIBS]) AC_SUBST([OPTIONAL_PKCS11_HELPER_CFLAGS]) AC_SUBST([OPTIONAL_PKCS11_HELPER_LIBS]) +AC_SUBST([OPTIONAL_INOTIFY_CFLAGS]) +AC_SUBST([OPTIONAL_INOTIFY_LIBS]) AC_SUBST([PLUGIN_AUTH_PAM_CFLAGS]) AC_SUBST([PLUGIN_AUTH_PAM_LIBS]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/doc/openvpn.8 new/openvpn-2.4.9/doc/openvpn.8 --- old/openvpn-2.4.8/doc/openvpn.8 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/doc/openvpn.8 2020-04-16 15:26:45.000000000 +0200 @@ -4634,8 +4634,10 @@ .B \-hash option of .B openssl x509 -and +, .B openssl crl +and +.BR X509_LOOKUP_hash_dir (3) for more information. Similarly to the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/include/openvpn-plugin.h new/openvpn-2.4.9/include/openvpn-plugin.h --- old/openvpn-2.4.8/include/openvpn-plugin.h 2019-10-30 13:38:15.000000000 +0100 +++ new/openvpn-2.4.9/include/openvpn-plugin.h 2020-04-16 15:27:08.000000000 +0200 @@ -55,7 +55,7 @@ */ #define OPENVPN_VERSION_MAJOR 2 #define OPENVPN_VERSION_MINOR 4 -#define OPENVPN_VERSION_PATCH ".8" +#define OPENVPN_VERSION_PATCH ".9" /* * Plug-in types. These types correspond to the set of script callbacks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/Makefile.am new/openvpn-2.4.9/src/openvpn/Makefile.am --- old/openvpn-2.4.8/src/openvpn/Makefile.am 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/Makefile.am 2020-04-16 15:26:45.000000000 +0200 @@ -28,6 +28,7 @@ $(OPTIONAL_LZO_CFLAGS) \ $(OPTIONAL_LZ4_CFLAGS) \ $(OPTIONAL_PKCS11_HELPER_CFLAGS) \ + $(OPTIONAL_INOTIFY_CFLAGS) \ -DPLUGIN_LIBDIR=\"${plugindir}\" if WIN32 @@ -129,7 +130,8 @@ $(OPTIONAL_CRYPTO_LIBS) \ $(OPTIONAL_SELINUX_LIBS) \ $(OPTIONAL_SYSTEMD_LIBS) \ - $(OPTIONAL_DL_LIBS) + $(OPTIONAL_DL_LIBS) \ + $(OPTIONAL_INOTIFY_LIBS) if WIN32 openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4 -lncrypt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/cryptoapi.c new/openvpn-2.4.9/src/openvpn/cryptoapi.c --- old/openvpn-2.4.8/src/openvpn/cryptoapi.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/cryptoapi.c 2020-04-16 15:26:45.000000000 +0200 @@ -50,6 +50,7 @@ #include "buffer.h" #include "openssl_compat.h" +#include "win32.h" /* MinGW w32api 3.17 is still incomplete when it comes to CryptoAPI while * MinGW32-w64 defines all macros used. This is a hack around that problem. @@ -529,27 +530,32 @@ * SUBJ:<certificate substring to match> * THUMB:<certificate thumbprint hex value>, e.g. * THUMB:f6 49 24 41 01 b4 fb 44 0c ce f4 36 ae d0 c4 c9 df 7a b6 28 + * The first matching certificate that has not expired is returned. */ const CERT_CONTEXT *rv = NULL; + DWORD find_type; + const void *find_param; + unsigned char hash[255]; + CRYPT_HASH_BLOB blob = {.cbData = 0, .pbData = hash}; + struct gc_arena gc = gc_new(); if (!strncmp(cert_prop, "SUBJ:", 5)) { /* skip the tag */ - cert_prop += 5; - rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - 0, CERT_FIND_SUBJECT_STR_A, cert_prop, NULL); - + find_param = wide_string(cert_prop + 5, &gc); + find_type = CERT_FIND_SUBJECT_STR_W; } else if (!strncmp(cert_prop, "THUMB:", 6)) { - unsigned char hash[255]; - char *p; + const char *p; int i, x = 0; - CRYPT_HASH_BLOB blob; + find_type = CERT_FIND_HASH; + find_param = &blob; /* skip the tag */ cert_prop += 6; - for (p = (char *) cert_prop, i = 0; *p && i < sizeof(hash); i++) { + for (p = cert_prop, i = 0; *p && i < sizeof(hash); i++) + { if (*p >= '0' && *p <= '9') { x = (*p - '0') << 4; @@ -564,7 +570,8 @@ } if (!*++p) /* unexpected end of string */ { - break; + msg(M_WARN, "WARNING: cryptoapicert: error parsing <THUMB:%s>.", cert_prop); + goto out; } if (*p >= '0' && *p <= '9') { @@ -585,12 +592,33 @@ } } blob.cbData = i; - blob.pbData = (unsigned char *) &hash; - rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - 0, CERT_FIND_HASH, &blob, NULL); + } + else + { + msg(M_WARN, "WARNING: cryptoapicert: unsupported certificate specification <%s>", cert_prop); + goto out; + } + while(true) + { + int validity = 1; + /* this frees previous rv, if not NULL */ + rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + 0, find_type, find_param, rv); + if (rv) + { + validity = CertVerifyTimeValidity(NULL, rv->pCertInfo); + } + if (!rv || validity == 0) + { + break; + } + msg(M_WARN, "WARNING: cryptoapicert: ignoring certificate in store %s.", + validity < 0 ? "not yet valid" : "that has expired"); } +out: + gc_free(&gc); return rv; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/forward.c new/openvpn-2.4.9/src/openvpn/forward.c --- old/openvpn-2.4.8/src/openvpn/forward.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/forward.c 2020-04-16 15:26:45.000000000 +0200 @@ -873,6 +873,9 @@ if (is_hard_reset(opcode, c->options.key_method)) { c->c2.frame = c->c2.frame_initial; +#ifdef ENABLE_FRAGMENT + c->c2.frame_fragment = c->c2.frame_fragment_initial; +#endif } interval_action(&c->c2.tmp_int); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/init.c new/openvpn-2.4.9/src/openvpn/init.c --- old/openvpn-2.4.8/src/openvpn/init.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/init.c 2020-04-16 15:26:45.000000000 +0200 @@ -2294,9 +2294,16 @@ { tls_poor_mans_ncp(&c->options, c->c2.tls_multi->remote_ciphername); } - /* Do not regenerate keys if server sends an extra push reply */ - if (!session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized - && !tls_session_update_crypto_params(session, &c->options, &c->c2.frame)) + struct frame *frame_fragment = NULL; +#ifdef ENABLE_FRAGMENT + if (c->options.ce.fragment) + { + frame_fragment = &c->c2.frame_fragment; + } +#endif + + if (!tls_session_update_crypto_params(session, &c->options, &c->c2.frame, + frame_fragment)) { msg(D_TLS_ERRORS, "OPTIONS ERROR: failed to import crypto options"); return false; @@ -3035,6 +3042,7 @@ */ c->c2.frame_fragment = c->c2.frame; frame_subtract_extra(&c->c2.frame_fragment, &c->c2.frame_fragment_omit); + c->c2.frame_fragment_initial = c->c2.frame_fragment; #endif #if defined(ENABLE_FRAGMENT) && defined(ENABLE_OCC) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/misc.c new/openvpn-2.4.9/src/openvpn/misc.c --- old/openvpn-2.4.8/src/openvpn/misc.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/misc.c 2020-04-16 15:26:45.000000000 +0200 @@ -880,6 +880,43 @@ } } +#ifdef ENABLE_MANAGEMENT + +/* Get username/password from the management interface */ +static bool +auth_user_pass_mgmt(struct user_pass *up, const char *prefix, const unsigned int flags, + const char *auth_challenge) +{ + const char *sc = NULL; + + if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) + { + management_auth_failure(management, prefix, "previous auth credentials failed"); + } + +#ifdef ENABLE_CLIENT_CR + if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE)) + { + sc = auth_challenge; + } +#endif + + if (!management_query_user_pass(management, up, prefix, flags, sc)) + { + if ((flags & GET_USER_PASS_NOFATAL) != 0) + { + return false; + } + else + { + msg(M_FATAL, "ERROR: could not read %s username/password/ok/string from management interface", prefix); + } + } + return true; +} + +#endif /* ifdef ENABLE_MANAGEMENT */ + /* * Get and store a username/password */ @@ -913,30 +950,10 @@ && (!from_authfile && (flags & GET_USER_PASS_MANAGEMENT)) && management_query_user_pass_enabled(management)) { - const char *sc = NULL; response_from_stdin = false; - - if (flags & GET_USER_PASS_PREVIOUS_CREDS_FAILED) - { - management_auth_failure(management, prefix, "previous auth credentials failed"); - } - -#ifdef ENABLE_CLIENT_CR - if (auth_challenge && (flags & GET_USER_PASS_STATIC_CHALLENGE)) + if (!auth_user_pass_mgmt(up, prefix, flags, auth_challenge)) { - sc = auth_challenge; - } -#endif - if (!management_query_user_pass(management, up, prefix, flags, sc)) - { - if ((flags & GET_USER_PASS_NOFATAL) != 0) - { - return false; - } - else - { - msg(M_FATAL, "ERROR: could not read %s username/password/ok/string from management interface", prefix); - } + return false; } } else @@ -1013,6 +1030,22 @@ { strncpy(up->password, password_buf, USER_PASS_LEN); } + /* The auth-file does not have the password: get both username + * and password from the management interface if possible. + * Otherwise set to read password from console. + */ +#if defined(ENABLE_MANAGEMENT) + else if (management + && (flags & GET_USER_PASS_MANAGEMENT) + && management_query_user_pass_enabled(management)) + { + msg(D_LOW, "No password found in %s authfile '%s'. Querying the management interface", prefix, auth_file); + if (!auth_user_pass_mgmt(up, prefix, flags, auth_challenge)) + { + return false; + } + } +#endif else { password_from_stdin = 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/multi.c new/openvpn-2.4.9/src/openvpn/multi.c --- old/openvpn-2.4.8/src/openvpn/multi.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/multi.c 2020-04-16 15:26:45.000000000 +0200 @@ -2132,8 +2132,30 @@ { if (mi) { - /* continue authentication and send push_reply */ + /* continue authentication, perform NCP negotiation and send push_reply */ multi_process_post(m, mi, mpp_flags); + + /* With NCP and deferred authentication, we perform cipher negotiation and + * data channel keys generation on incoming push request, assuming that auth + * succeeded. When auth succeeds in between push requests and async push is used, + * we send push reply immediately. Above multi_process_post() call performs + * NCP negotiation and here we do keys generation. */ + + struct context *c = &mi->context; + struct frame *frame_fragment = NULL; +#ifdef ENABLE_FRAGMENT + if (c->options.ce.fragment) + { + frame_fragment = &c->c2.frame_fragment; + } +#endif + struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE]; + if (!tls_session_update_crypto_params(session, &c->options, + &c->c2.frame, frame_fragment)) + { + msg(D_TLS_ERRORS, "TLS Error: initializing data channel failed"); + register_signal(c, SIGUSR1, "init-data-channel-failed"); + } } else { @@ -2540,7 +2562,8 @@ orig_buf = c->c2.buf.data; if (process_incoming_link_part1(c, lsi, floated)) { - if (floated) + /* nonzero length means that we have a valid, decrypted packed */ + if (floated && c->c2.buf.len > 0) { multi_process_float(m, m->pending); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/openvpn.h new/openvpn-2.4.9/src/openvpn/openvpn.h --- old/openvpn-2.4.8/src/openvpn/openvpn.h 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/openvpn.h 2020-04-16 15:26:45.000000000 +0200 @@ -269,6 +269,7 @@ /* Object to handle advanced MTU negotiation and datagram fragmentation */ struct fragment_master *fragment; struct frame frame_fragment; + struct frame frame_fragment_initial; struct frame frame_fragment_omit; #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/push.c new/openvpn-2.4.9/src/openvpn/push.c --- old/openvpn-2.4.8/src/openvpn/push.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/push.c 2020-04-16 15:26:45.000000000 +0200 @@ -287,11 +287,16 @@ { if (c->options.mode == MODE_SERVER) { + struct frame *frame_fragment = NULL; +#ifdef ENABLE_FRAGMENT + if (c->options.ce.fragment) + { + frame_fragment = &c->c2.frame_fragment; + } +#endif struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE]; - /* Do not regenerate keys if client send a second push request */ - if (!session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized - && !tls_session_update_crypto_params(session, &c->options, - &c->c2.frame)) + if (!tls_session_update_crypto_params(session, &c->options, + &c->c2.frame, frame_fragment)) { msg(D_TLS_ERRORS, "TLS Error: initializing data channel failed"); goto error; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/socks.c new/openvpn-2.4.9/src/openvpn/socks.c --- old/openvpn-2.4.8/src/openvpn/socks.c 2019-10-30 13:37:54.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/socks.c 2020-04-16 15:26:43.000000000 +0200 @@ -416,7 +416,7 @@ memcpy(&addr->addr.in4.sin_port, buf + 8, sizeof(addr->addr.in4.sin_port)); struct gc_arena gc = gc_new(); msg(M_INFO, "SOCKS proxy wants us to send UDP to %s", - print_sockaddr(addr, &gc)); + print_openvpn_sockaddr(addr, &gc)); gc_free(&gc); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/ssl.c new/openvpn-2.4.9/src/openvpn/ssl.c --- old/openvpn-2.4.8/src/openvpn/ssl.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/ssl.c 2020-04-16 15:26:45.000000000 +0200 @@ -1962,8 +1962,15 @@ bool tls_session_update_crypto_params(struct tls_session *session, - struct options *options, struct frame *frame) + struct options *options, struct frame *frame, + struct frame *frame_fragment) { + if (session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized) + { + /* keys already generated, nothing to do */ + return true; + } + if (!session->opt->server && 0 != strcmp(options->ciphername, session->opt->config_ciphername) && !tls_item_in_cipher_list(options->ciphername, options->ncp_ciphers)) @@ -2006,6 +2013,22 @@ frame_init_mssfix(frame, options); frame_print(frame, D_MTU_INFO, "Data Channel MTU parms"); + /* + * mssfix uses data channel framing, which at this point contains + * actual overhead. Fragmentation logic uses frame_fragment, which + * still contains worst case overhead. Replace it with actual overhead + * to prevent unneeded fragmentation. + */ + + if (frame_fragment) + { + frame_remove_from_extra_frame(frame_fragment, crypto_max_overhead()); + crypto_adjust_frame_parameters(frame_fragment, &session->opt->key_type, + options->use_iv, options->replay, packet_id_long_form); + frame_set_mtu_dynamic(frame_fragment, options->ce.fragment, SET_MTU_UPPER_BOUND); + frame_print(frame_fragment, D_MTU_INFO, "Fragmentation MTU parms"); + } + return tls_session_generate_data_channel_keys(session); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/ssl.h new/openvpn-2.4.9/src/openvpn/ssl.h --- old/openvpn-2.4.8/src/openvpn/ssl.h 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/ssl.h 2020-04-16 15:26:45.000000000 +0200 @@ -473,17 +473,21 @@ /** * Update TLS session crypto parameters (cipher and auth) and derive data - * channel keys based on the supplied options. + * channel keys based on the supplied options. Does nothing if keys are already + * generated. * - * @param session The TLS session to update. - * @param options The options to use when updating session. - * @param frame The frame options for this session (frame overhead is - * adjusted based on the selected cipher/auth). + * @param session The TLS session to update. + * @param options The options to use when updating session. + * @param frame The frame options for this session (frame overhead is + * adjusted based on the selected cipher/auth). + * @param frame_fragment The fragment frame options. * - * @return true if updating succeeded, false otherwise. + * @return true if updating succeeded or keys are already generated, false otherwise. */ bool tls_session_update_crypto_params(struct tls_session *session, - struct options *options, struct frame *frame); + struct options *options, + struct frame *frame, + struct frame *frame_fragment); /** * "Poor man's NCP": Use peer cipher if it is an allowed (NCP) cipher. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/ssl_mbedtls.c new/openvpn-2.4.9/src/openvpn/ssl_mbedtls.c --- old/openvpn-2.4.8/src/openvpn/ssl_mbedtls.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/ssl_mbedtls.c 2020-04-16 15:26:45.000000000 +0200 @@ -974,21 +974,22 @@ CLEAR(*ks_ssl); /* Initialise SSL config */ - mbedtls_ssl_config_init(&ks_ssl->ssl_config); - mbedtls_ssl_config_defaults(&ks_ssl->ssl_config, ssl_ctx->endpoint, + ALLOC_OBJ_CLEAR(ks_ssl->ssl_config, mbedtls_ssl_config); + mbedtls_ssl_config_init(ks_ssl->ssl_config); + mbedtls_ssl_config_defaults(ks_ssl->ssl_config, ssl_ctx->endpoint, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); #ifdef MBEDTLS_DEBUG_C mbedtls_debug_set_threshold(3); #endif - mbedtls_ssl_conf_dbg(&ks_ssl->ssl_config, my_debug, NULL); - mbedtls_ssl_conf_rng(&ks_ssl->ssl_config, mbedtls_ctr_drbg_random, + mbedtls_ssl_conf_dbg(ks_ssl->ssl_config, my_debug, NULL); + mbedtls_ssl_conf_rng(ks_ssl->ssl_config, mbedtls_ctr_drbg_random, rand_ctx_get()); - mbedtls_ssl_conf_cert_profile(&ks_ssl->ssl_config, &ssl_ctx->cert_profile); + mbedtls_ssl_conf_cert_profile(ks_ssl->ssl_config, &ssl_ctx->cert_profile); if (ssl_ctx->allowed_ciphers) { - mbedtls_ssl_conf_ciphersuites(&ks_ssl->ssl_config, ssl_ctx->allowed_ciphers); + mbedtls_ssl_conf_ciphersuites(ks_ssl->ssl_config, ssl_ctx->allowed_ciphers); } /* Disable record splitting (for now). OpenVPN assumes records are sent @@ -996,35 +997,35 @@ * testing. Since OpenVPN is not susceptible to BEAST, we can just * disable record splitting as a quick fix. */ #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - mbedtls_ssl_conf_cbc_record_splitting(&ks_ssl->ssl_config, + mbedtls_ssl_conf_cbc_record_splitting(ks_ssl->ssl_config, MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED); #endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ /* Initialise authentication information */ if (is_server) { - mbed_ok(mbedtls_ssl_conf_dh_param_ctx(&ks_ssl->ssl_config, + mbed_ok(mbedtls_ssl_conf_dh_param_ctx(ks_ssl->ssl_config, ssl_ctx->dhm_ctx)); } - mbed_ok(mbedtls_ssl_conf_own_cert(&ks_ssl->ssl_config, ssl_ctx->crt_chain, + mbed_ok(mbedtls_ssl_conf_own_cert(ks_ssl->ssl_config, ssl_ctx->crt_chain, ssl_ctx->priv_key)); /* Initialise SSL verification */ #if P2MP_SERVER if (session->opt->ssl_flags & SSLF_CLIENT_CERT_OPTIONAL) { - mbedtls_ssl_conf_authmode(&ks_ssl->ssl_config, MBEDTLS_SSL_VERIFY_OPTIONAL); + mbedtls_ssl_conf_authmode(ks_ssl->ssl_config, MBEDTLS_SSL_VERIFY_OPTIONAL); } else if (!(session->opt->ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)) #endif { - mbedtls_ssl_conf_authmode(&ks_ssl->ssl_config, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_authmode(ks_ssl->ssl_config, MBEDTLS_SSL_VERIFY_REQUIRED); } - mbedtls_ssl_conf_verify(&ks_ssl->ssl_config, verify_callback, session); + mbedtls_ssl_conf_verify(ks_ssl->ssl_config, verify_callback, session); /* TODO: mbed TLS does not currently support sending the CA chain to the client */ - mbedtls_ssl_conf_ca_chain(&ks_ssl->ssl_config, ssl_ctx->ca_chain, ssl_ctx->crl); + mbedtls_ssl_conf_ca_chain(ks_ssl->ssl_config, ssl_ctx->ca_chain, ssl_ctx->crl); /* Initialize minimum TLS version */ { @@ -1041,7 +1042,7 @@ tls_version_to_major_minor(tls_version_min, &major, &minor); } - mbedtls_ssl_conf_min_version(&ks_ssl->ssl_config, major, minor); + mbedtls_ssl_conf_min_version(ks_ssl->ssl_config, major, minor); } /* Initialize maximum TLS version */ @@ -1054,18 +1055,18 @@ { int major, minor; tls_version_to_major_minor(tls_version_max, &major, &minor); - mbedtls_ssl_conf_max_version(&ks_ssl->ssl_config, major, minor); + mbedtls_ssl_conf_max_version(ks_ssl->ssl_config, major, minor); } } /* Initialise SSL context */ ALLOC_OBJ_CLEAR(ks_ssl->ctx, mbedtls_ssl_context); mbedtls_ssl_init(ks_ssl->ctx); - mbedtls_ssl_setup(ks_ssl->ctx, &ks_ssl->ssl_config); + mbedtls_ssl_setup(ks_ssl->ctx, ks_ssl->ssl_config); /* Initialise BIOs */ - CLEAR(ks_ssl->bio_ctx); - mbedtls_ssl_set_bio(ks_ssl->ctx, &ks_ssl->bio_ctx, ssl_bio_write, + ALLOC_OBJ_CLEAR(ks_ssl->bio_ctx, bio_ctx); + mbedtls_ssl_set_bio(ks_ssl->ctx, ks_ssl->bio_ctx, ssl_bio_write, ssl_bio_read, NULL); } @@ -1079,9 +1080,17 @@ mbedtls_ssl_free(ks_ssl->ctx); free(ks_ssl->ctx); } - mbedtls_ssl_config_free(&ks_ssl->ssl_config); - buf_free_entries(&ks_ssl->bio_ctx.in); - buf_free_entries(&ks_ssl->bio_ctx.out); + if (ks_ssl->ssl_config) + { + mbedtls_ssl_config_free(ks_ssl->ssl_config); + free(ks_ssl->ssl_config); + } + if (ks_ssl->bio_ctx) + { + buf_free_entries(&ks_ssl->bio_ctx->in); + buf_free_entries(&ks_ssl->bio_ctx->out); + free(ks_ssl->bio_ctx); + } CLEAR(*ks_ssl); } } @@ -1176,7 +1185,7 @@ len = maxlen; } - retval = endless_buf_read(&ks->bio_ctx.out, BPTR(buf), len); + retval = endless_buf_read(&ks->bio_ctx->out, BPTR(buf), len); /* Error during read, check for retry error */ if (retval < 0) @@ -1221,7 +1230,7 @@ return 0; } - retval = endless_buf_write(&ks->bio_ctx.in, BPTR(buf), buf->len); + retval = endless_buf_write(&ks->bio_ctx->in, BPTR(buf), buf->len); if (retval < 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/ssl_mbedtls.h new/openvpn-2.4.9/src/openvpn/ssl_mbedtls.h --- old/openvpn-2.4.8/src/openvpn/ssl_mbedtls.h 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/ssl_mbedtls.h 2020-04-16 15:26:45.000000000 +0200 @@ -86,9 +86,9 @@ }; struct key_state_ssl { - mbedtls_ssl_config ssl_config; /**< mbedTLS global ssl config */ + mbedtls_ssl_config *ssl_config; /**< mbedTLS global ssl config */ mbedtls_ssl_context *ctx; /**< mbedTLS connection context */ - bio_ctx bio_ctx; + bio_ctx *bio_ctx; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpn/ssl_openssl.c new/openvpn-2.4.9/src/openvpn/ssl_openssl.c --- old/openvpn-2.4.8/src/openvpn/ssl_openssl.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpn/ssl_openssl.c 2020-04-16 15:26:45.000000000 +0200 @@ -634,8 +634,11 @@ /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter * loading */ SSL_CTX_set_ecdh_auto(ctx->ctx, 1); - return; + + /* OpenSSL 1.1.0 and newer have always ecdh auto loading enabled, + * so do nothing */ #endif + return; #else /* For older OpenSSL we have to extract the curve from key on our own */ EC_KEY *eckey = NULL; @@ -837,24 +840,36 @@ #endif /* ENABLE_CRYPTOAPI */ static void -tls_ctx_add_extra_certs(struct tls_root_ctx *ctx, BIO *bio) +tls_ctx_add_extra_certs(struct tls_root_ctx *ctx, BIO *bio, bool optional) { X509 *cert; - for (;; ) + while (true) { cert = NULL; - if (!PEM_read_bio_X509(bio, &cert, NULL, NULL)) /* takes ownership of cert */ - { - break; - } - if (!cert) + if (!PEM_read_bio_X509(bio, &cert, NULL, NULL)) { + /* a PEM_R_NO_START_LINE "Error" indicates that no certificate + * is found in the buffer. If loading more certificates is + * optional, break without raising an error + */ + if (optional + && ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) + { + /* remove that error from error stack */ + (void)ERR_get_error(); + break; + } + + /* Otherwise, bail out with error */ crypto_msg(M_FATAL, "Error reading extra certificate"); } + /* takes ownership of cert like a set1 method */ if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1) { crypto_msg(M_FATAL, "Error adding extra certificate"); } + /* We loaded at least one certificate, so loading more is optional */ + optional = true; } } @@ -904,7 +919,7 @@ ret = SSL_CTX_use_certificate(ctx->ctx, x); if (ret) { - tls_ctx_add_extra_certs(ctx, in); + tls_ctx_add_extra_certs(ctx, in, true); } end: @@ -919,6 +934,10 @@ crypto_msg(M_FATAL, "Cannot load certificate file %s", cert_file); } } + else + { + crypto_print_openssl_errors(M_DEBUG); + } if (in != NULL) { @@ -972,12 +991,7 @@ pkey = PEM_read_bio_PrivateKey(in, NULL, SSL_CTX_get_default_passwd_cb(ctx->ctx), SSL_CTX_get_default_passwd_cb_userdata(ctx->ctx)); - if (!pkey) - { - goto end; - } - - if (!SSL_CTX_use_PrivateKey(ssl_ctx, pkey)) + if (!pkey || !SSL_CTX_use_PrivateKey(ssl_ctx, pkey)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON(ERR_peek_error()) == EVP_R_BAD_DECRYPT)) @@ -1012,7 +1026,6 @@ backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, const char *crl_inline) { - X509_CRL *crl = NULL; BIO *in = NULL; X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx); @@ -1053,21 +1066,39 @@ goto end; } - crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); - if (crl == NULL) + int num_crls_loaded = 0; + while (true) { - msg(M_WARN, "CRL: cannot read CRL from file %s", crl_file); - goto end; - } + X509_CRL *crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL); + if (crl == NULL) + { + /* + * PEM_R_NO_START_LINE can be considered equivalent to EOF. + */ + bool eof = ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE; + /* but warn if no CRLs have been loaded */ + if (num_crls_loaded > 0 && eof) + { + /* remove that error from error stack */ + (void)ERR_get_error(); + break; + } - if (!X509_STORE_add_crl(store, crl)) - { - msg(M_WARN, "CRL: cannot add %s to store", crl_file); - goto end; - } + crypto_msg(M_WARN, "CRL: cannot read CRL from file %s", crl_file); + break; + } + if (!X509_STORE_add_crl(store, crl)) + { + X509_CRL_free(crl); + crypto_msg(M_WARN, "CRL: cannot add %s to store", crl_file); + break; + } + X509_CRL_free(crl); + num_crls_loaded++; + } + msg(M_INFO, "CRL: loaded %d CRLs from file %s", num_crls_loaded, crl_file); end: - X509_CRL_free(crl); BIO_free(in); } @@ -1434,7 +1465,7 @@ } else { - tls_ctx_add_extra_certs(ctx, in); + tls_ctx_add_extra_certs(ctx, in, false); } BIO_free(in); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpnserv/common.c new/openvpn-2.4.9/src/openvpnserv/common.c --- old/openvpn-2.4.8/src/openvpnserv/common.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpnserv/common.c 2020-04-16 15:26:45.000000000 +0200 @@ -102,8 +102,10 @@ } /* The default value of REG_KEY is the install path */ - if (GetRegString(key, NULL, install_path, sizeof(install_path), NULL) != ERROR_SUCCESS) + status = GetRegString(key, NULL, install_path, sizeof(install_path), NULL); + if (status != ERROR_SUCCESS) { + error = status; goto out; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/src/openvpnserv/interactive.c new/openvpn-2.4.9/src/openvpnserv/interactive.c --- old/openvpn-2.4.8/src/openvpnserv/interactive.c 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/src/openvpnserv/interactive.c 2020-04-16 15:26:45.000000000 +0200 @@ -360,14 +360,13 @@ /* * Validate options against a white list. Also check the config_file is * inside the config_dir. The white list is defined in validate.c - * Returns true on success + * Returns true on success, false on error with reason set in errmsg. */ static BOOL -ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options) +ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options, WCHAR *errmsg, DWORD capacity) { WCHAR **argv; int argc; - WCHAR buf[256]; BOOL ret = FALSE; int i; const WCHAR *msg1 = L"You have specified a config file location (%s relative to %s)" @@ -382,8 +381,10 @@ if (!argv) { - ReturnLastError(pipe, L"CommandLineToArgvW"); - ReturnError(pipe, ERROR_STARTUP_DATA, L"Cannot validate options", 1, &exit_event); + swprintf(errmsg, capacity, + L"Cannot validate options: CommandLineToArgvW failed with error = 0x%08x", + GetLastError()); + errmsg[capacity-1] = L'\0'; goto out; } @@ -403,10 +404,9 @@ if (!CheckOption(workdir, 2, argv_tmp, &settings)) { - swprintf(buf, _countof(buf), msg1, argv[0], workdir, + swprintf(errmsg, capacity, msg1, argv[0], workdir, settings.ovpn_admin_group); - buf[_countof(buf) - 1] = L'\0'; - ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); + errmsg[capacity-1] = L'\0'; } goto out; } @@ -422,18 +422,15 @@ { if (wcscmp(L"--config", argv[i]) == 0 && argc-i > 1) { - swprintf(buf, _countof(buf), msg1, argv[i+1], workdir, + swprintf(errmsg, capacity, msg1, argv[i+1], workdir, settings.ovpn_admin_group); - buf[_countof(buf) - 1] = L'\0'; - ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } else { - swprintf(buf, _countof(buf), msg2, argv[i], + swprintf(errmsg, capacity, msg2, argv[i], settings.ovpn_admin_group); - buf[_countof(buf) - 1] = L'\0'; - ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } + errmsg[capacity-1] = L'\0'; goto out; } } @@ -1352,7 +1349,7 @@ RunOpenvpn(LPVOID p) { HANDLE pipe = p; - HANDLE ovpn_pipe, svc_pipe; + HANDLE ovpn_pipe = NULL, svc_pipe = NULL; PTOKEN_USER svc_user = NULL, ovpn_user = NULL; HANDLE svc_token = NULL, imp_token = NULL, pri_token = NULL; HANDLE stdin_read = NULL, stdin_write = NULL; @@ -1367,6 +1364,7 @@ WCHAR *cmdline = NULL; size_t cmdline_size; undo_lists_t undo_lists; + WCHAR errmsg[512] = L""; SECURITY_ATTRIBUTES inheritable = { .nLength = sizeof(inheritable), @@ -1459,10 +1457,17 @@ goto out; } - /* Check user is authorized or options are white-listed */ - if (!IsAuthorizedUser(ovpn_user->User.Sid, imp_token, settings.ovpn_admin_group) - && !ValidateOptions(pipe, sud.directory, sud.options)) + /* + * Only authorized users are allowed to use any command line options or + * have the config file in locations other than the global config directory. + * + * Check options are white-listed and config is in the global directory + * OR user is authorized to run any config. + */ + if (!ValidateOptions(pipe, sud.directory, sud.options, errmsg, _countof(errmsg)) + && !IsAuthorizedUser(ovpn_user->User.Sid, imp_token, settings.ovpn_admin_group)) { + ReturnError(pipe, ERROR_STARTUP_DATA, errmsg, 1, &exit_event); goto out; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/openvpn-2.4.8/version.m4 new/openvpn-2.4.9/version.m4 --- old/openvpn-2.4.8/version.m4 2019-10-30 13:37:55.000000000 +0100 +++ new/openvpn-2.4.9/version.m4 2020-04-16 15:26:45.000000000 +0200 @@ -3,12 +3,12 @@ define([PRODUCT_TARNAME], [openvpn]) define([PRODUCT_VERSION_MAJOR], [2]) define([PRODUCT_VERSION_MINOR], [4]) -define([PRODUCT_VERSION_PATCH], [.8]) +define([PRODUCT_VERSION_PATCH], [.9]) m4_append([PRODUCT_VERSION], [PRODUCT_VERSION_MAJOR]) m4_append([PRODUCT_VERSION], [PRODUCT_VERSION_MINOR], [[.]]) m4_append([PRODUCT_VERSION], [PRODUCT_VERSION_PATCH], [[]]) define([PRODUCT_BUGREPORT], [[email protected]]) -define([PRODUCT_VERSION_RESOURCE], [2,4,8,0]) +define([PRODUCT_VERSION_RESOURCE], [2,4,9,0]) dnl define the TAP version define([PRODUCT_TAP_WIN_COMPONENT_ID], [tap0901]) define([PRODUCT_TAP_WIN_MIN_MAJOR], [9]) ++++++ openvpn.keyring ++++++ --- /var/tmp/diff_new_pack.PFTb7F/_old 2020-09-23 18:38:32.473219518 +0200 +++ /var/tmp/diff_new_pack.PFTb7F/_new 2020-09-23 18:38:32.473219518 +0200 @@ -1,6 +1,6 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -mQINBFicXUkBEAC9j2L+kJxqetXfslRL/UOqZUNpfNGUjpP2yb+j9UYdZbS3dq67 +xsFNBFicXUkBEAC9j2L+kJxqetXfslRL/UOqZUNpfNGUjpP2yb+j9UYdZbS3dq67 i0oYINqKRO4fZEg0VLpW611fTUL3qhKADmSlrktY8p26T79I/TYAUuwlijTFKUVw 3RGpMsfuldnk007uhx7Go5Ss6y7fPzwWxhvwuRhNdh8I+vswrsBMp08dQ36sIjnv 5QQ1MekBiIiOnMwQBgUUSG7rsbGtrIlW0mlScO3fOAI2CtT2J4s3uGnktKsGSuoe @@ -11,75 +11,281 @@ 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 -FKGqKh6WaFt+aJ7PQAHUDxo1A6Fe+8DScg== -=Xpiz +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 +PPD9yqBR8Ls7c8cf/fe1xhFPL3FEEpkpnq7/pg== +=PV0e -----END PGP PUBLIC KEY BLOCK-----
