diff --git a/Android.mk.in b/Android.mk.in index 6277861ed..a5cc7df12 100644 --- a/Android.mk.in +++ b/Android.mk.in @@ -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 \ diff --git a/configure.in b/configure.in index 7589c30b3..280465032 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c index aed0029e5..a8e5f19b1 100644 --- a/src/libcharon/daemon.c +++ b/src/libcharon/daemon.c @@ -22,8 +22,11 @@ #include #include #include + #ifdef CAPABILITIES +#ifdef HAVE_SYS_CAPABILITY_H #include +#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) { diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index 2e27b00f8..89123bb8a 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -33,7 +33,9 @@ #include #ifdef CAPABILITIES +#ifdef HAVE_SYS_CAPABILITY_H #include +#endif /* HAVE_SYS_CAPABILITY_H */ #endif /* CAPABILITIES */ #include @@ -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);