]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
capabilities: Ensure required capabilities are actually held by the process/user
authorTobias Brunner <tobias@strongswan.org>
Wed, 8 May 2013 15:14:29 +0000 (17:14 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 25 Jun 2013 15:16:32 +0000 (17:16 +0200)
src/charon-nm/nm/nm_backend.c
src/libcharon/daemon.c
src/libcharon/plugins/xauth_pam/xauth_pam_plugin.c
src/libstrongswan/utils/capabilities.c
src/libstrongswan/utils/capabilities.h

index c18bf992a945be157ff61ea7621623143a2fb457..e07919827b5c0c4a96227746592f5f8b8d98ee6e 100644 (file)
@@ -142,7 +142,12 @@ static bool nm_backend_init()
        }
 
        /* bypass file permissions to read from users ssh-agent */
-       charon->caps->keep(charon->caps, CAP_DAC_OVERRIDE);
+       if (!charon->caps->keep(charon->caps, CAP_DAC_OVERRIDE))
+       {
+               DBG1(DBG_CFG, "NM backend requires CAP_DAC_OVERRIDE capability");
+               nm_backend_deinit();
+               return FALSE;
+       }
 
        lib->processor->queue_job(lib->processor,
                (job_t*)callback_job_create_with_prio((callback_job_cb_t)run, this,
index 70262b73692df579475197b08e5af1a49d859810..e375ab73152f1e647a10bd2ce2f2c7f8e3a871e6 100644 (file)
@@ -591,8 +591,6 @@ private_daemon_t *daemon_create(const char *name)
        this->public.shunts = shunt_manager_create();
        this->kernel_handler = kernel_handler_create();
 
-       this->public.caps->keep(this->public.caps, CAP_NET_ADMIN);
-
        return this;
 }
 
@@ -628,6 +626,12 @@ bool libcharon_init(const char *name)
 
        this = daemon_create(name);
 
+       if (!this->public.caps->keep(this->public.caps, CAP_NET_ADMIN))
+       {
+               dbg(DBG_DMN, 1, "libcharon requires CAP_NET_ADMIN capability");
+               return FALSE;
+       }
+
        /* for uncritical pseudo random numbers */
        srandom(time(NULL) + getpid());
 
index b9ba0b5ac8b7056242491a479dbf0d75eea6d340..522cc2426712a7ccaccf7923d10da89b05ac75d1 100644 (file)
@@ -52,6 +52,13 @@ plugin_t *xauth_pam_plugin_create()
 {
        xauth_pam_plugin_t *this;
 
+       /* required for PAM authentication */
+       if (!charon->caps->keep(charon->caps, CAP_AUDIT_WRITE))
+       {
+               DBG1(DBG_DMN, "xauth-pam plugin requires CAP_AUDIT_WRITE capability");
+               return NULL;
+       }
+
        INIT(this,
                .plugin = {
                        .get_name = _get_name,
@@ -60,8 +67,5 @@ plugin_t *xauth_pam_plugin_create()
                },
        );
 
-       /* required for PAM authentication */
-       charon->caps->keep(charon->caps, CAP_AUDIT_WRITE);
-
        return &this->plugin;
 }
index 89f47820e148b7f4dea74120da2b8271574e0ac8..059271713f3231e916b64e47aaaa95272abc8e16 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  * Copyright (C) 2012 Martin Willi
  * Copyright (C) 2012 revosec AG
@@ -76,9 +76,57 @@ struct private_capabilities_t {
 #endif
 };
 
-METHOD(capabilities_t, keep, void,
+static bool has_capability(u_int cap)
+{
+#ifndef CAPABILITIES
+       /* if we can't check the actual capabilities assume only root has it */
+       return getuid() == 0;
+#endif /* !CAPABILITIES */
+#ifdef CAPABILITIES_LIBCAP
+       cap_flag_value_t val;
+       cap_t caps;
+       bool ok;
+
+       caps = cap_get_proc();
+       if (!caps)
+       {
+               return FALSE;
+       }
+       ok = cap_get_flag(caps, cap, CAP_PERMITTED, &val) == 0 && val == CAP_SET;
+       cap_free(caps);
+       return ok;
+#endif /* CAPABILITIES_LIBCAP */
+#ifdef CAPABILITIES_NATIVE
+       struct __user_cap_header_struct header = {
+#if defined(_LINUX_CAPABILITY_VERSION_3)
+               .version = _LINUX_CAPABILITY_VERSION_3,
+#elif defined(_LINUX_CAPABILITY_VERSION_2)
+               .version = _LINUX_CAPABILITY_VERSION_2,
+#elif defined(_LINUX_CAPABILITY_VERSION_1)
+               .version = _LINUX_CAPABILITY_VERSION_1,
+#else
+               .version = _LINUX_CAPABILITY_VERSION,
+#endif
+       };
+       struct __user_cap_data_struct caps[2];
+       int i = 0;
+
+       if (cap >= 32)
+       {
+               i++;
+               cap -= 32;
+       }
+       return capget(&header, caps) == 0 && caps[i].permitted & (1 << cap);
+#endif /* CAPABILITIES_NATIVE */
+}
+
+METHOD(capabilities_t, keep, bool,
        private_capabilities_t *this, u_int cap)
 {
+       if (!has_capability(cap))
+       {
+               return FALSE;
+       }
 #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);
@@ -96,6 +144,7 @@ METHOD(capabilities_t, keep, void,
        this->caps[i].permitted |= 1 << cap;
        this->caps[i].inheritable |= 1 << cap;
 #endif /* CAPABILITIES_NATIVE */
+       return TRUE;
 }
 
 METHOD(capabilities_t, get_uid, uid_t,
index cd23cbf107c31b30c8cb5f7c065149f84f1d568a..3de11bc6cc9a95f90931017a5bdb5958509bac0d 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
  * Copyright (C) 2012 Martin Willi
  * Copyright (C) 2012 revosec AG
  *
@@ -36,11 +38,14 @@ typedef struct capabilities_t capabilities_t;
 struct capabilities_t {
 
        /**
-        * Register a capability to keep while calling drop().
+        * Register a capability to keep while calling drop(). Verifies that the
+        * capability is currently held.
         *
         * @param cap           capability to keep
+        * @return                      FALSE if the capability is currently not held
         */
-       void (*keep)(capabilities_t *this, u_int cap);
+       bool (*keep)(capabilities_t *this,
+                                u_int cap) __attribute__((warn_unused_result));
 
        /**
         * Get the user ID set through set_uid/resolve_uid.