Adding support for the native Linux capabilities interface.
authorTobias Brunner <tobias@strongswan.org>
Tue, 15 Jun 2010 17:40:44 +0000 (19:40 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 15 Jun 2010 17:58:30 +0000 (19:58 +0200)
Note that this interface is deprecated and mainly added to support
Android. Use libcap, if possible.

Android.mk.in
configure.in
src/libcharon/daemon.c
src/pluto/plutomain.c

index 6277861..a5cc7df 100644 (file)
@@ -42,6 +42,8 @@ strongswan_CFLAGS := \
        -DHAVE_STRUCT_SADB_X_POLICY_SADB_X_POLICY_PRIORITY \
        -DHAVE_IPSEC_MODE_BEET \
        -DHAVE_IPSEC_DIR_FWD \
+       -DCAPABILITIES \
+       -DCAPABILITIES_NATIVE \
        -DMONOLITHIC \
        -DUSE_VSTR \
        -DROUTING_TABLE=0 \
index 7589c30..2804650 100644 (file)
@@ -40,7 +40,7 @@ ARG_WITH_SUBST([linux-headers],      [\${top_srcdir}/src/include], [set director
 ARG_WITH_SUBST([routing-table],      [220], [set routing table to use for IPsec routes])
 ARG_WITH_SUBST([routing-table-prio], [220], [set priority for IPsec routing table])
 
-ARG_WITH_SET([capabilities],         [no], [set capability dropping library. Currently only the value "libcap" is supported])
+ARG_WITH_SET([capabilities],         [no], [set capability dropping library. Currently supported values are "libcap" and "native"])
 ARG_WITH_SET([mpz_powm_sec],         [yes], [use the more side-channel resistant mpz_powm_sec in libgmp, if available])
 
 AC_ARG_WITH(
@@ -613,9 +613,21 @@ 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 = xnative; then
+       AC_MSG_NOTICE([Usage of the native Linux capabilities interface is deprecated, use libcap instead])
+       dnl Linux requires the following for capset(), Android does not have it,
+       dnl but defines capset() in unistd.h instead.
+       AC_CHECK_HEADERS([sys/capability.h])
+       AC_CHECK_FUNC(capset,,[AC_MSG_ERROR([capset() not found!])])
+       AC_DEFINE(CAPABILITIES_NATIVE)
+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!])])
+       AC_CHECK_HEADER([sys/capability.h],
+               [AC_DEFINE(HAVE_SYS_CAPABILITY_H)],
+               [AC_MSG_ERROR([libcap header sys/capability.h not found!])])
+       AC_DEFINE(CAPABILITIES_LIBCAP)
 fi
 
 if test x$integrity_test = xtrue; then
@@ -879,7 +891,7 @@ dnl ==============================
 if test x$mediation = xtrue; then
        AC_DEFINE(ME)
 fi
-if test x$capabilities = xlibcap; then
+if test x$capabilities = xlibcap -o x$capabilities = xnative; then
        AC_DEFINE(CAPABILITIES)
 fi
 if test x$monolithic = xtrue; then
index aed0029..a8e5f19 100644 (file)
 #include <syslog.h>
 #include <time.h>
 #include <errno.h>
+
 #ifdef CAPABILITIES
+#ifdef HAVE_SYS_CAPABILITY_H
 #include <sys/capability.h>
+#endif /* HAVE_SYS_CAPABILITY_H */
 #endif /* CAPABILITIES */
 
 #include "daemon.h"
@@ -46,12 +49,16 @@ struct private_daemon_t {
         */
        daemon_t public;
 
-#ifdef CAPABILITIES
        /**
         * capabilities to keep
         */
+#ifdef CAPABILITIES_LIBCAP
        cap_t caps;
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+       struct __user_cap_data_struct caps;
+#endif /* CAPABILITIES_NATIVE */
+
 };
 
 /**
@@ -99,9 +106,9 @@ static void destroy(private_daemon_t *this)
        DESTROY_IF(this->public.receiver);
        /* unload plugins to release threads */
        lib->plugins->unload(lib->plugins);
-#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
        cap_free(this->caps);
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
        DESTROY_IF(this->public.traps);
        DESTROY_IF(this->public.ike_sa_manager);
        DESTROY_IF(this->public.kernel_interface);
@@ -133,22 +140,36 @@ static void destroy(private_daemon_t *this)
 METHOD(daemon_t, keep_cap, void,
           private_daemon_t *this, u_int cap)
 {
-#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
        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 */
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+       this->caps.effective |= 1 << cap;
+       this->caps.permitted |= 1 << cap;
+       this->caps.inheritable |= 1 << cap;
+#endif /* CAPABILITIES_NATIVE */
 }
 
 METHOD(daemon_t, drop_capabilities, bool,
           private_daemon_t *this)
 {
-#ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
        if (cap_set_proc(this->caps) != 0)
        {
                return FALSE;
        }
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+       struct __user_cap_header_struct header = {
+               .version = _LINUX_CAPABILITY_VERSION,
+       };
+       if (capset(&header, &this->caps) != 0)
+       {
+               return FALSE;
+       }
+#endif /* CAPABILITIES_NATIVE */
        return TRUE;
 }
 
@@ -397,7 +418,9 @@ private_daemon_t *daemon_create()
        );
 
 #ifdef CAPABILITIES
+#ifdef CAPABILITIES_LIBCAP
        this->caps = cap_init();
+#endif /* CAPABILITIES_LIBCAP */
        keep_cap(this, CAP_NET_ADMIN);
        if (lib->leak_detective)
        {
index 2e27b00..89123bb 100644 (file)
@@ -33,7 +33,9 @@
 #include <grp.h>
 
 #ifdef CAPABILITIES
+#ifdef HAVE_SYS_CAPABILITY_H
 #include <sys/capability.h>
+#endif /* HAVE_SYS_CAPABILITY_H */
 #endif /* CAPABILITIES */
 
 #include <freeswan.h>
@@ -258,7 +260,6 @@ int main(int argc, char **argv)
        char *virtual_private = NULL;
        int lockfd;
 #ifdef CAPABILITIES
-       cap_t caps;
        int keep[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
 #endif /* CAPABILITIES */
 
@@ -716,18 +717,41 @@ int main(int argc, char **argv)
                }
 #endif
 
-#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)
+#ifdef CAPABILITIES_LIBCAP
        {
-               plog("unable to drop daemon capabilities");
-               abort();
+               cap_t caps;
+               caps = cap_init();
+               cap_set_flag(caps, CAP_EFFECTIVE, countof(keep), keep, CAP_SET);
+               cap_set_flag(caps, CAP_INHERITABLE, countof(keep), keep, CAP_SET);
+               cap_set_flag(caps, CAP_PERMITTED, countof(keep), keep, CAP_SET);
+               if (cap_set_proc(caps) != 0)
+               {
+                       plog("unable to drop daemon capabilities");
+                       abort();
+               }
+               cap_free(caps);
        }
-       cap_free(caps);
-#endif /* CAPABILITIES */
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+       {
+               struct __user_cap_data_struct caps = { .effective = 0 };
+               struct __user_cap_header_struct header = {
+                       .version = _LINUX_CAPABILITY_VERSION,
+               };
+               int i;
+               for (i = 0; i < countof(keep); i++)
+               {
+                       caps.effective |= 1 << keep[i];
+                       caps.permitted |= 1 << keep[i];
+                       caps.inheritable |= 1 << keep[i];
+               }
+               if (capset(&header, &caps) != 0)
+               {
+                       plog("unable to drop daemon capabilities");
+                       abort();
+               }
+       }
+#endif /* CAPABILITIES_NATIVE */
 
        /* loading X.509 CA certificates */
        load_authcerts("ca", CA_CERT_PATH, X509_CA);