]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
dco: disable DCO if --user specified but unable to retain capabilities
authorTimo Rothenpieler <timo@rothenpieler.org>
Wed, 17 Aug 2022 13:18:17 +0000 (15:18 +0200)
committerGert Doering <gert@greenie.muc.de>
Wed, 17 Aug 2022 14:08:07 +0000 (16:08 +0200)
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 <timo@rothenpieler.org>
Tested-By: Bernhard Schmidt <berni@birkenwald.de>
Acked-by: Gert Doering <gert@greenie.muc.de>
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 <gert@greenie.muc.de>
src/openvpn/dco.c

index caa4ce324083bf126521f267af554841aa2bfd56..b7db23f4571f8c09144381e5fd9f84635021fa49 100644 (file)
 #include "ssl_ncp.h"
 #include "tun.h"
 
+#ifdef HAVE_LIBCAPNG
+#include <cap-ng.h>
+#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;
 }