Index: configure.ac =================================================================== --- configure.ac (revision 42015) +++ configure.ac (working copy) @@ -154,6 +154,7 @@ # by the --with option name, to make things easier for the users :-) AST_EXT_LIB_SETUP([ALSA], [Advanced Linux Sound Architecture], [asound]) +AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capabilities], [cap]) AST_EXT_LIB_SETUP([CURSES], [curses], [curses]) AST_EXT_LIB_SETUP([GNUTLS], [GNU TLS support (used for iksemel only)], [gnutls]) AST_EXT_LIB_SETUP([GSM], [GSM], [gsm], [, or 'internal']) @@ -307,6 +308,10 @@ AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h]) +if test "x${host_os}" = "xlinux-gnu" ; then + AST_EXT_LIB_CHECK([CAP], [cap], [cap_from_text], [sys/capability.h]) +fi + GSM_INTERNAL="yes" AC_SUBST(GSM_INTERNAL) GSM_SYSTEM="yes" Index: doc/security.txt =================================================================== --- doc/security.txt (revision 42015) +++ doc/security.txt (working copy) @@ -28,6 +28,13 @@ AES encryption of voice and signalling. The SIP channel does not support encryption in this version of Asterisk. +By default, if you have libcap available, Asterisk will try to retain the +CAP_NET_ADMIN capability when running as a non-root user. If you do not need +that capability you may want to configure Asterisk with --without-cap; however, +this will prevent Asterisk from being able to mark high ToS bits under Linux. +More information on CAP_NET_ADMIN is available at: +http://www.lids.org/lids-howto/node48.html + * DIALPLAN SECURITY First and foremost remember this: Index: main/Makefile =================================================================== --- main/Makefile (revision 42015) +++ main/Makefile (working copy) @@ -48,6 +48,9 @@ ifneq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),) AST_LIBS+=-ldl endif + ifneq (x$(CAP_LIB),x) + AST_LIBS+=$(CAP_LIB) + endif AST_LIBS+=-lpthread $(EDITLINE_LIB) -lm -lresolv else AST_LIBS+=$(EDITLINE_LIB) -lm Index: main/asterisk.c =================================================================== --- main/asterisk.c (revision 42015) +++ main/asterisk.c (working copy) @@ -80,13 +80,12 @@ #include #ifdef linux #include -#endif +#ifdef HAVE_CAP +#include +#endif /* HAVE_CAP */ +#endif /* linux */ #include -#ifdef linux -#include -#endif - #if defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS) #include #if defined(SOLARIS) @@ -2489,12 +2488,22 @@ } if (!is_child_of_nonroot && runuser) { +#ifdef HAVE_CAP + cap_t cap; + int has_cap = 1; +#endif /* HAVE_CAP */ struct passwd *pw; pw = getpwnam(runuser); if (!pw) { ast_log(LOG_WARNING, "No such user '%s'!\n", runuser); exit(1); } +#ifdef HAVE_CAP + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { + ast_log(LOG_WARNING, "Unable to keep capabilities.\n"); + has_cap = 0; + } +#endif /* HAVE_CAP */ if (!rungroup) { if (setgid(pw->pw_gid)) { ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid); @@ -2512,6 +2521,18 @@ setenv("ASTERISK_ALREADY_NONROOT", "yes", 1); if (option_verbose) ast_verbose("Running as user '%s'\n", runuser); +#ifdef HAVE_CAP + if (has_cap) { + cap = cap_from_text("cap_net_admin=ep"); + if (cap_set_proc(cap)) { + ast_log(LOG_WARNING, "Unable to install capabilities.\n"); + break; + } + if (cap_free(cap)) { + ast_log(LOG_WARNING, "Unable to drop capabilities.\n"); + } + } +#endif /* HAVE_CAP */ } #endif /* __CYGWIN__ */ Index: makeopts.in =================================================================== --- makeopts.in (revision 42015) +++ makeopts.in (working copy) @@ -156,3 +156,6 @@ SUPPSERV_INCLUDE=@SUPPSERV_INCLUDE@ SUPPSERV_LIB=@SUPPSERV_LIB@ + +CAP_LIB=@CAP_LIB@ +CAP_INCLUDE=@CAP_INCLUDE@