From 494dabeab4779496dbf8c5e95d6e566b6017af36 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 28 Jan 2020 20:31:46 +0300 Subject: [PATCH] pppd: Introduce net_capable option to unroot pppd for Linux 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 | 10 +++++++++- pppd/main.c | 7 +++---- pppd/pppd.h | 1 + pppd/sys-linux.c | 41 +++++++++++++++++++++++++++++++++++++++++ pppd/sys-solaris.c | 14 ++++++++++++++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux index 9664f7098..789bb3c8a 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 @@ -127,7 +130,12 @@ endif ifneq ($(wildcard $(shell $(CC) --print-sysroot)/usr/include/crypt.h),) CFLAGS += -DHAVE_CRYPT_H=1 -LIBS += -lcrypt +LIBS += -lcrypt +endif + +ifdef USE_LIBCAP +CFLAGS += -DUSE_CAP +LIBS += -lcap endif ifdef USE_LIBUTIL diff --git a/pppd/main.c b/pppd/main.c index 652240cc6..ec7471d95 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 be net capable to run the %s", argv[0]); exit(EXIT_NOT_ROOT); } diff --git a/pppd/pppd.h b/pppd/pppd.h index b31b78da7..80f1ca41d 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -623,6 +623,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 a0531e9d3..e1fb87e94 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 0b993a501..4a30e5e2c 100644 --- a/pppd/sys-solaris.c +++ b/pppd/sys-solaris.c @@ -903,6 +903,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 */