use libcap for capability dropping
authorMartin Willi <martin@strongswan.org>
Fri, 29 Aug 2008 09:24:14 +0000 (09:24 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 29 Aug 2008 09:24:14 +0000 (09:24 -0000)
optional, must be enabled --with-capabilities=libcap
will be extended to support --with-capabilities=libcap2

configure.in
scripts/cfg-leak
src/charon/Makefile.am
src/charon/daemon.c
src/charon/plugins/eap_gtc/eap_gtc_plugin.c
src/pluto/Makefile.am
src/pluto/plutomain.c

index 289e627..c3dd728 100644 (file)
@@ -138,6 +138,14 @@ AC_ARG_WITH(
        [AC_SUBST(ipsecgroup, "root")]
 )
 
+dnl Will be extended to --with-capabilities=libcap|libcap2
+AC_ARG_WITH(
+       [capabilities],
+       AS_HELP_STRING([--with-capabilities=libcap],[capability dropping using libcap. Currenlty only the value "libcap" is supported (default is NO).]),
+       [capabilities="$withval"],
+       [capabilities=no]
+)
+
 AC_ARG_ENABLE(
        [curl],
        AS_HELP_STRING([--enable-curl],[enable CURL fetcher plugin to fetch files via libcurl (default is NO). Requires libcurl.]),
@@ -628,15 +636,6 @@ AC_HAVE_LIBRARY(dl)
 AC_CHECK_FUNCS(backtrace)
 AC_CHECK_FUNCS(dladdr)
 
-AC_MSG_CHECKING([capset() definition])
-AC_TRY_COMPILE(
-       [#include <linux/capset.h>],
-       [
-               void *test = capset;
-       ], 
-       [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); AC_DEFINE_UNQUOTED(NO_CAPSET_DEFINED, 1)]
-)
-
 if test x$gmp = xtrue; then
        AC_HAVE_LIBRARY([gmp],[LIBS="$LIBS"],[AC_MSG_ERROR([GNU Multi Precision library gmp not found])])
        AC_MSG_CHECKING([gmp.h version >= 4.1.4])
@@ -732,6 +731,11 @@ if test x$eap_gtc = xtrue; then
        AC_CHECK_HEADER([security/pam_appl.h],,[AC_MSG_ERROR([PAM header security/pam_appl.h not found!])])
 fi
 
+if test x$capabilities = xlibcap; then
+       AC_HAVE_LIBRARY([cap],[LIBS="$LIBS"],[AC_MSG_ERROR([libcap library not found])])
+       AC_CHECK_HEADER([sys/capability.h],,[AC_MSG_ERROR([libcap header sys/capability.h not found!])])
+fi
+
 dnl ======================================
 dnl  collect all plugins for libstrongswan
 dnl ======================================
@@ -850,6 +854,7 @@ AM_CONDITIONAL(USE_MANAGER, test x$manager = xtrue)
 AM_CONDITIONAL(USE_ME, test x$me = xtrue)
 AM_CONDITIONAL(USE_INTEGRITY_TEST, test x$integrity_test = xtrue)
 AM_CONDITIONAL(USE_SELF_TEST, test x$self_test = xtrue)
+AM_CONDITIONAL(USE_CAPABILITIES, test x$capabilities = xlibcap)
 AM_CONDITIONAL(USE_PLUTO, test x$pluto = xtrue)
 AM_CONDITIONAL(USE_CHARON, test x$charon = xtrue)
 AM_CONDITIONAL(USE_TOOLS, test x$tools = xtrue)
@@ -864,6 +869,9 @@ dnl ==============================
 if test x$me = xtrue; then
        AC_DEFINE(ME)
 fi
+if test x$capabilities = xlibcap; then
+       AC_DEFINE(CAPABILITIES)
+fi
 
 dnl ==============================
 dnl  build Makefiles
index 4ec425e..8ccf1d6 100755 (executable)
@@ -1,4 +1,4 @@
 #!/bin/bash
 CFLAGS="-Wall -Wno-format -Wno-pointer-sign -Wno-strict-aliasing -g -O2" ./configure \
---sysconfdir=/etc --disable-tools --disable-pluto --enable-leak-detective --enable-dumm \
+--sysconfdir=/etc --disable-tools --disable-pluto --enable-leak-detective --enable-dumm --with-capabilities=libcap \
 $1 $2 $3 $4 $5
index 82f521f..c7fb7ff 100644 (file)
@@ -129,6 +129,11 @@ if USE_SELF_TEST
   AM_CFLAGS += -DSELF_TEST
 endif
 
+if USE_CAPABILITIES
+  charon_LDADD += -lcap
+endif
+
+
 # build optional plugins
 ########################
 
index 3d2ad77..127a158 100644 (file)
@@ -22,7 +22,6 @@
 #endif /* HAVE_DLADDR */
 
 #include <stdio.h>
-#include <linux/capability.h>
 #include <sys/prctl.h>
 #include <signal.h>
 #include <pthread.h>
@@ -38,6 +37,9 @@
 #ifdef HAVE_BACKTRACE
 # include <execinfo.h>
 #endif /* HAVE_BACKTRACE */
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif /* CAPABILITIES */
 
 #include "daemon.h"
 
 #include <config/traffic_selector.h>
 #include <config/proposal.h>
 
-/* on some distros, a capset definition is missing */
-#ifdef NO_CAPSET_DEFINED
-extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-#endif /* NO_CAPSET_DEFINED */
-
-/* missing on older kernel headers */
-#ifndef CAP_AUDIT_WRITE
-#define CAP_AUDIT_WRITE 29
-#endif /* CAP_AUDIT_WRITE */
-
 #ifdef INTEGRITY_TEST
 #include <fips/fips.h>
 #include <fips/fips_signature.h>
@@ -80,11 +72,13 @@ struct private_daemon_t {
         * The thread_id of main-thread.
         */
        pthread_t main_thread_id;
-       
+
+#ifdef CAPABILITIES
        /**
         * capabilities to keep
         */
-       u_int32_t keep;
+       cap_t caps;
+#endif /* CAPABILITIES */
 };
 
 /**
@@ -193,6 +187,9 @@ static void destroy(private_daemon_t *this)
        }
        /* unload plugins to release threads */
        lib->plugins->unload(lib->plugins);
+#ifdef CAPABILITIES
+       cap_free(this->caps);
+#endif /* CAPABILITIES */
        DESTROY_IF(this->public.ike_sa_manager);
        DESTROY_IF(this->public.kernel_interface);
        DESTROY_IF(this->public.scheduler);
@@ -253,10 +250,7 @@ static void kill_daemon(private_daemon_t *this, char *reason)
  * drop daemon capabilities
  */
 static void drop_capabilities(private_daemon_t *this)
-{
-       struct __user_cap_header_struct hdr;
-       struct __user_cap_data_struct data;
-       
+{      
        prctl(PR_SET_KEEPCAPS, 1);
 
        if (setgid(charon->gid) != 0)
@@ -267,21 +261,13 @@ static void drop_capabilities(private_daemon_t *this)
        {
                kill_daemon(this, "change to unprivileged user failed");        
        }
-
-       /* we use the old capset version for now. For systems with version 2
-        * available, we specifiy version 1 excplicitly. */
-#ifdef _LINUX_CAPABILITY_VERSION_1
-       hdr.version = _LINUX_CAPABILITY_VERSION_1;
-#else
-       hdr.version = _LINUX_CAPABILITY_VERSION;
-#endif
-       hdr.pid = 0;
-       data.inheritable = data.effective = data.permitted = this->keep;
        
-       if (capset(&hdr, &data))
+#ifdef CAPABILITIES
+       if (cap_set_proc(this->caps) != 0)
        {
                kill_daemon(this, "unable to drop daemon capabilities");
        }
+#endif /* CAPABILITIES */
 }
 
 /**
@@ -289,7 +275,11 @@ static void drop_capabilities(private_daemon_t *this)
  */
 static void keep_cap(private_daemon_t *this, u_int cap)
 {
-       this->keep |= 1 << cap;
+#ifdef CAPABILITIES
+       cap_set_flag(this->caps, CAP_EFFECTIVE, 1, &cap, CAP_SET);
+       cap_set_flag(this->caps, CAP_INHERITABLE, 1, &cap, CAP_SET);
+       cap_set_flag(this->caps, CAP_PERMITTED, 1, &cap, CAP_SET);
+#endif /* CAPABILITIES */
 }
 
 /**
@@ -498,11 +488,14 @@ private_daemon_t *daemon_create(void)
        this->public.gid = 0;
        
        this->main_thread_id = pthread_self();
-       this->keep = 1<<CAP_NET_ADMIN;
+#ifdef CAPABILITIES
+       this->caps = cap_init();
+       keep_cap(this, CAP_NET_ADMIN);
        if (lib->leak_detective)
        {
-               this->keep = 1<<CAP_SYS_NICE;
+               keep_cap(this, CAP_SYS_NICE);
        }
+#endif /* CAPABILITIES */
        
        /* add handler for SEGV and ILL,
         * add handler for USR1 (cancellation).
index 0407edc..cea88ef 100644 (file)
@@ -21,7 +21,8 @@
 
 #include <daemon.h>
 
-#include <linux/capability.h>
+/* missing in cababilities.h */
+#define CAP_AUDIT_WRITE 29
 
 /**
  * Implementation of plugin_t.destroy
index 156b810..c28fbf6 100644 (file)
@@ -139,3 +139,7 @@ if USE_SMARTCARD
   AM_CFLAGS += -DSMARTCARD
 endif
 
+if USE_CAPABILITIES
+  pluto_LDADD += -lcap
+endif
+
index f1b3163..b7bb8df 100644 (file)
 #include <resolv.h>
 #include <arpa/nameser.h>      /* missing from <resolv.h> on old systems */
 #include <sys/queue.h>
-#include <linux/capability.h>
 #include <sys/prctl.h>
 #include <pwd.h>
 #include <grp.h>
 
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif /* CAPABILITIES */
+
 #include <freeswan.h>
 
 #include <pfkeyv2.h>
 #include "nat_traversal.h"
 #include "virtual.h"
 
-/* on some distros, a capset() definition is missing */
-#ifdef NO_CAPSET_DEFINED
-extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-#endif /* NO_CAPSET_DEFINED */
-
 static void
 usage(const char *mess)
 {
@@ -236,8 +234,10 @@ main(int argc, char **argv)
     bool force_keepalive = FALSE;
     char *virtual_private = NULL;
     int lockfd;
-    struct __user_cap_header_struct hdr;
-    struct __user_cap_data_struct data;
+#ifdef CAPABILITIES
+    cap_t caps;
+    int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
+#endif /* CAPABILITIES */
 
     /* handle arguments */
     for (;;)
@@ -619,14 +619,6 @@ main(int argc, char **argv)
     init_fetch();
 
     /* drop unneeded capabilities and change UID/GID */
-#ifdef _LINUX_CAPABILITY_VERSION_1
-    hdr.version = _LINUX_CAPABILITY_VERSION_1;
-#else
-    hdr.version = _LINUX_CAPABILITY_VERSION;
-#endif
-    hdr.pid = 0;
-    data.inheritable = data.effective = data.permitted = 
-                               1<<CAP_NET_ADMIN | 1<<CAP_NET_BIND_SERVICE;
 
     prctl(PR_SET_KEEPCAPS, 1);
        
@@ -656,11 +648,19 @@ main(int argc, char **argv)
        }
        }
 #endif
-    if (capset(&hdr, &data))
+
+#ifdef CAPABILITIES
+    caps = cap_init();
+    cap_set_flag(caps, CAP_EFFECTIVE, 2, keep, CAP_SET);
+    cap_set_flag(caps, CAP_INHERITABLE, 2, keep, CAP_SET);
+    cap_set_flag(caps, CAP_PERMITTED, 2, keep, CAP_SET);
+    if (cap_set_proc(caps) != 0)
     {
-       plog("unable to drop root privileges");
+       plog("unable to drop daemon capabilities");
        abort();
     }
+    cap_free(caps);
+#endif /* CAPABILITIES */
 
     /* loading X.509 CA certificates */
     load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);