From patchwork Fri Mar 19 04:31:28 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1636 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director9.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id +H/yOh/EVGBkSAAAIUCqbw (envelope-from ) for ; Fri, 19 Mar 2021 11:32:47 -0400 Received: from proxy18.mail.iad3b.rsapps.net ([172.31.255.6]) by director9.mail.ord1d.rsapps.net with LMTP id KB/sOh/EVGAPIgAAalYnBA (envelope-from ) for ; Fri, 19 Mar 2021 11:32:47 -0400 Received: from smtp2.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy18.mail.iad3b.rsapps.net with LMTPS id CLOjMh/EVGAiWAAA3NpJmQ (envelope-from ) for ; Fri, 19 Mar 2021 11:32:47 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp2.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 5ac8a65c-88c8-11eb-ac77-5254000fbace-1-1 Received: from [216.105.38.7] ([216.105.38.7:49186] helo=lists.sourceforge.net) by smtp2.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id AC/09-28034-E14C4506; Fri, 19 Mar 2021 11:32:47 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.92.3) (envelope-from ) id 1lNH6M-00067c-KC; Fri, 19 Mar 2021 15:31:50 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) (envelope-from ) id 1lNH6E-000679-Ao for openvpn-devel@lists.sourceforge.net; Fri, 19 Mar 2021 15:31:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc: MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=MHRBdXLWB5NAHZTOsXSMbh8jUuQAxx9QsYt/CNJBuGE=; b=LId6jyIhOxM6ebNxT8BEAw8UdX on8o7Wo2SBatWZ9IK/vai+3eSUkiuABckqJ7tj0jCq2AIaG4xjWtuGzG8HpngAVcUIkQECAERZ5A0 pL8/Adiogwx8CrM3np1RIwtTRBchp+eeSB6uClRvC7lnGNCiEbkZWUE1PlIJzZNSoC3Y=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:MIME-Version: Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=MHRBdXLWB5NAHZTOsXSMbh8jUuQAxx9QsYt/CNJBuGE=; b=Y43Grv4bDHcWGdAgPgVK+dEhQe uabfoDLXL20vADXchH8DcUpTNqlCiXfnM8lWcIYlSlxmShANGv5QbKJpCwIdFYQbFTtxHNUxSVZUM ocC4HKKyZ33Z/Zug/ete7sC4ISdkY67GLGE0YUxX6RWFM4RMSe39J/UQWETkImIh+jO4=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) id 1lNH69-00029R-01 for openvpn-devel@lists.sourceforge.net; Fri, 19 Mar 2021 15:31:40 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.94 (FreeBSD)) (envelope-from ) id 1lNH61-000Mo3-ON for openvpn-devel@lists.sourceforge.net; Fri, 19 Mar 2021 16:31:29 +0100 Received: (nullmailer pid 8778 invoked by uid 10006); Fri, 19 Mar 2021 15:31:29 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Fri, 19 Mar 2021 16:31:28 +0100 Message-Id: <20210319153129.8734-1-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: rfc2549.org] 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1lNH69-00029R-01 Subject: [Openvpn-devel] [PATCH 1/2] Move extract_iv_proto to ssl_util.c/h X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox This function is used by both NCP and push, so move it to a more proper place. Signed-off-by: Arne Schwabe Acked-By: David Sommerseth --- src/openvpn/multi.c | 1 + src/openvpn/push.c | 18 +----------------- src/openvpn/push.h | 10 ---------- src/openvpn/ssl_util.c | 16 ++++++++++++++++ src/openvpn/ssl_util.h | 8 ++++++++ 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index d10f188c..f7e0f680 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -51,6 +51,7 @@ #include "crypto_backend.h" +#include "ssl_util.h" /*#define MULTI_DEBUG_EVENT_LOOP*/ diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 320ad737..a6519557 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -37,6 +37,7 @@ #include "manage.h" #include "memdbg.h" +#include "ssl_util.h" #if P2MP @@ -1057,21 +1058,4 @@ remove_iroutes_from_push_route_list(struct options *o) gc_free(&gc); } } - -unsigned int -extract_iv_proto(const char *peer_info) -{ - const char *optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; - if (optstr) - { - int proto = 0; - int r = sscanf(optstr, "IV_PROTO=%d", &proto); - if (r == 1 && proto > 0) - { - return proto; - } - } - return 0; -} - #endif /* if P2MP */ diff --git a/src/openvpn/push.h b/src/openvpn/push.h index 377f94a6..bb787a62 100644 --- a/src/openvpn/push.h +++ b/src/openvpn/push.h @@ -91,16 +91,6 @@ void send_restart(struct context *c, const char *kill_msg); */ void send_push_reply_auth_token(struct tls_multi *multi); - -/** - * Extracts the IV_PROTO variable and returns its value or 0 - * if it cannot be extracted. - * - * @param peer_info peer info string to search for IV_PROTO - */ -unsigned int -extract_iv_proto(const char *peer_info); - /** * Parses an AUTH_PENDING message and if in pull mode extends the timeout * diff --git a/src/openvpn/ssl_util.c b/src/openvpn/ssl_util.c index a74e3b72..f6e66be4 100644 --- a/src/openvpn/ssl_util.c +++ b/src/openvpn/ssl_util.c @@ -59,3 +59,19 @@ extract_var_peer_info(const char *peer_info, const char *var, var_value[var_end - var_start] = '\0'; return var_value; } + +unsigned int +extract_iv_proto(const char *peer_info) +{ + const char *optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; + if (optstr) + { + int proto = 0; + int r = sscanf(optstr, "IV_PROTO=%d", &proto); + if (r == 1 && proto > 0) + { + return proto; + } + } + return 0; +} diff --git a/src/openvpn/ssl_util.h b/src/openvpn/ssl_util.h index bc2ae30d..741a7782 100644 --- a/src/openvpn/ssl_util.h +++ b/src/openvpn/ssl_util.h @@ -46,4 +46,12 @@ extract_var_peer_info(const char *peer_info, const char *var, struct gc_arena *gc); +/** + * Extracts the IV_PROTO variable and returns its value or 0 + * if it cannot be extracted. + * + * @param peer_info peer info string to search for IV_PROTO + */ +unsigned int +extract_iv_proto(const char *peer_info); #endif From patchwork Fri Mar 19 04:31:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 1637 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director12.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id 0JrSDSrEVGCfVwAAIUCqbw (envelope-from ) for ; Fri, 19 Mar 2021 11:32:58 -0400 Received: from proxy1.mail.iad3b.rsapps.net ([172.31.255.6]) by director12.mail.ord1d.rsapps.net with LMTP id QI7YDSrEVGA/LwAAIasKDg (envelope-from ) for ; Fri, 19 Mar 2021 11:32:58 -0400 Received: from smtp36.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy1.mail.iad3b.rsapps.net with LMTPS id GAJeBSrEVGC0eQAALM5PBw (envelope-from ) for ; Fri, 19 Mar 2021 11:32:58 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp36.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 60fd43c0-88c8-11eb-b870-5254003a7283-1-1 Received: from [216.105.38.7] ([216.105.38.7:49234] helo=lists.sourceforge.net) by smtp36.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id DD/A1-07797-924C4506; Fri, 19 Mar 2021 11:32:57 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.92.3) (envelope-from ) id 1lNH6I-00067L-Dv; Fri, 19 Mar 2021 15:31:49 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.3) (envelope-from ) id 1lNH6C-000672-MX for openvpn-devel@lists.sourceforge.net; Fri, 19 Mar 2021 15:31:42 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:To: From:Sender:Reply-To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=xHvNWlXd/P0yCVhZeM1EVtWP+tl9kx1gjDYZeckX9go=; b=U1oeERUuumTS/S+/tK9GRQ817c v97hTMHV2BezqvwEu2fkmQXC4LzyFOH7C8uqX7TFuF48inWIo7Gusvqn+iyl/f5VhHcW100K7hkbg oxM3WFUMRIiSlCnpUrVF78CZIRfxgh/huzx7hgaKIV/A7NaYBc7l8QV6Ytw8MZ7pwLQ0=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=xHvNWlXd/P0yCVhZeM1EVtWP+tl9kx1gjDYZeckX9go=; b=Vd9rdmvEmCQi4eRxukmUOuglMO uyF/f25wB8c430gR0I1/uoms6J/xkFf9InxKUwQrFVKXxTLx9t/h0c/J7qah/4dPcI+qz74v7qfgw 9Eo2wCpHAPGBwJkk6HTRYEPz/1qkZ+a0/32q/ZOqGAMH915zJmEbST66S95plKuRWrjg=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.92.2) id 1lNH68-002BPF-7D for openvpn-devel@lists.sourceforge.net; Fri, 19 Mar 2021 15:31:40 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.94 (FreeBSD)) (envelope-from ) id 1lNH61-000Mo5-QU for openvpn-devel@lists.sourceforge.net; Fri, 19 Mar 2021 16:31:29 +0100 Received: (nullmailer pid 8781 invoked by uid 10006); Fri, 19 Mar 2021 15:31:29 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Fri, 19 Mar 2021 16:31:29 +0100 Message-Id: <20210319153129.8734-2-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210319153129.8734-1-arne@rfc2549.org> References: <20210319153129.8734-1-arne@rfc2549.org> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: makefile.am] 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record X-Headers-End: 1lNH68-002BPF-7D Subject: [Openvpn-devel] [PATCH 2/2] Implement '--compress migrate' to migrate to non-compression setup X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox This option allow migration to a non compression server config while still retraining compatibility with client that have a compression setting in their config. For existing setups that used to have comp-lzo no or another compression setting in their configs it is a difficult to migrate to a setup without compression without replacing all client configs at once especially if OpenVPN 2.3 or earlier clients are in the mix that do not support pushing stub-v2. Even with OpenVPN 2.4 and later clients that support pushing this is not a satisfying solution as the clients log occ mismatches and the "push stub-v2" needs to be in the server config "forever". Signed-off-by: Arne Schwabe --- doc/man-sections/protocol-options.rst | 12 +++- src/openvpn/comp.h | 1 + src/openvpn/multi.c | 41 +++++++++++++ src/openvpn/options.c | 6 ++ src/openvpn/ssl.c | 34 ++++++++++- src/openvpn/ssl_common.h | 1 + src/openvpn/ssl_util.c | 43 ++++++++++++++ src/openvpn/ssl_util.h | 15 +++++ tests/unit_tests/openvpn/Makefile.am | 14 ++++- tests/unit_tests/openvpn/test_misc.c | 83 +++++++++++++++++++++++++++ 10 files changed, 245 insertions(+), 5 deletions(-) create mode 100644 tests/unit_tests/openvpn/test_misc.c diff --git a/doc/man-sections/protocol-options.rst b/doc/man-sections/protocol-options.rst index e9d5d63d..c5cd76dd 100644 --- a/doc/man-sections/protocol-options.rst +++ b/doc/man-sections/protocol-options.rst @@ -84,10 +84,10 @@ configured in a compatible way between both the local and remote side. --compress algorithm **DEPRECATED** Enable a compression algorithm. Compression is generally not recommended. VPN tunnels which use compression are susceptible to - the VORALCE attack vector. + the VORALCE attack vector. See also the :code:`migrate` parameter below. The ``algorithm`` parameter may be :code:`lzo`, :code:`lz4`, - :code:`lz4-v2`, :code:`stub`, :code:`stub-v2` or empty. + :code:`lz4-v2`, :code:`stub`, :code:`stub-v2`, :code:`migrate` or empty. LZO and LZ4 are different compression algorithms, with LZ4 generally offering the best performance with least CPU usage. @@ -106,6 +106,14 @@ configured in a compatible way between both the local and remote side. Note: the :code:`stub` (or empty) option is NOT compatible with the older option ``--comp-lzo no``. + The :code:`migrate` algorithm is a special and is intended to allow + migration away from ``--compress``/``--comp-lzo`` options to no compression. + This options set the server to no compression mode. If a client + is detected that indicates that compression is used the will automatically + add ``--push compress stub-v2`` to the client specific configuration + if supported by the client and otherwise switch to ``comp-lzo no`` + and also ``--push comp-lzo`` to the client specific configuration. + ***Security Considerations*** Compression and encryption is a tricky combination. If an attacker knows diff --git a/src/openvpn/comp.h b/src/openvpn/comp.h index 5c0322ca..a880e198 100644 --- a/src/openvpn/comp.h +++ b/src/openvpn/comp.h @@ -58,6 +58,7 @@ #define COMP_F_ADVERTISE_STUBS_ONLY (1<<3) /* tell server that we only support compression stubs */ #define COMP_F_ALLOW_STUB_ONLY (1<<4) /* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY * we still accept other compressions to be pushed */ +#define COMP_F_MIGRATE (1<<5) /* push stub-v2 or comp-lzo no when we see a client with comp-lzo in occ */ /* diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c index f7e0f680..3060410d 100644 --- a/src/openvpn/multi.c +++ b/src/openvpn/multi.c @@ -2469,6 +2469,46 @@ multi_client_connect_early_setup(struct multi_context *m, multi_client_connect_setenv(m, mi); } +/** + * Do the necessary modification for doing the compress mitigrate. This is + * implemented as a connect handler as it fits the modify config for a client + * paradigm and also is early enough in the chain to be overwritten by another + * ccd/script to do compression on a special client. + */ +static enum client_connect_return +multi_client_connect_compress_migrate(struct multi_context *m, + struct multi_instance *mi, + bool deferred, + unsigned int *option_types_found) +{ + struct options *o = &mi->context.options; + const char *const peer_info =mi->context.c2.tls_multi->peer_info; + + if (!peer_info) + { + return CC_RET_SUCCEEDED; + } + + + if (o->comp.flags & COMP_F_MIGRATE && mi->context.c2.tls_multi->remote_usescomp) + { + if(strstr(peer_info, "IV_COMP_STUBv2=1")) + { + push_option(o, "compress stub-v2", M_USAGE); + } + else + { + /* Client is old and does not support STUBv2 but since it + * announced comp-lzo via OCC we assume it uses comp-lzo, so + * switch to that and pushed the uncompressed variant. */ + push_option(o, "comp-lzo no", M_USAGE); + o->comp.alg = COMP_ALG_STUB; + *option_types_found |= OPT_P_COMP; + } + } + return CC_RET_SUCCEEDED; +} + /** * Try to source a dynamic config file from the * --client-config-dir directory. @@ -2537,6 +2577,7 @@ typedef enum client_connect_return (*multi_client_connect_handler) bool from_deferred, unsigned int *option_types_found); static const multi_client_connect_handler client_connect_handlers[] = { + multi_client_connect_compress_migrate, multi_client_connect_source_ccd, multi_client_connect_call_plugin_v1, multi_client_connect_call_plugin_v2, diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 86e78b05..f0d1e128 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -7692,6 +7692,12 @@ add_option(struct options *options, options->comp.alg = COMP_ALGV2_UNCOMPRESSED; options->comp.flags |= COMP_F_ADVERTISE_STUBS_ONLY; } + else if (streq(p[1], "migrate")) + { + options->comp.alg = COMP_ALG_UNDEF; + options->comp.flags = COMP_F_MIGRATE; + + } else if (options->comp.flags & COMP_F_ALLOW_STUB_ONLY) { /* Also printed on a push to hint at configuration problems */ diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 893e5753..7ab8d585 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -60,6 +60,7 @@ #include "ssl_verify.h" #include "ssl_backend.h" #include "ssl_ncp.h" +#include "ssl_util.h" #include "auth_token.h" #include "memdbg.h" @@ -2235,6 +2236,16 @@ error: return ret; } +static bool +write_compat_local_options(struct buffer *buf, const char *options) +{ + struct gc_arena gc = gc_new(); + const char* local_options = options_string_compat_lzo(options, &gc); + bool ret = write_string(buf, local_options, TLS_OPTIONS_LEN); + gc_free(&gc); + return ret; +} + /** * Handle the writing of key data, peer-info, username/password, OCC * to the TLS control channel (cleartext). @@ -2266,7 +2277,15 @@ key_method_2_write(struct buffer *buf, struct tls_session *session) /* write options string */ { - if (!write_string(buf, session->opt->local_options, TLS_OPTIONS_LEN)) + if (multi->remote_usescomp && session->opt->mode == MODE_SERVER + && multi->opt.comp_options.flags & COMP_F_MIGRATE) + { + if (!write_compat_local_options(buf, session->opt->local_options)) + { + goto error; + } + } + else if (!write_string(buf, session->opt->local_options, TLS_OPTIONS_LEN)) { goto error; } @@ -2460,6 +2479,7 @@ key_method_2_read(struct buffer *buf, struct tls_multi *multi, struct tls_sessio free(multi->remote_ciphername); multi->remote_ciphername = options_string_extract_option(options, "cipher", NULL); + multi->remote_usescomp = strstr(options, ",comp-lzo,") != NULL; /* In OCC we send '[null-cipher]' instead 'none' */ if (multi->remote_ciphername @@ -2509,7 +2529,17 @@ key_method_2_read(struct buffer *buf, struct tls_multi *multi, struct tls_sessio if (!session->opt->disable_occ && !options_cmp_equal(options, session->opt->remote_options)) { - options_warning(options, session->opt->remote_options); + const char *remote_options = session->opt->remote_options; + if (multi->opt.comp_options.flags & COMP_F_MIGRATE && multi->remote_usescomp) + { + msg(D_SHOW_OCC, "Note: --comp-lzo migrate is enabled and remote " + "announces comp-lzo, consider removing " + "compress/comp-lzo options from remote config."); + remote_options = options_string_compat_lzo(remote_options, &gc); + } + + options_warning(options, remote_options); + if (session->opt->ssl_flags & SSLF_OPT_VERIFY) { msg(D_TLS_ERRORS, "Option inconsistency warnings triggering disconnect due to --opt-verify"); diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 2e3c98db..5791b014 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -574,6 +574,7 @@ struct tls_multi bool use_peer_id; char *remote_ciphername; /**< cipher specified in peer's config file */ + bool remote_usescomp; /**< remote announced comp-lzo in OCC string */ /* * Our session objects. diff --git a/src/openvpn/ssl_util.c b/src/openvpn/ssl_util.c index f6e66be4..38b371f1 100644 --- a/src/openvpn/ssl_util.c +++ b/src/openvpn/ssl_util.c @@ -75,3 +75,46 @@ extract_iv_proto(const char *peer_info) } return 0; } + +const char * +options_string_compat_lzo(const char *options, struct gc_arena *gc) +{ + + /* comp-lzo: 'V4,dev-type tun,link-mtu 1458,tun-mtu 1400,proto UDPv4,comp-lzo,auth SHA1,keysize 128,key-method 2,tls-server' */ + /* w/o comp: 'V4,dev-type tun,link-mtu 1457,tun-mtu 1400,proto UDPv4,auth SHA1,keysize 128,key-method 2,tls-server' */ + + + /* Note: since this function is used only in a very limited scope it makes + * assumptions how the string looks. Since we locally generated the string + * we can make these assumptions */ + + + /* Check that the link-mtu string is in options */ + const char* tmp = strstr(options, ",link-mtu"); + if (!tmp) + { + return options; + } + + /* Get old link_mtu size */ + int link_mtu; + if(sscanf(tmp, ",link-mtu %d,", &link_mtu) !=1 || link_mtu < 100 || link_mtu > 9000) + { + return options; + } + + struct buffer buf = alloc_buf_gc(strlen(options) + strlen(",comp-lzo") + 2, gc); + + + buf_write(&buf, options, (int)(tmp - options)); + + /* Increase link-mtu by one for the comp-lzo opcode */ + buf_printf(&buf, ",link-mtu %d", link_mtu + 1); + + tmp += strlen(",link-mtu ") + (link_mtu < 1000 ? 3 : 4); + + buf_printf(&buf, "%s,comp-lzo", tmp); + + return BSTR(&buf); + +} diff --git a/src/openvpn/ssl_util.h b/src/openvpn/ssl_util.h index 741a7782..472aa591 100644 --- a/src/openvpn/ssl_util.h +++ b/src/openvpn/ssl_util.h @@ -54,4 +54,19 @@ extract_var_peer_info(const char *peer_info, */ unsigned int extract_iv_proto(const char *peer_info); + +/** + * Takes a locally produced OCC string for TLS server mode and modifies as + * if the option comp-lzo was enabled. This is to send a client in + * comp-lzo migrate mode the expected OCC string. + * + * Note: This function excpets the string to be in the locally generated + * format and does not accept arbitrary strings. + * + * @param options the locally generated OCC string + * @param gc gc_arena to allocate the returned string in + * @return the modified string or options on error + */ +const char * +options_string_compat_lzo(const char *options, struct gc_arena *gc); #endif diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index 50f3a02e..524ef50d 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -6,7 +6,7 @@ if HAVE_LD_WRAP_SUPPORT test_binaries += argv_testdriver buffer_testdriver endif -test_binaries += crypto_testdriver packet_id_testdriver auth_token_testdriver ncp_testdriver +test_binaries += crypto_testdriver packet_id_testdriver auth_token_testdriver ncp_testdriver misc_testdriver if HAVE_LD_WRAP_SUPPORT test_binaries += tls_crypt_testdriver endif @@ -127,3 +127,15 @@ ncp_testdriver_SOURCES = test_ncp.c mock_msg.c \ $(openvpn_srcdir)/packet_id.c \ $(openvpn_srcdir)/platform.c \ $(openvpn_srcdir)/ssl_util.c + + +misc_testdriver_CFLAGS = @TEST_CFLAGS@ \ + -I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) + +misc_testdriver_LDFLAGS = @TEST_LDFLAGS@ + +misc_testdriver_SOURCES = test_misc.c mock_msg.c \ + mock_get_random.c \ + $(openvpn_srcdir)/buffer.c \ + $(openvpn_srcdir)/ssl_util.c \ + $(openvpn_srcdir)/platform.c \ No newline at end of file diff --git a/tests/unit_tests/openvpn/test_misc.c b/tests/unit_tests/openvpn/test_misc.c new file mode 100644 index 00000000..4fcf82c1 --- /dev/null +++ b/tests/unit_tests/openvpn/test_misc.c @@ -0,0 +1,83 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2019 Arne Schwabe + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "ssl_util.h" + +static void +test_compat_lzo_string(void **state) +{ + struct gc_arena gc = gc_new(); + + const char* input = "V4,dev-type tun,link-mtu 1457,tun-mtu 1400,proto UDPv4,auth SHA1,keysize 128,key-method 2,tls-server"; + + const char* output = options_string_compat_lzo(input, &gc); + + assert_string_equal(output, "V4,dev-type tun,link-mtu 1458,tun-mtu 1400,proto UDPv4,auth SHA1,keysize 128,key-method 2,tls-server,comp-lzo"); + + /* This string is has a much too small link-mtu so we should fail on it" */ + input = "V4,dev-type tun,link-mtu 2,tun-mtu 1400,proto UDPv4,auth SHA1,keysize 128,key-method 2,tls-server"; + + output = options_string_compat_lzo(input, &gc); + + assert_string_equal(input, output); + + /* not matching at all */ + input = "V4,dev-type tun"; + output = options_string_compat_lzo(input, &gc); + + assert_string_equal(input, output); + + + input = "V4,dev-type tun,link-mtu 999,tun-mtu 1400,proto UDPv4,auth SHA1,keysize 128,key-method 2,tls-server"; + output = options_string_compat_lzo(input, &gc); + + /* 999 -> 1000, 3 to 4 chars */ + assert_string_equal(output, "V4,dev-type tun,link-mtu 1000,tun-mtu 1400,proto UDPv4,auth SHA1,keysize 128,key-method 2,tls-server,comp-lzo"); + +}; + +const struct CMUnitTest misc_tests[] = { + cmocka_unit_test(test_compat_lzo_string), +}; + +int +main(void) +{ + return cmocka_run_group_tests(misc_tests, NULL, NULL); +}