Blob Blame History Raw
From a7efa0ed8b28de55ef0fa2b39fefc3753ce1db8a Mon Sep 17 00:00:00 2001
From: Jeffrey C. Ollie <jcollie@pc21224.campus.dmacc.edu>
Date: Thu, 8 Nov 2007 16:42:56 -0600
Subject: [PATCH] Backport patch that lets Asterisk set the TOS byte even when running as non-root.

---
 CHANGES          |    5 +++++
 configure.ac     |    5 +++++
 doc/security.txt |    7 +++++++
 main/Makefile    |    3 +++
 main/asterisk.c  |   30 +++++++++++++++++++++++++-----
 makeopts.in      |    3 +++
 6 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/CHANGES b/CHANGES
index faa1855..7825d58 100644
--- a/CHANGES
+++ b/CHANGES
@@ -339,3 +339,8 @@ Changes since Asterisk 1.2:
          1. aelparse -- compile .ael files outside of asterisk
     * New manager events:
          1. OriginateResponse event comes to replace OriginateSuccess and OriginateFailure
+
+    * Ability to use libcap to set high ToS bits when non-root on
+      Linux. If configure is unable to find libcap then you can use
+      --with-cap to specify the path.
+
diff --git a/configure.ac b/configure.ac
index 1488a1e..17ecb3d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -169,6 +169,7 @@ AC_SUBST(AST_DEVMODE)
 
 AST_EXT_LIB_SETUP([ALSA], [Advanced Linux Sound Architecture], [asound])
 AST_EXT_LIB_SETUP([CURL], [cURL], [curl])
+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'])
@@ -395,6 +396,10 @@ AST_EXT_LIB_CHECK([ALSA], [asound], [snd_spcm_init], [alsa/asoundlib.h], [-lm -l
 
 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"
diff --git a/doc/security.txt b/doc/security.txt
index 0801679..3adf536 100644
--- a/doc/security.txt
+++ b/doc/security.txt
@@ -28,6 +28,13 @@ The IAX2 protocol supports strong RSA key authentication as well as
 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:
diff --git a/main/Makefile b/main/Makefile
index 4f405b5..cee9e13 100644
--- a/main/Makefile
+++ b/main/Makefile
@@ -55,6 +55,9 @@ ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc ),)
   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
diff --git a/main/asterisk.c b/main/asterisk.c
index 202a190..bd8cd9b 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -82,13 +82,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <sys/stat.h>
 #ifdef linux
 #include <sys/prctl.h>
-#endif
+#ifdef HAVE_CAP
+#include <sys/capability.h>
+#endif /* HAVE_CAP */
+#endif /* linux */
 #include <regex.h>
 
-#ifdef linux
-#include <sys/prctl.h>
-#endif
-
 #if  defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS)
 #include <netdb.h>
 #if defined(SOLARIS)
@@ -2734,6 +2733,10 @@ int main(int argc, char *argv[])
 	}
 
 	if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
+#ifdef HAVE_CAP
+		cap_t cap;
+		int has_cap = 1;
+#endif /* HAVE_CAP */
 		struct passwd *pw;
 		pw = getpwnam(runuser);
 		if (!pw) {
@@ -2744,6 +2747,12 @@ int main(int argc, char *argv[])
 			ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\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);
@@ -2760,6 +2769,17 @@ int main(int argc, char *argv[])
 		}
 		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");
+			}
+			if (cap_free(cap)) {
+				ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
+			}
+		}
+#endif /* HAVE_CAP */
 	}
 
 #endif /* __CYGWIN__ */
diff --git a/makeopts.in b/makeopts.in
index 8138dd8..a81503c 100644
--- a/makeopts.in
+++ b/makeopts.in
@@ -189,3 +189,6 @@ TERMCAP_DIR=@TERMCAP_DIR@
 TINFO_INCLUDE=@TINFO_INCLUDE@
 TINFO_LIB=@TINFO_LIB@
 TINFO_DIR=@TINFO_DIR@
+
+CAP_LIB=@CAP_LIB@
+CAP_INCLUDE=@CAP_INCLUDE@
-- 
1.5.3.6