diff --git a/pppd/Makefile.linux b/pppd/Makefile.linux index 22837c504..4860e1f37 100644 --- a/pppd/Makefile.linux +++ b/pppd/Makefile.linux @@ -79,6 +79,9 @@ PLUGIN=y # Enable EAP SRP-SHA1 authentication (requires libsrp) #USE_SRP=y +# Use libcap (requires libcap) +#USE_LIBCAP=y + # Use libutil; test if logwtmp is declared in to detect ifeq ($(shell echo '\#include ' | $(CC) -E - 2>/dev/null | grep -q logwtmp && echo yes),yes) USE_LIBUTIL=y @@ -148,6 +151,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 87a5d2921..0f9969b3a 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -360,11 +360,14 @@ main(int argc, char *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()) { + #ifdef USE_CAP + option_error("must have CAP_NET_RAW or root privilege to run %s", argv[0]); + #else + option_error("must be root to run %s, since it is not setuid-root", argv[0]); + #endif /* USE_CAP */ exit(EXIT_NOT_ROOT); } diff --git a/pppd/pppd.h b/pppd/pppd.h index 612902f55..1c75771f3 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -622,6 +622,7 @@ void sys_init(void); /* Do system-dependent initialization */ void sys_cleanup(void); /* Restore system state before exiting */ int sys_check_options(void); /* Check options specified */ void sys_close(void); /* Clean up in a child before execing */ +int net_capable(void); /* Test for any access to the net management */ int ppp_available(void); /* Test whether ppp kernel support exists */ int get_pty(int *, int *, char *, int); /* Get pty master/slave */ int open_ppp_loopback(void); /* Open loopback for demand-dialling */ diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index b7972b908..d13d7d6df 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 /* @@ -2329,6 +2334,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 e0cd0be32..171a4a97d 100644 --- a/pppd/sys-solaris.c +++ b/pppd/sys-solaris.c @@ -852,6 +852,20 @@ daemon(int nochdir, int 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 */