Index: configure.ac =================================================================== --- configure.ac (revision 33615) +++ configure.ac (working copy) @@ -254,6 +254,10 @@ AST_EXT_LIB([tonezone], [tone_zone_find], [zaptel.h], [ZAPTEL], [Zaptel], [-lm]) fi +if test "x${PBX_OSTYPE}" = "xLinux" ; then + AST_EXT_LIB([cap], [cap_from_text], [sys/capability.h], [POSIX1E], [Linux POSIX.1e Capabilities]) +fi + GSM_INTERNAL="yes" GSM_SYSTEM="yes" AC_ARG_WITH([gsm], AC_HELP_STRING([--with-gsm=PATH], [use libgsm files in PATH, or 'internal']), [ Index: doc/security.txt =================================================================== --- doc/security.txt (revision 33615) +++ 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: Makefile =================================================================== --- Makefile (revision 33615) +++ Makefile (working copy) @@ -311,6 +311,9 @@ ifeq ($(OSARCH),Linux) LIBS+=-ldl -lpthread $(EDITLINE_LIBS) -lm -lresolv #-lnjamd + ifneq (x$(CAP_LIB),x) + LIBS+=$(CAP_LIB) + endif else LIBS+=$(EDITLINE_LIBS) -lm endif Index: makeopts.in =================================================================== --- makeopts.in (revision 33615) +++ makeopts.in (working copy) @@ -123,3 +123,6 @@ RADIUSCLIENT_LIB=@RADIUSCLIENT_LIB@ RADIUSCLIENT_INCLUDE=@RADIUSCLIENT_INCLUDE@ + +CAP_LIB=@POSIX1E_LIB@ +CAP_INCLUDE=@POSIX1E_INCLUDE@ Index: asterisk.c =================================================================== --- asterisk.c (revision 33615) +++ asterisk.c (working copy) @@ -80,13 +80,12 @@ #include #ifdef linux #include -#endif +#ifdef HAVE_POSIX1E +#include +#endif /* HAVE_POSIX1E */ +#endif /* linux */ #include -#ifdef linux -#include -#endif - #if defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS) #include #if defined(SOLARIS) @@ -2502,12 +2501,22 @@ } if (!is_child_of_nonroot && runuser) { +#if (defined(linux) && defined(HAVE_POSIX1E)) + cap_t cap; + int has_cap = 1; +#endif /* HAVE_POSIX1E */ struct passwd *pw; pw = getpwnam(runuser); if (!pw) { ast_log(LOG_WARNING, "No such user '%s'!\n", runuser); exit(1); } +#if (defined(linux) && defined(HAVE_POSIX1E)) + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { + ast_log(LOG_WARNING, "Unable to keep capabilities.\n"); + has_cap = 0; + } +#endif /* HAVE_POSIX1E */ if (!rungroup) { if (setgid(pw->pw_gid)) { ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid); @@ -2525,6 +2534,20 @@ setenv("ASTERISK_ALREADY_NONROOT", "yes", 1); if (option_verbose) ast_verbose("Running as user '%s'\n", runuser); +#if (defined(linux) && defined(HAVE_POSIX1E)) + do { + 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"); + } + } + } while (0); +#endif /* HAVE_POSIX1E */ } #endif /* __CYGWIN__ */