From patchwork Wed Mar 30 04:05:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timo Rothenpieler X-Patchwork-Id: 2355 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director7.mail.ord1d.rsapps.net ([172.31.255.6]) by backend41.mail.ord1d.rsapps.net with LMTP id 0IH9Cj1yRGKObAAAqwncew (envelope-from ) for ; Wed, 30 Mar 2022 11:07:41 -0400 Received: from proxy2.mail.iad3b.rsapps.net ([172.31.255.6]) by director7.mail.ord1d.rsapps.net with LMTP id kJksEz1yRGICcgAAovjBpQ (envelope-from ) for ; Wed, 30 Mar 2022 11:07:41 -0400 Received: from smtp26.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy2.mail.iad3b.rsapps.net with LMTPS id YLsoDD1yRGINXAAAvAZTew (envelope-from ) for ; Wed, 30 Mar 2022 11:07:41 -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: smtp26.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; dkim=fail (signature verification failed) header.d=rothenpieler.org; dmarc=fail (p=none; dis=none) header.from=rothenpieler.org X-Suspicious-Flag: YES X-Classification-ID: 240d5612-b03b-11ec-96d4-5254001088d3-1-1 Received: from [216.105.38.7] ([216.105.38.7:37940] helo=lists.sourceforge.net) by smtp26.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 85/B4-18258-C3274426; Wed, 30 Mar 2022 11:07:40 -0400 Received: from [127.0.0.1] (helo=sfs-ml-1.v29.lw.sourceforge.com) by sfs-ml-1.v29.lw.sourceforge.com with esmtp (Exim 4.94.2) (envelope-from ) id 1nZZtw-0001hH-H7; Wed, 30 Mar 2022 15:06:23 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-1.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1nZZtu-0001h0-Og for openvpn-devel@lists.sourceforge.net; Wed, 30 Mar 2022 15:06:21 +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=yI6oG0wzZrl84SjBpb+lORP3lu9wWFU6dQ72GK0OakE=; b=S2Img6vy1rvpppPTUaCA9aa5F5 nvJg+Ce/HcqxXggnrGaMD26KIBoBVtzImpo9r0lhtOMYcy+perRLeLSmPKs5bhDS7K45MoA0jv2tD woA1KsseTs8r1Eo73JPalUN/KmrLgqoOEB9UVeM/IqX63794IXKoykYVHu1GDLsQ0L5s=; 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=yI6oG0wzZrl84SjBpb+lORP3lu9wWFU6dQ72GK0OakE=; b=ZJTbc7ijRCTlGvkPEthMWvG64Q 4OiWUUheAp8orzOYprrFd9BDjQ0UBH9CCv/QQ8jYhdO3rHqegvrlpRXEuSZ5zaLT265kWu5ows34j W126UP4legwX1ez3BB49TTH8rX9OmhdzdPRgfhwBuuGWxOA18dv2k7ICC0NrGts5oZB8=; Received: from btbn.de ([136.243.74.85]) by sfi-mx-2.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.94.2) id 1nZZto-0007SN-VF for openvpn-devel@lists.sourceforge.net; Wed, 30 Mar 2022 15:06:21 +0000 Received: from [authenticated] by btbn.de (Postfix) with ESMTPSA id 8EE8B21DD24; Wed, 30 Mar 2022 17:06:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rothenpieler.org; s=mail; t=1648652769; bh=yI6oG0wzZrl84SjBpb+lORP3lu9wWFU6dQ72GK0OakE=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=oDLg6nIdQxxj44jhCw7RDMSJ6qeZCoaOcBMOzSX42omWQEEiXBLcwnAO5ETIwHF0C FnAyB0f9WzMm09XGwVIeM7Cehjc1Xz9QsHYsz2QLXR1KfKedPzdCQKw0jd4f0RtYZ6 wCQiGx4qvGuGRF/Y9nt1hxZkyTd58bLKHcF1+pcI9aTdglq8+HWzHvxmpcVEyEzobX /J4FD78kKbhkAKUWcy1JYjEp/MvkVHt/FadnYMdUCm0vyDu6BkfRi9bwMQtL1GXFZ2 cEOUxjxNdHAamSd46yhYOmnNbOF3X0Jzobwvku95q4kmhRJLE6ngM2KJkC+H62KRi0 gdmth0KwPtYhg== From: Timo Rothenpieler To: openvpn-devel@lists.sourceforge.net Date: Wed, 30 Mar 2022 17:05:50 +0200 Message-Id: <20220330150550.1489-1-timo@rothenpieler.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <1a4c7f58-16fb-b909-0b40-41f20390179b@sf.lists.topphemmelig.net> References: <1a4c7f58-16fb-b909-0b40-41f20390179b@sf.lists.topphemmelig.net> 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: --- configure.ac | 18 ++++++ distro/systemd/openvpn-client@.service.in | 2 +- distro/systemd/openvpn-server@.service.in | 2 +- src/openvpn/init.c | 25 ++++++- src/openvpn/platform.c | 79 +++++++++++++ [...] Content analysis details: (-0.2 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.0 T_SCC_BODY_TEXT_LINE No description available. X-Headers-End: 1nZZto-0007SN-VF Subject: [Openvpn-devel] [PATCH] Retain CAP_NET_ADMIN when dropping privileges 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox --- configure.ac | 18 ++++++ distro/systemd/openvpn-client@.service.in | 2 +- distro/systemd/openvpn-server@.service.in | 2 +- src/openvpn/init.c | 25 ++++++- src/openvpn/platform.c | 79 +++++++++++++++++++++++ src/openvpn/platform.h | 5 ++ 6 files changed, 127 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 7199483a..5832b62f 100644 --- a/configure.ac +++ b/configure.ac @@ -794,6 +794,24 @@ dnl esac fi +dnl +dnl Depend on libcap-ng on Linux +dnl +case "$host" in + *-*-linux*) + PKG_CHECK_MODULES([LIBCAPNG], + [libcap-ng], + [have_libcapng="yes"], + [AC_MSG_ERROR([libcap-ng package not found. Is the development package and pkg-config installed?])] + ) + + CFLAGS="${CFLAGS} ${LIBCAPNG_CFALGS}" + LIBS="${LIBS} ${LIBCAPNG_LIBS}" + AC_DEFINE(HAVE_LIBCAPNG, 1, [Enable libcap-ng support]) + ;; +esac + + if test "${with_crypto_library}" = "openssl"; then AC_ARG_VAR([OPENSSL_CFLAGS], [C compiler flags for OpenSSL]) AC_ARG_VAR([OPENSSL_LIBS], [linker flags for OpenSSL]) diff --git a/distro/systemd/openvpn-client@.service.in b/distro/systemd/openvpn-client@.service.in index cbcef653..159fb4dc 100644 --- a/distro/systemd/openvpn-client@.service.in +++ b/distro/systemd/openvpn-client@.service.in @@ -11,7 +11,7 @@ Type=notify PrivateTmp=true WorkingDirectory=/etc/openvpn/client ExecStart=@sbindir@/openvpn --suppress-timestamps --nobind --config %i.conf -CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_SYS_CHROOT CAP_DAC_OVERRIDE LimitNPROC=10 DeviceAllow=/dev/null rw DeviceAllow=/dev/net/tun rw diff --git a/distro/systemd/openvpn-server@.service.in b/distro/systemd/openvpn-server@.service.in index d1cc72cb..6e8e7d94 100644 --- a/distro/systemd/openvpn-server@.service.in +++ b/distro/systemd/openvpn-server@.service.in @@ -11,7 +11,7 @@ Type=notify PrivateTmp=true WorkingDirectory=/etc/openvpn/server ExecStart=@sbindir@/openvpn --status %t/openvpn-server/status-%i.log --status-version 2 --suppress-timestamps --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_OVERRIDE CAP_AUDIT_WRITE +CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_SYS_CHROOT CAP_DAC_OVERRIDE CAP_AUDIT_WRITE LimitNPROC=10 DeviceAllow=/dev/null rw DeviceAllow=/dev/net/tun rw diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 8818ba6f..705eb92e 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -1138,6 +1138,25 @@ possibly_become_daemon(const struct options *options) return ret; } +/* + * Determine if we need to retain process capabilities. DCO and SITNL need it. + * Enforce it for DCO, but only try and soft-fail for SITNL to keep backwards compat. + */ +static int +get_need_keep_caps(struct context *c) +{ + if (dco_enabled(&c->options)) + { + return 1; + } + +#ifdef ENABLE_SITNL + return -1; +#else + return 0; +#endif +} + /* * Actually do UID/GID downgrade, chroot and SELinux context switching, if requested. */ @@ -1167,8 +1186,10 @@ do_uid_gid_chroot(struct context *c, bool no_delay) { if (no_delay) { - platform_group_set(&c0->platform_state_group); - platform_user_set(&c0->platform_state_user); + int keep_caps = get_need_keep_caps(c); + platform_user_group_set(&c0->platform_state_user, + &c0->platform_state_group, + keep_caps); } else if (c->first_time) { diff --git a/src/openvpn/platform.c b/src/openvpn/platform.c index 450f28ba..e67844ad 100644 --- a/src/openvpn/platform.c +++ b/src/openvpn/platform.c @@ -43,6 +43,10 @@ #include #endif +#ifdef HAVE_LIBCAPNG +#include +#endif + /* Redefine the top level directory of the filesystem * to restrict access to files for security */ void @@ -155,6 +159,81 @@ platform_group_set(const struct platform_state_group *state) #endif } +void platform_user_group_set(const struct platform_state_user *user_state, + const struct platform_state_group *group_state, + int keep_caps) +{ + unsigned int err_flags = (keep_caps > 0) ? M_FATAL : M_NONFATAL; +#ifdef HAVE_LIBCAPNG + int new_gid = -1, new_uid = -1; + int res; + + if (keep_caps == 0) + { + goto fallback; + } + + /* + * new_uid/new_gid defaults to -1, which will not make + * libcap-ng change the UID/GID unless configured + */ + if (group_state->groupname && group_state->gr) + { + new_gid = group_state->gr->gr_gid; + } + if (user_state->username && user_state->pw) + { + new_uid = user_state->pw->pw_uid; + } + + /* Prepare capabilities before dropping UID/GID */ + capng_clear(CAPNG_SELECT_BOTH); + res = capng_update(CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_NET_ADMIN); + if (res < 0) + { + msg(err_flags, "capng_update(CAP_NET_ADMIN) failed: %d", res); + goto fallback; + } + + /* Change to new UID/GID */ + res = capng_change_id(new_uid, new_gid, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING); + if (res == -4 || res == -6) + { + msg(M_ERR, "capng_change_id('%s','%s') failed: %d", + user_state->username, group_state->groupname, res); + } + else if (res < 0) + { + msg(err_flags | M_ERRNO, "capng_change_id('%s','%s') failed retaining capabilities: %d", + user_state->username, group_state->groupname, res); + goto fallback; + } + + if (new_uid >= 0) + { + msg(M_INFO, "UID set to %s", user_state->username); + } + if (new_gid >= 0) + { + msg(M_INFO, "GID set to %s", group_state->groupname); + } + + msg(M_INFO, "Capabilities retained"); + + return; +fallback: +#endif /* HAVE_LIBCAPNG */ + if (keep_caps) + { + msg(err_flags, "Unable to retain capabilities"); + } + + platform_group_set(group_state); + platform_user_set(user_state); +} + + + /* Change process priority */ void platform_nice(int niceval) diff --git a/src/openvpn/platform.h b/src/openvpn/platform.h index a3eec298..b163f093 100644 --- a/src/openvpn/platform.h +++ b/src/openvpn/platform.h @@ -85,6 +85,11 @@ bool platform_group_get(const char *groupname, struct platform_state_group *stat void platform_group_set(const struct platform_state_group *state); +void platform_user_group_set(const struct platform_state_user *user_state, + const struct platform_state_group *group_state, + int keep_caps); + + /* * Extract UID or GID */