From: Timo Rothenpieler Date: Wed, 17 Aug 2022 13:18:17 +0000 (+0200) Subject: dco: disable DCO if --user specified but unable to retain capabilities X-Git-Tag: v2.6_beta1~112 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da31c1654c8534658157cfe9c9de5750ee752608;p=thirdparty%2Fopenvpn.git dco: disable DCO if --user specified but unable to retain capabilities If run under network manager, OpenVPN starts with uid=0 and '--user nm-openvpn', but is lacking the CAP_SETPCAP capabilities to retain CAP_NET_ADMIN after dropping root privileges. In DCO mode, OpenVPN must have CAP_NET_ADMIN today, always, otherwise TLS renegotiation / key rotation will not be possible. So, check at startup, if --user is specified, if CAP_NET_ADMIN is permitted and CAP_SETPCAP is available. If either of the capabilities is missing, disable DCO. Traditional tun/tap works with "uid=0 on tun open, and setuid() afterwards". Long-Term, get NM to enable OpenVPN to run with CAP_NET_ADMIN. Debian bug report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1017379 Signed-off-by: Timo Rothenpieler Tested-By: Bernhard Schmidt Acked-by: Gert Doering Message-Id: <20220817131817.467-1-timo@rothenpieler.org> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg24952.html Signed-off-by: Gert Doering --- diff --git a/src/openvpn/dco.c b/src/openvpn/dco.c index caa4ce324..b7db23f45 100644 --- a/src/openvpn/dco.c +++ b/src/openvpn/dco.c @@ -44,6 +44,10 @@ #include "ssl_ncp.h" #include "tun.h" +#ifdef HAVE_LIBCAPNG +#include +#endif + static int dco_install_key(struct tls_multi *multi, struct key_state *ks, const uint8_t *encrypt_key, const uint8_t *encrypt_iv, @@ -247,6 +251,28 @@ dco_check_option_conflict_platform(int msglevel, const struct options *o) } } #endif /* if defined(TARGET_LINUX) */ + +#if defined(HAVE_LIBCAPNG) + /* DCO can't operate without CAP_NET_ADMIN. To retain it when switching user + * we need CAP_SETPCAP. CAP_NET_ADMIN also needs to be part of the permitted set + * of capabilities in order to retain it. + */ + if (o->username) + { + if (!capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) + { + msg(msglevel, "--user specified but lacking CAP_SETPCAP. " + "Cannot retain CAP_NET_ADMIN. Disabling data channel offload"); + return false; + } + if (!capng_have_capability(CAPNG_PERMITTED, CAP_NET_ADMIN)) + { + msg(msglevel, "--user specified but not permitted to retain CAP_NET_ADMIN. " + "Disabling data channel offload"); + return false; + } + } +#endif /* if defined(HAVE_LIBCAPNG) */ return true; }