replaced --with-gid/uid by --with-group/user
authorMartin Willi <martin@strongswan.org>
Thu, 8 May 2008 10:58:04 +0000 (10:58 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 8 May 2008 10:58:04 +0000 (10:58 -0000)
using named users, groups
fixed capability dropping in pluto

12 files changed:
configure.in
src/Makefile.am
src/charon/daemon.c
src/charon/daemon.h
src/charon/plugins/smp/smp.c
src/charon/plugins/stroke/stroke_socket.c
src/libstrongswan/utils/leak_detective.c
src/pluto/plutomain.c
src/starter/Makefile.am
src/starter/invokecharon.c
src/starter/invokepluto.c
src/starter/starter.c

index d9473fd..b29ce3a 100644 (file)
@@ -118,17 +118,25 @@ AC_ARG_WITH(
 )
 
 AC_ARG_WITH(
-       [uid],
-       AS_HELP_STRING([--with-uid=uid],[change user of the daemons to UID after startup (default is 0).]),
-       [AC_DEFINE_UNQUOTED(IPSEC_UID, $withval) AC_SUBST(ipsecuid, "$withval")],
-       [AC_DEFINE_UNQUOTED(IPSEC_UID, 0) AC_SUBST(ipsecuid, "0")]
+       [uid],,[AC_MSG_ERROR([--with-uid is gone, use --with-user instead!])]
 )
 
 AC_ARG_WITH(
-       [gid],
-       AS_HELP_STRING([--with-gid=gid],[change group of the daemons to GID after startup (default is 0).]),
-       [AC_DEFINE_UNQUOTED(IPSEC_GID, $withval) AC_SUBST(ipsecgid, "$withval")],
-       [AC_DEFINE_UNQUOTED(IPSEC_GID, 0) AC_SUBST(ipsecgid, "0")]
+       [gid],,[AC_MSG_ERROR([--with-gid is gone, use --with-group instead!])]
+)
+
+AC_ARG_WITH(
+       [user],
+       AS_HELP_STRING([--with-user=user],[change user of the daemons to "user" after startup (default is 0).]),
+       [AC_DEFINE_UNQUOTED(IPSEC_USER, "$withval") AC_SUBST(ipsecuser, "$withval")],
+       [AC_SUBST(ipsecuser, "root")]
+)
+
+AC_ARG_WITH(
+       [group],
+       AS_HELP_STRING([--with-group=group],[change group of the daemons to "group" after startup (default is 0).]),
+       [AC_DEFINE_UNQUOTED(IPSEC_GROUP, "$withval") AC_SUBST(ipsecgroup, "$withval")],
+       [AC_SUBST(ipsecgroup, "root")]
 )
 
 AC_ARG_ENABLE(
index 3ed61df..1322dda 100644 (file)
@@ -42,5 +42,5 @@ endif
 EXTRA_DIST = strongswan.conf
 
 install-exec-local :   
-               test -e "$(DESTDIR)${sysconfdir}" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)"
-               test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -m 600 strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf
+               test -e "$(DESTDIR)${sysconfdir}" || $(INSTALL) -d "$(DESTDIR)$(sysconfdir)"
+               test -e "$(DESTDIR)$(sysconfdir)/strongswan.conf" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -m 640 strongswan.conf $(DESTDIR)$(sysconfdir)/strongswan.conf
index 0400a99..ce12917 100644 (file)
@@ -28,6 +28,8 @@
 #include <string.h>
 #include <getopt.h>
 #include <errno.h>
+#include <pwd.h>
+#include <grp.h>
 #ifdef HAVE_BACKTRACE
 # include <execinfo.h>
 #endif /* HAVE_BACKTRACE */
@@ -207,11 +209,17 @@ static void destroy(private_daemon_t *this)
 static void kill_daemon(private_daemon_t *this, char *reason)
 {
        /* we send SIGTERM, so the daemon can cleanly shut down */
-       DBG1(DBG_DMN, "killing daemon: %s", reason);
+       if (this->public.bus)
+       {
+               DBG1(DBG_DMN, "killing daemon: %s", reason);
+       }
+       else
+       {
+               fprintf(stderr, "killing daemon: %s\n", reason);
+       }
        if (this->main_thread_id == pthread_self())
        {
                /* initialization failed, terminate daemon */
-               destroy(this);
                unlink(PID_FILE);
                exit(-1);
        }
@@ -237,18 +245,14 @@ static void drop_capabilities(private_daemon_t *this, bool full)
        
        if (full)
        {
-#              if IPSEC_GID
-               if (setgid(IPSEC_GID) != 0)
+               if (setgid(charon->gid) != 0)
                {
-                       kill_daemon(this, "changing GID to unprivileged group failed");
+                       kill_daemon(this, "change to unprivileged group failed");       
                }
-#              endif
-#              if IPSEC_UID
-               if (setuid(IPSEC_UID) != 0)
+               if (setuid(charon->uid) != 0)
                {
-                       kill_daemon(this, "changing UID to unprivileged user failed");
+                       kill_daemon(this, "change to unprivileged user failed");        
                }
-#              endif
        }
        else
        {
@@ -283,6 +287,39 @@ static void drop_capabilities(private_daemon_t *this, bool full)
 }
 
 /**
+ * lookup UID and GID 
+ */
+static void lookup_uid_gid(private_daemon_t *this)
+{
+#ifdef IPSEC_USER
+       {
+               char buf[1024];
+               struct passwd passwd, *pwp;
+       
+               if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
+                       pwp == NULL)
+               {
+                       kill_daemon(this, "resolving user '"IPSEC_USER"' failed");
+               }
+               charon->uid = pwp->pw_uid;
+       }
+#endif
+#ifdef IPSEC_GROUP
+       {
+               char buf[1024];
+               struct group group, *grp;
+       
+               if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
+                       grp == NULL)
+               {
+                       kill_daemon(this, "reslvoing group '"IPSEC_GROUP"' failed");
+               }
+               charon->gid = grp->gr_gid;
+       }
+#endif
+}
+
+/**
  * Initialize the daemon
  */
 static bool initialize(private_daemon_t *this, bool syslog, level_t levels[])
@@ -428,6 +465,8 @@ private_daemon_t *daemon_create(void)
        this->public.outlog = NULL;
        this->public.syslog = NULL;
        this->public.authlog = NULL;
+       this->public.uid = 0;
+       this->public.gid = 0;
        
        this->main_thread_id = pthread_self();
        
@@ -496,6 +535,8 @@ int main(int argc, char *argv[])
        private_charon = daemon_create();
        charon = (daemon_t*)private_charon;
        
+       lookup_uid_gid(private_charon);
+       
        /* drop the capabilities we won't need for initialization */
        prctl(PR_SET_KEEPCAPS, 1);
        drop_capabilities(private_charon, FALSE);
@@ -571,7 +612,7 @@ int main(int argc, char *argv[])
        if (pid_file)
        {
                fprintf(pid_file, "%d\n", getpid());
-               fchown(fileno(pid_file), IPSEC_UID, IPSEC_GID);
+               fchown(fileno(pid_file), charon->uid, charon->gid);
                fclose(pid_file);
        }
        
index 5d59075..8399523 100644 (file)
@@ -299,6 +299,16 @@ struct daemon_t {
 #endif /* ME */
        
        /**
+        * User ID the daemon will user after initialization
+        */
+       uid_t uid;
+
+       /**
+        * Group ID the daemon will use after initialization
+        */
+       gid_t gid;
+       
+       /**
         * Shut down the daemon.
         * 
         * @param reason                describtion why it will be killed
index 9382451..6380714 100644 (file)
@@ -728,7 +728,7 @@ plugin_t *plugin_create()
                return NULL;
        }
        umask(old);
-       if (chown(unix_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0)
+       if (chown(unix_addr.sun_path, charon->uid, charon->gid) != 0)
        {
                DBG1(DBG_CFG, "changing XML socket permissions failed: %s", strerror(errno));
        }
index 2ae22e4..abc1479 100644 (file)
@@ -537,7 +537,7 @@ static bool open_socket(private_stroke_socket_t *this)
                return FALSE;
        }
        umask(old);
-       if (chown(socket_addr.sun_path, IPSEC_UID, IPSEC_GID) != 0)
+       if (chown(socket_addr.sun_path, charon->uid, charon->gid) != 0)
        {
                DBG1(DBG_CFG, "changing stroke socket permissions failed: %s",
                         strerror(errno));
index b979c40..e64dc0c 100644 (file)
@@ -249,6 +249,8 @@ char *whitelist[] = {
        "getprotobynumber",
        "getservbyport",
        "getservbyname",
+       "getpwnam_r",
+       "getgrnam_r",
        "register_printf_function",
        "syslog",
        "vsyslog",
index 49638a3..f1b3163 100644 (file)
@@ -31,6 +31,8 @@
 #include <sys/queue.h>
 #include <linux/capability.h>
 #include <sys/prctl.h>
+#include <pwd.h>
+#include <grp.h>
 
 #include <freeswan.h>
 
@@ -617,19 +619,43 @@ main(int argc, char **argv)
     init_fetch();
 
     /* drop unneeded capabilities and change UID/GID */
+#ifdef _LINUX_CAPABILITY_VERSION_1
+    hdr.version = _LINUX_CAPABILITY_VERSION_1;
+#else
     hdr.version = _LINUX_CAPABILITY_VERSION;
+#endif
     hdr.pid = 0;
     data.inheritable = data.effective = data.permitted = 
                                1<<CAP_NET_ADMIN | 1<<CAP_NET_BIND_SERVICE;
 
     prctl(PR_SET_KEEPCAPS, 1);
+       
+#ifdef IPSEC_GROUP
+    {
+       struct group group, *grp;
+    char buf[1024];
 
-#   if IPSEC_GID
-       setgid(IPSEC_GID);
-#   endif
-#   if IPSEC_UID
-       setuid(IPSEC_UID);
-#   endif
+       if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) != 0 ||
+               grp == NULL || setgid(grp->gr_gid) != 0)
+       {
+           plog("unable to change daemon group");
+           abort();
+       }
+    }
+#endif
+#ifdef IPSEC_USER
+    {
+       struct passwd passwd, *pwp;
+    char buf[1024];
+
+       if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) != 0 ||
+               pwp == NULL || setuid(pwp->pw_uid) != 0)
+       {
+           plog("unable to change daemon user");
+           abort();
+       }
+       }
+#endif
     if (capset(&hdr, &data))
     {
        plog("unable to drop root privileges");
index e3b7f0d..3a8a313 100644 (file)
@@ -31,14 +31,14 @@ defs.o:             $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
                $(COMPILE) -c -o $@ $<
 
 install-exec-local :   
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/certs"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/crls"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(MKDIR_P) "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs"
-               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(MKDIR_P) -m 700 "$(DESTDIR)$(sysconfdir)/ipsec.d/private"
-               test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -m 644 ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/cacerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/cacerts"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/ocspcerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/ocspcerts"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/certs" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/certs"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/acerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/acerts"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/aacerts" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/aacerts"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/crls" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/crls"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/reqs" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d "$(DESTDIR)$(sysconfdir)/ipsec.d/reqs"
+               test -e "$(DESTDIR)${sysconfdir}/ipsec.d/private" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -d -m 750 "$(DESTDIR)$(sysconfdir)/ipsec.d/private"
+               test -e "$(DESTDIR)$(sysconfdir)/ipsec.conf" || $(INSTALL) -o ${ipsecuser} -g ${ipsecgroup} -m 644 ipsec.conf $(DESTDIR)$(sysconfdir)/ipsec.conf
 
index 477be1f..ade71fc 100644 (file)
@@ -103,8 +103,8 @@ starter_stop_charon (void)
 int
 starter_start_charon (starter_config_t *cfg, bool debug)
 {
-    int pid, i;
     struct stat stb;
+    int pid, i;
     char buffer[BUF_LEN];
     int argc = 1;
     char *arg[] = {
@@ -159,34 +159,6 @@ starter_start_charon (starter_config_t *cfg, bool debug)
        unlink(CHARON_CTL_FILE);
        _stop_requested = 0;
 
-       /* if ipsec.secrets file is missing then generate RSA default key pair */
-       if (stat(SECRETS_FILE, &stb) != 0)
-       {
-           mode_t oldmask;
-           FILE *f;
-
-           plog("no %s file, generating RSA key", SECRETS_FILE);
-           seteuid(IPSEC_UID);
-           setegid(IPSEC_GID);
-           system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
-           seteuid(0);
-           setegid(0);
-
-           /* ipsec.secrets is root readable only */
-           oldmask = umask(0066);
-
-           f = fopen(SECRETS_FILE, "w");
-           if (f)
-           {
-               fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
-               fprintf(f, "\n");
-               fprintf(f, ": RSA myKey.der\n");
-               fclose(f);
-           }
-           chown(SECRETS_FILE, IPSEC_UID, IPSEC_GID);
-           umask(oldmask);
-       }
-
        pid = fork();
        switch (pid)
        {
index b3a8749..c2b9c73 100644 (file)
@@ -106,8 +106,8 @@ starter_stop_pluto (void)
 int
 starter_start_pluto (starter_config_t *cfg, bool debug)
 {
-    int i;
     struct stat stb;
+    int i;
     pid_t pid;
     char **l;
     int argc = 2;
@@ -218,34 +218,6 @@ starter_start_pluto (starter_config_t *cfg, bool debug)
        if (cfg->setup.prepluto)
            system(cfg->setup.prepluto);
 
-       /* if ipsec.secrets file is missing then generate RSA default key pair */
-       if (stat(SECRETS_FILE, &stb) != 0)
-       {
-           mode_t oldmask;
-           FILE *f;
-
-           plog("no %s file, generating RSA key", SECRETS_FILE);
-           seteuid(IPSEC_UID);
-           setegid(IPSEC_GID);
-           system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
-           seteuid(0);
-           setegid(0);
-
-           /* ipsec.secrets is root readable only */
-           oldmask = umask(0066);
-
-           f = fopen(SECRETS_FILE, "w");
-           if (f)
-           {
-               fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
-               fprintf(f, "\n");
-               fprintf(f, ": RSA myKey.der\n");
-               fclose(f);
-           }
-           chown(SECRETS_FILE, IPSEC_UID, IPSEC_GID);
-           umask(oldmask);
-       }
-
        pid = fork();
        switch (pid)
        {
index c92b2bc..ff042e2 100644 (file)
@@ -26,6 +26,8 @@
 #include <string.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
 
 #include <freeswan.h>
 
@@ -139,6 +141,64 @@ fsig(int signal)
     }
 }
 
+static void generate_selfcert()
+{
+    struct stat stb;
+    
+       /* if ipsec.secrets file is missing then generate RSA default key pair */
+       if (stat(SECRETS_FILE, &stb) != 0)
+       {
+           mode_t oldmask;
+           FILE *f;
+           uid_t uid = 0;
+           gid_t gid = 0;
+
+#ifdef IPSEC_GROUP
+               {
+                       char buf[1024];
+                       struct group group, *grp;
+               
+                       if (getgrnam_r(IPSEC_GROUP, &group, buf, sizeof(buf), &grp) == 0 &&
+                               grp)
+                       {
+                               gid = grp->gr_gid;
+                       }
+               }
+#endif
+#ifdef IPSEC_USER
+               {
+                       char buf[1024];
+                       struct passwd passwd, *pwp;
+               
+                       if (getpwnam_r(IPSEC_USER, &passwd, buf, sizeof(buf), &pwp) == 0 &&
+                               pwp)
+                       {
+                               uid = pwp->pw_uid;
+                       }
+               }
+#endif
+           setegid(gid);
+           seteuid(uid);
+           system("ipsec scepclient --out pkcs1 --out cert-self --quiet");
+           seteuid(0);
+           setegid(0);
+
+           /* ipsec.secrets is root readable only */
+           oldmask = umask(0066);
+
+           f = fopen(SECRETS_FILE, "w");
+           if (f)
+           {
+               fprintf(f, "# /etc/ipsec.secrets - strongSwan IPsec secrets file\n");
+               fprintf(f, "\n");
+               fprintf(f, ": RSA myKey.der\n");
+               fclose(f);
+           }
+           chown(SECRETS_FILE, uid, gid);
+           umask(oldmask);
+       }
+}
+
 static void
 usage(char *name)
 {
@@ -274,6 +334,8 @@ int main (int argc, char **argv)
        plog("starter is already running (%s exists) -- no fork done", STARTER_PID_FILE);
        exit(LSB_RC_SUCCESS);
     }
+    
+    generate_selfcert();
 
     /* fork if we're not debugging stuff */
     if (!no_fork)