support of PKCS#11 init arguments required by NSS softoken, patch contributed by...
[strongswan.git] / src / pluto / plutomain.c
index 5d6e7aa..a5bf827 100644 (file)
@@ -29,6 +29,8 @@
 #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 <freeswan.h>
 
 #include "ocsp.h"
 #include "crl.h"
 #include "fetch.h"
+#include "xauth.h"
 #include "sha1.h"
 #include "md5.h"
 #include "crypto.h"    /* requires sha1.h and md5.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)
 {
@@ -80,7 +88,7 @@ usage(const char *mess)
            " [--nocrsend]"
            " \\\n\t"
            "[--strictcrlpolicy]"
-           " [--crlcheckinterval]"
+           " [--crlcheckinterval <interval>]"
            " [--cachecrls]"
            " [--uniqueids]"
            " \\\n\t"
@@ -96,7 +104,8 @@ usage(const char *mess)
            " \\\n\t"
            "[--adns <pathname>]"
            "[--pkcs11module <path>]"
-           "[--pkcs11keepstate"
+           "[--pkcs11keepstate]"
+           "[--pkcs11initargs <string>]"
 #ifdef DEBUG
            " \\\n\t"
            "[--debug-none]"
@@ -209,6 +218,11 @@ bool pkcs11_keep_state = FALSE;
 /* by default pluto does not allow pkcs11 proxy access via whack */
 bool pkcs11_proxy = FALSE;
 
+/* argument string to pass to PKCS#11 module.
+ * Not used for compliant modules, just for NSS softoken
+ */
+static const char *pkcs11_init_args = NULL;
+
 int
 main(int argc, char **argv)
 {
@@ -220,6 +234,8 @@ 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;
 
     /* handle arguments */
     for (;;)
@@ -253,6 +269,7 @@ main(int argc, char **argv)
 #endif /* !USE_LWRES */
            { "pkcs11module", required_argument, NULL, 'm' },
            { "pkcs11keepstate", no_argument, NULL, 'k' },
+           { "pkcs11initargs", required_argument, NULL, 'z' },
            { "pkcs11proxy", no_argument, NULL, 'y' },
            { "nat_traversal", no_argument, NULL, '1' },
            { "keep_alive", required_argument, NULL, '2' },
@@ -422,6 +439,10 @@ main(int argc, char **argv)
            pkcs11_proxy = TRUE;
            continue;
 
+       case 'z':       /* --pkcs11initargs */
+           pkcs11_init_args = optarg;
+           continue;
+
 #ifdef DEBUG
        case 'N':       /* --debug-none */
            base_debugging = DBG_NONE;
@@ -506,19 +527,6 @@ main(int argc, char **argv)
        }
     }
 
-#ifdef IPSECPOLICY
-    /* create info socket. */
-    {
-       err_t ugh = init_info_socket();
-
-       if (ugh != NULL)
-       {
-           fprintf(stderr, "pluto: %s", ugh);
-           exit_pluto(1);
-       }
-    }
-#endif
-
     /* If not suppressed, do daemon fork */
 
     if (fork_desired)
@@ -570,12 +578,10 @@ main(int argc, char **argv)
        int i;
 
        for (i = getdtablesize() - 1; i >= 0; i--)  /* Bad hack */
-           if ((!log_to_stderr || i != 2)
-#ifdef IPSECPOLICY
-           && i != info_fd
-#endif
-           && i != ctl_fd)
+       {
+           if ((!log_to_stderr || i != 2) && i != ctl_fd)
                close(i);
+       }
 
        /* make sure that stdin, stdout, stderr are reserved */
        if (open("/dev/null", O_RDONLY) != 0)
@@ -598,7 +604,8 @@ main(int argc, char **argv)
 
     init_nat_traversal(nat_traversal, keep_alive, force_keepalive, nat_t_spf);
     init_virtual_ip(virtual_private);
-    scx_init(pkcs11_module_path);   /* load and initialize PKCS #11 module */
+    scx_init(pkcs11_module_path, pkcs11_init_args);   /* load and initialize PKCS #11 module */
+    xauth_init();                  /* load and initialize XAUTH module */
     init_rnd_pool();
     init_secret();
     init_states();
@@ -609,6 +616,26 @@ main(int argc, char **argv)
     init_id();
     init_fetch();
 
+    /* drop unneeded capabilities and change UID/GID */
+    hdr.version = _LINUX_CAPABILITY_VERSION;
+    hdr.pid = 0;
+    data.effective = data.permitted = 1<<CAP_NET_ADMIN | 1<<CAP_NET_BIND_SERVICE;
+    data.inheritable = 0;
+
+    prctl(PR_SET_KEEPCAPS, 1);
+
+#   if IPSEC_GID
+       setgid(IPSEC_GID);
+#   endif
+#   if IPSEC_UID
+       setuid(IPSEC_UID);
+#   endif
+    if (capset(&hdr, &data))
+    {
+       plog("unable to drop root privileges");
+       abort();
+    }
+
     /* loading X.509 CA certificates */
     load_authcerts("CA cert", CA_CERT_PATH, AUTH_CA);
     /* loading X.509 AA certificates */
@@ -649,6 +676,7 @@ exit_pluto(int status)
     free_ocsp();               /* free ocsp cache */
     free_ifaces();
     scx_finalize();            /* finalize and unload PKCS #11 module */
+    xauth_finalize();          /* finalize and unload XAUTH module */
     stop_adns();
     free_md_pool();
     delete_lock();