From d29473ff4432822f8784d3b2142507ce7a2e8b55 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 26a5735..cd4e87b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -174,6 +174,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'])
@@ -400,6 +401,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.7