Issue 15 - Patch by tilman2: Drop privileges optionally
authorfatbob313 <martin@fatbob.nu>
Sun, 23 Jan 2011 11:58:12 +0000 (11:58 +0000)
committerfatbob313 <martin@fatbob.nu>
Sun, 23 Jan 2011 11:58:12 +0000 (11:58 +0000)
src/conf.c
src/conf.h
src/main.c
umurmur.conf.example

index 72fd8f1563ec7c92ab8c767f10f02e9312798843..35926473f9cbd81faffc24964a335e1801ca7b5d 100644 (file)
@@ -136,6 +136,28 @@ const char *getStrConf(param_t param)
                        return "";
                }
                break;
+       case USERNAME:
+               setting = config_lookup(&configuration, "username");
+               if (!setting)
+                       return "";
+               else {
+                       if ((strsetting = config_setting_get_string(setting)) != NULL)
+                               return strsetting;
+                       else
+                       return "";
+               }
+               break;
+       case GROUPNAME:
+               setting = config_lookup(&configuration, "groupname");
+               if (!setting)
+                       return "";
+               else {
+                       if ((strsetting = config_setting_get_string(setting)) != NULL)
+                               return strsetting;
+                       else
+                       return "";
+               }
+               break;
        default:
                doAssert(false);
                break;
index 1b9b21e9da929a0a31bf0902f651b1afb45cb1bc..6e0a6662a8e106894905987dadea2903d1b577c7 100644 (file)
@@ -43,6 +43,8 @@ typedef enum param {
        MAX_BANDWIDTH,
        MAX_CLIENTS,
        DEFAULT_CHANNEL,
+       USERNAME,
+       GROUPNAME,
 } param_t;
 
 typedef struct {
index 7bd8a0bfbefdcc2a7e6dadb4a95efbc0744a8582..36c5f88db63232928ba607e91518c4292a21aacc 100644 (file)
@@ -36,6 +36,8 @@
 #include <sys/stat.h>
 #include <sys/utsname.h>
 #include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
 #include <signal.h>
 #include <errno.h>
 #include <string.h>
@@ -70,6 +72,59 @@ void lockfile(const char *pidfile)
        Log_info("PID-file: %s", pidfile);
 }
 
+/* Drops privileges (if configured to do so). */
+static void switch_user(void)
+{
+       struct passwd *pwd;
+       struct group *grp = NULL;
+       const char *username, *groupname;
+       gid_t gid;
+
+       username = getStrConf(USERNAME);
+       groupname = getStrConf(GROUPNAME);
+
+       if (!*username) {
+               /* It's an error to specify groupname
+                * but leave username empty.
+                */
+               if (*groupname)
+                       Log_fatal("username missing");
+
+               /* Nothing to do. */
+               return;
+       }
+
+       pwd = getpwnam(username);
+       if (!pwd)
+               Log_fatal("Unknown user '%s'", username);
+
+       if (!*groupname)
+               gid = pwd->pw_gid;
+       else {
+               grp = getgrnam(groupname);
+
+               if (!grp)
+                       Log_fatal("Unknown group '%s'", groupname);
+
+               gid = grp->gr_gid;
+       }
+
+       if (initgroups(pwd->pw_name, gid))
+               Log_fatal("initgroups() failed: %s", strerror(errno));
+
+       if (setgid(gid))
+               Log_fatal("setgid() failed: %s", strerror(errno));
+
+       if (setuid(pwd->pw_uid))
+               Log_fatal("setuid() failed: %s", strerror(errno));
+       
+       if (!grp)
+               grp = getgrgid(gid);
+       if (!grp)
+               Log_fatal("getgrgid() failed: %s", strerror(errno));
+       
+       Log_info("Switch to user '%s' group '%s'", pwd->pw_name, grp->gr_name);
+}
 
 void signal_handler(int sig)
 {
@@ -189,18 +244,28 @@ int main(int argc, char **argv)
                        break;
                }
        }
+
+       /* Logging to terminal if not daemonizing, otherwise to syslog.
+        * Need to initialize logging before calling Conf_init()
+        */
+       if (!nodaemon)
+               Log_init(false);
+       else
+               Log_init(true);
        
+       /* Initialize the config subsystem early;
+        * switch_user() will need to read some config variables.
+        */
+       Conf_init(conffile);
+
        if (!nodaemon) {
-               Log_init(false);
                daemonize();
                if (pidfile != NULL)
                        lockfile(pidfile);
+
+               switch_user();
        }
-       else
-               Log_init(true);
 
-       Conf_init(conffile);
-                       
        signal(SIGCHLD, SIG_IGN); /* ignore child */
        signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
        signal(SIGTTOU, SIG_IGN);
index 47c0dea0d9e76eb842fc0e495a7142030faacf0e..09b49c5a581de5c8354341481e18f4ee66e02001 100644 (file)
@@ -4,6 +4,8 @@ certificate = "/etc/umurmur/cert.crt";
 private_key = "/etc/umurmur/key.key";
 password = "";
 max_users = 10;
+username = "";
+groupname = "";
 
 # Root channel must always be defined first.
 # If a channel has a parent, the parent must be defined before the child channel(s).