From patchwork Mon Jul 18 12:17:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Quartulli X-Patchwork-Id: 2590 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director8.mail.ord1d.rsapps.net ([172.28.255.1]) by backend30.mail.ord1d.rsapps.net with LMTP id QB+TJjvc1WKCUgAAIUCqbw (envelope-from ) for ; Mon, 18 Jul 2022 18:18:35 -0400 Received: from proxy8.mail.ord1c.rsapps.net ([172.28.255.1]) by director8.mail.ord1d.rsapps.net with LMTP id 8A91Jjvc1WLBMwAAfY0hYg (envelope-from ) for ; Mon, 18 Jul 2022 18:18:35 -0400 Received: from smtp28.gate.ord1c ([172.28.255.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy8.mail.ord1c.rsapps.net with LMTPS id 2KpHJjvc1WLhOgAAHz/atg (envelope-from ) for ; Mon, 18 Jul 2022 18:18:35 -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: smtp28.gate.ord1c.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=unstable.cc X-Suspicious-Flag: YES X-Classification-ID: 90575090-06e7-11ed-a9dd-a0369f1890f1-1-1 Received: from [216.105.38.7] ([216.105.38.7:48616] helo=lists.sourceforge.net) by smtp28.gate.ord1c.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 45/F6-31896-B3CD5D26; Mon, 18 Jul 2022 18:18:35 -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.94.2) (envelope-from ) id 1oDZ3W-0006we-1f; Mon, 18 Jul 2022 22:17:34 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1oDZ3U-0006wX-Q6 for openvpn-devel@lists.sourceforge.net; Mon, 18 Jul 2022 22:17:33 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type: 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=NZCFKD5S0qAdMfZzmNTSmnTJo4r7pxz5ydYwdyAbFrk=; b=WIlOZGED5UevsTGT5xXyjSlnsT hHC4Yva82Fze4yx9pWhrTFnmuMQk414XTKbwh1EUJ181RVI+ZeEL70y1Fs1cANHjshNv11BSJFlxu XTdgjzhHkLw0eliODX97KMeBPIhWwM3omrHIE7m8QkfEc1DNZubVUCXqG2wpDLyfIpeY=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type: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=NZCFKD5S0qAdMfZzmNTSmnTJo4r7pxz5ydYwdyAbFrk=; b=gXDRAxw/oHryjUJcYjTob4GeOi uvHeZ21gTA+eEKAt/StbOCqAWqZaz72y4M+bhc4rbPDr8LWX4fZHgluCku8EvR23ZPeSoVlpWh5LP 4GJOPawRcAs8UgixBbBvuf47LDRc2gIMpuGNo8CXRz4LF0GNV1fUUx9C8lobrc1YWvRg=; Received: from s2.neomailbox.net ([5.148.176.60]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.94.2) id 1oDZ3T-003Ls4-Jy for openvpn-devel@lists.sourceforge.net; Mon, 18 Jul 2022 22:17:33 +0000 From: Antonio Quartulli To: openvpn-devel@lists.sourceforge.net Date: Tue, 19 Jul 2022 00:17:57 +0200 Message-Id: <20220718221757.545-1-a@unstable.cc> In-Reply-To: <20220712221341.16175-1-a@unstable.cc> References: MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-2.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: Signed-off-by: Antonio Quartulli --- ** this patch should be applied before 05/27 ** Changes from v2: * add actual invocation to dco_check_option_conflict() in options.c * add missing '}' in dco_check_option_conflict_ce() Content analysis details: (-0.0 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record X-Headers-End: 1oDZ3T-003Ls4-Jy Subject: [Openvpn-devel] [PATCH v3 07/25] dco: add option check - disable DCO if conflict is detected 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: , Cc: Antonio Quartulli Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox Signed-off-by: Antonio Quartulli Acked-by: Gert Doering --- ** this patch should be applied before 05/27 ** Changes from v2: * add actual invocation to dco_check_option_conflict() in options.c * add missing '}' in dco_check_option_conflict_ce() Changes from v1: * add 'already existing device check' to dco_check_option_conflict_platform() so that DCO can be pre-emptively disabled if the following are true: - an iface with the same name as provided by the user exists - the iface is non-DCO src/openvpn/Makefile.am | 2 +- src/openvpn/dco.c | 190 ++++++++++++++++++++++++++++ src/openvpn/openvpn.vcxproj | 1 + src/openvpn/openvpn.vcxproj.filters | 3 + src/openvpn/options.c | 5 + 5 files changed, 200 insertions(+), 1 deletion(-) create mode 100644 src/openvpn/dco.c diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 91635b67..aaa1dbce 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -53,7 +53,7 @@ openvpn_SOURCES = \ crypto.c crypto.h crypto_backend.h \ crypto_openssl.c crypto_openssl.h \ crypto_mbedtls.c crypto_mbedtls.h \ - dco.h dco_internal.h \ + dco.c dco.h dco_internal.h \ dco_linux.c dco_linux.h \ dhcp.c dhcp.h \ dns.c dns.h \ diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c new file mode 100644 index 00000000..b3fd135f --- /dev/null +++ b/src/openvpn/dco.c @@ -0,0 +1,190 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2021-2022 Arne Schwabe + * Copyright (C) 2021-2022 Antonio Quartulli + * Copyright (C) 2021-2022 OpenVPN Inc + * + * 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 (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#if defined(ENABLE_DCO) + +#include "syshead.h" +#include "dco.h" +#include "networking.h" +#include "options.h" +#include "ssl_ncp.h" +#include "tun.h" + +static bool +dco_check_option_conflict_platform(int msglevel, const struct options *o) +{ +#if defined(TARGET_LINUX) + /* if the device name is fixed, we need to check if an interface with this + * name already exists. IF it does, it must be a DCO interface, otherwise + * DCO has to be disabled in order to continue. + */ + if (tun_name_is_fixed(o->dev)) + { + char iftype[IFACE_TYPE_LEN_MAX]; + /* we pass NULL as net_ctx because using DCO on Linux implies that we + * are using SITNL and the latter does not need any context. This way we + * don't need to have the net_ctx percolate all the way here + */ + int ret = net_iface_type(NULL, o->dev, iftype); + if ((ret == 0) && (strcmp(iftype, "ovpn-dco") != 0)) + { + msg(msglevel, "Interface %s exists and is non-DCO. Disabling data channel offload", + o->dev); + return false; + } + else if ((ret < 0) && (ret != -ENODEV)) + { + msg(msglevel, "Cannot retrieve type of device %s: %s (%d)", o->dev, + strerror(-ret), ret); + } + } +#endif /* if defined(TARGET_LINUX) */ + return true; +} + +static bool +dco_check_option_conflict_ce(const struct connection_entry *ce, int msglevel) +{ + if (ce->fragment) + { + msg(msglevel, "Note: --fragment disables data channel offload."); + return false; + } + + if (ce->http_proxy_options) + { + msg(msglevel, "Note: --http-proxy disables data channel offload."); + return false; + } + + if (ce->socks_proxy_server) + { + msg(msglevel, "Note: --socks-proxy disables data channel offload."); + return false; + } + + return true; +} + +bool +dco_check_option_conflict(int msglevel, const struct options *o) +{ + if (o->tuntap_options.disable_dco) + { + /* already disabled by --disable-dco, no need to print warnings */ + return false; + } + + if (!dco_available(msglevel)) + { + return false; + } + + if (!dco_check_option_conflict_platform(msglevel, o)) + { + return false; + } + + if (dev_type_enum(o->dev, o->dev_type) != DEV_TYPE_TUN) + { + msg(msglevel, "Note: dev-type not tun, disabling data channel offload."); + return false; + } + + /* At this point the ciphers have already been normalised */ + if (o->enable_ncp_fallback + && !tls_item_in_cipher_list(o->ciphername, DCO_SUPPORTED_CIPHERS)) + { + msg(msglevel, "Note: --data-cipher-fallback with cipher '%s' " + "disables data channel offload.", o->ciphername); + return false; + } + + if (o->connection_list) + { + const struct connection_list *l = o->connection_list; + for (int i = 0; i < l->len; ++i) + { + if (!dco_check_option_conflict_ce(l->array[i], msglevel)) + { + return false; + } + } + } + else + { + if (!dco_check_option_conflict_ce(&o->ce, msglevel)) + { + return false; + } + } + + if (o->mode == MODE_SERVER && o->topology != TOP_SUBNET) + { + msg(msglevel, "Note: NOT using '--topology subnet' disables data channel offload."); + return false; + } + +#if defined(USE_COMP) + if (o->comp.alg != COMP_ALG_UNDEF) + { + msg(msglevel, "Note: Using compression disables data channel offload."); + + if (o->mode == MODE_SERVER && !(o->comp.flags & COMP_F_MIGRATE)) + { + /* We can end up here from the multi.c call, only print the + * note if it is not already enabled */ + msg(msglevel, "Consider using the '--compress migrate' option."); + } + return false; + } +#endif + + struct gc_arena gc = gc_new(); + char *tmp_ciphers = string_alloc(o->ncp_ciphers, &gc); + const char *token; + while ((token = strsep(&tmp_ciphers, ":"))) + { + if (!tls_item_in_cipher_list(token, DCO_SUPPORTED_CIPHERS)) + { + msg(msglevel, "Note: cipher '%s' in --data-ciphers is not supported " + "by ovpn-dco, disabling data channel offload.", token); + gc_free(&gc); + return false; + } + } + gc_free(&gc); + + return true; +} + +#endif /* defined(ENABLE_DCO) */ diff --git a/src/openvpn/openvpn.vcxproj b/src/openvpn/openvpn.vcxproj index bc1a0300..0b3db7c7 100644 --- a/src/openvpn/openvpn.vcxproj +++ b/src/openvpn/openvpn.vcxproj @@ -276,6 +276,7 @@ + diff --git a/src/openvpn/openvpn.vcxproj.filters b/src/openvpn/openvpn.vcxproj.filters index 3c21a4c6..16905079 100644 --- a/src/openvpn/openvpn.vcxproj.filters +++ b/src/openvpn/openvpn.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files + Source Files diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 95d4008a..7b919a1e 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -3645,6 +3645,11 @@ options_postprocess_mutate(struct options *o, struct env_set *es) o->verify_hash_no_ca = true; } + /* check if any option should force disabling DCO */ +#if defined(TARGET_LINUX) + o->tuntap_options.disable_dco = !dco_check_option_conflict(D_DCO, o); +#endif + /* * Save certain parms before modifying options during connect, especially * when using --pull