capability API to allow plugin-controlled capability set
authorMartin Willi <martin@strongswan.org>
Thu, 28 Aug 2008 16:27:48 +0000 (16:27 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 28 Aug 2008 16:27:48 +0000 (16:27 -0000)
src/charon/daemon.c
src/charon/daemon.h
src/charon/plugins/eap_gtc/eap_gtc_plugin.c
src/libstrongswan/library.c
src/libstrongswan/library.h
src/libstrongswan/utils/leak_detective.c

index 9e0b16a..3d2ad77 100644 (file)
@@ -80,6 +80,11 @@ struct private_daemon_t {
         * The thread_id of main-thread.
         */
        pthread_t main_thread_id;
+       
+       /**
+        * capabilities to keep
+        */
+       u_int32_t keep;
 };
 
 /**
@@ -247,41 +252,20 @@ static void kill_daemon(private_daemon_t *this, char *reason)
 /**
  * drop daemon capabilities
  */
-static void drop_capabilities(private_daemon_t *this, bool full)
+static void drop_capabilities(private_daemon_t *this)
 {
        struct __user_cap_header_struct hdr;
        struct __user_cap_data_struct data;
        
-       /* CAP_NET_ADMIN is needed to use netlink,
-        * CAP_AUDIT_WRITE for PAM authentication in EAP-GTC */
-       u_int32_t keep = (1<<CAP_NET_ADMIN) | (1<<CAP_SYS_NICE) |
-                                        (1<<CAP_AUDIT_WRITE);
-       
-       if (full)
+       prctl(PR_SET_KEEPCAPS, 1);
+
+       if (setgid(charon->gid) != 0)
        {
-               if (setgid(charon->gid) != 0)
-               {
-                       kill_daemon(this, "change to unprivileged group failed");       
-               }
-               if (setuid(charon->uid) != 0)
-               {
-                       kill_daemon(this, "change to unprivileged user failed");        
-               }
+               kill_daemon(this, "change to unprivileged group failed");       
        }
-       else
+       if (setuid(charon->uid) != 0)
        {
-               /* CAP_NET_BIND_SERVICE to bind services below port 1024 */
-               keep |= (1<<CAP_NET_BIND_SERVICE);
-               /* CAP_NET_RAW to create RAW sockets */
-               keep |= (1<<CAP_NET_RAW);
-               /* CAP_DAC_READ_SEARCH to read ipsec.secrets */
-               keep |= (1<<CAP_DAC_READ_SEARCH);
-               /* CAP_CHOWN to change file permissions (socket permissions) */
-               keep |= (1<<CAP_CHOWN);
-               /* CAP_SETUID to call setuid()  */
-               keep |= (1<<CAP_SETUID);
-               /* CAP_SETGID to call setgid() */
-               keep |= (1<<CAP_SETGID);
+               kill_daemon(this, "change to unprivileged user failed");        
        }
 
        /* we use the old capset version for now. For systems with version 2
@@ -292,7 +276,7 @@ static void drop_capabilities(private_daemon_t *this, bool full)
        hdr.version = _LINUX_CAPABILITY_VERSION;
 #endif
        hdr.pid = 0;
-       data.inheritable = data.effective = data.permitted = keep;
+       data.inheritable = data.effective = data.permitted = this->keep;
        
        if (capset(&hdr, &data))
        {
@@ -301,6 +285,14 @@ static void drop_capabilities(private_daemon_t *this, bool full)
 }
 
 /**
+ * Implementation of daemon_t.keep_cap
+ */
+static void keep_cap(private_daemon_t *this, u_int cap)
+{
+       this->keep |= 1 << cap;
+}
+
+/**
  * lookup UID and GID 
  */
 static void lookup_uid_gid(private_daemon_t *this)
@@ -479,6 +471,7 @@ private_daemon_t *daemon_create(void)
                
        /* assign methods */
        this->public.kill = (void (*) (daemon_t*,char*))kill_daemon;
+       this->public.keep_cap = (void(*)(daemon_t*, u_int cap))keep_cap;
        
        /* NULL members for clean destruction */
        this->public.socket = NULL;
@@ -505,6 +498,11 @@ private_daemon_t *daemon_create(void)
        this->public.gid = 0;
        
        this->main_thread_id = pthread_self();
+       this->keep = 1<<CAP_NET_ADMIN;
+       if (lib->leak_detective)
+       {
+               this->keep = 1<<CAP_SYS_NICE;
+       }
        
        /* add handler for SEGV and ILL,
         * add handler for USR1 (cancellation).
@@ -574,10 +572,6 @@ int main(int argc, char *argv[])
        
        lookup_uid_gid(private_charon);
        
-       /* drop the capabilities we won't need for initialization */
-       prctl(PR_SET_KEEPCAPS, 1);
-       drop_capabilities(private_charon, FALSE);
-       
        /* use CTRL loglevel for default */
        for (signal = 0; signal < DBG_MAX; signal++)
        {
@@ -653,8 +647,8 @@ int main(int argc, char *argv[])
                fclose(pid_file);
        }
        
-       /* drop additional capabilites (bind & root) */
-       drop_capabilities(private_charon, TRUE);
+       /* drop the capabilities we won't need */
+       drop_capabilities(private_charon);
        
        /* start the engine, go multithreaded */
        charon->processor->set_threads(charon->processor,
index 3633e45..3bde9a2 100644 (file)
@@ -303,6 +303,15 @@ struct daemon_t {
        gid_t gid;
        
        /**
+        * Do not drop a given capability after initialization.
+        *
+        * Some plugins might need additional capabilites. They tell the daemon
+        * during plugin initialization which one they need, the daemon won't
+        * drop these.
+        */
+       void (*keep_cap)(daemon_t *this, u_int cap);
+       
+       /**
         * Shut down the daemon.
         * 
         * @param reason                describtion why it will be killed
index 58a2310..0407edc 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <daemon.h>
 
+#include <linux/capability.h>
+
 /**
  * Implementation of plugin_t.destroy
  */
@@ -42,6 +44,9 @@ plugin_t *plugin_create()
        
        this->plugin.destroy = (void(*)(plugin_t*))destroy;
        
+       /* required for PAM authentication */
+       charon->keep_cap(charon, CAP_AUDIT_WRITE);
+       
        charon->eap->add_method(charon->eap, EAP_GTC, 0, EAP_SERVER,
                                                        (eap_constructor_t)eap_gtc_create_server);
        charon->eap->add_method(charon->eap, EAP_GTC, 0, EAP_PEER,
index fe7498f..6b9043b 100644 (file)
@@ -86,6 +86,8 @@ void library_init(char *settings)
        private_library_t *this = malloc_thing(private_library_t);
        lib = &this->public;
        
+       lib->leak_detective = FALSE;
+       
 #ifdef LEAK_DETECTIVE
        this->detective = leak_detective_create();
 #endif /* LEAK_DETECTIVE */
index 9d151c4..2ea4b62 100644 (file)
@@ -108,6 +108,11 @@ struct library_t {
         * various settings loaded from settings file
         */
        settings_t *settings;
+       
+       /**
+        * is leak detective running?
+        */
+       bool leak_detective;
 };
 
 /**
index 72da4bd..70726da 100644 (file)
@@ -560,6 +560,7 @@ leak_detective_t *leak_detective_create()
        
        if (getenv("LEAK_DETECTIVE_DISABLE") == NULL)
        {
+               lib->leak_detective = TRUE;
                install_hooks();
        }
        return &this->public;