From 722f3263b6dbcf8ded9f295cbae0857f1664c36a Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 28 Jan 2020 20:31:46 +0300 Subject: [PATCH] pppd: Check CAP_NET_RAW capability on Linux rather than requiring euid 0 Introduce USE_LIBCAP option turned on by default for the linux build. Provide an option to check that we are capable to admin the network wihout root via CAP_NET_RAW libcap option. Requires libcap library. Fallback to geteuid method in case of Solaris and Linux without libcap. Signed-off-by: Alexey Andreev --- pppd/Makefile.linux | 8 ++++++++ pppd/main.c | 7 +++---- pppd/pppd.h | 1 + pppd/sys-linux.c | 41 +++++++++++++++++++++++++++++++++++++++++ pppd/sys-solaris.c | 14 ++++++++++++++ 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux index 44d47ad7f..48363bc95 100644 --- a/pppd/Makefile.linux +++ b/pppd/Makefile.linux @@ -78,6 +78,9 @@ PLUGIN=y # Enable EAP SRP-SHA1 authentication (requires libsrp) #USE_SRP=y +# Use libcap (requires libcap) +USE_LIBCAP=y + # Use libutil USE_LIBUTIL=y @@ -145,6 +148,11 @@ CFLAGS += -DHAVE_CRYPT_H=1 LIBS += -lcrypt endif +ifdef USE_LIBCAP +CFLAGS += -DUSE_CAP +LIBS += -lcap +endif + ifdef USE_LIBUTIL CFLAGS += -DHAVE_LOGWTMP=1 LIBS += -lutil diff --git a/pppd/main.c b/pppd/main.c index c18ea5105..486f26328 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -370,11 +370,10 @@ main(argc, argv) setlogmask(LOG_UPTO(LOG_DEBUG)); /* - * Check that we are running as root. + * Check that we are capable to admin the network. */ - if (geteuid() != 0) { - option_error("must be root to run %s, since it is not setuid-root", - argv[0]); + if (!net_capable()) { + option_error("must have CAP_NET_RAW or root privilege to run %s", argv[0]); exit(EXIT_NOT_ROOT); } diff --git a/pppd/pppd.h b/pppd/pppd.h index a35deaa8e..69b1fa4a1 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -630,6 +630,7 @@ void sys_init __P((void)); /* Do system-dependent initialization */ void sys_cleanup __P((void)); /* Restore system state before exiting */ int sys_check_options __P((void)); /* Check options specified */ void sys_close __P((void)); /* Clean up in a child before execing */ +int net_capable __P((void)); /* Test for any access to the net management */ int ppp_available __P((void)); /* Test whether ppp kernel support exists */ int get_pty __P((int *, int *, char *, int)); /* Get pty master/slave */ int open_ppp_loopback __P((void)); /* Open loopback for demand-dialling */ diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index f38210a47..84534fe45 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -144,6 +144,11 @@ #include #endif +#ifdef USE_CAP +#include +#include +#endif /* USE_CAP */ + #ifdef INET6 #ifndef _LINUX_IN6_H /* @@ -2242,6 +2247,42 @@ ppp_registered(void) return ret; } +/*********************************************************** + * + * net_capable - check for any access to the net management + */ + +int net_capable(void) +{ + int ok = 0; +#ifdef USE_CAP + /* + * Check that we are capable to admin the network. + */ + cap_t cap; + cap_flag_value_t cap_flag_value; + cap = cap_get_pid(getpid()); + if (cap != 0) { + if (cap_get_flag(cap, CAP_NET_RAW, CAP_EFFECTIVE, &cap_flag_value) == 0) { + if (cap_flag_value == CAP_SET) + ok = 1; + } + if (cap_get_flag(cap, CAP_NET_RAW, CAP_PERMITTED, &cap_flag_value) == 0) { + if (cap_flag_value == CAP_SET) + ok = 1; + } + } +#else /* USE_CAP */ + /* + * Check that we are running as root. + */ + if (geteuid() == 0) { + ok = 1; + } +#endif /* USE_CAP */ + return ok; +} + /******************************************************************** * * ppp_available - check whether the system has any ppp interfaces diff --git a/pppd/sys-solaris.c b/pppd/sys-solaris.c index 113eb7bdf..262a70ac2 100644 --- a/pppd/sys-solaris.c +++ b/pppd/sys-solaris.c @@ -904,6 +904,20 @@ daemon(nochdir, noclose) } #endif +/*********************************************************** + * + * net_capable - check for any access to the net management + */ + +int net_capable(void) +{ + int ok = 0; + if (geteuid() == 0) { + ok = 1; + } + return ok; +} + /* * ppp_available - check whether the system has any ppp interfaces */