Do user switch after SSL keys are initialized
[umurmur.git] / src / main.c
index 78060955aff92f8e8e66a4ffdc5ced518a4347b1..d98fb6aca3a89b42fa3d4fbe2d21d51cd74208ec 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 2009-2011, Martin Johansson <martin@fatbob.nu>
-   Copyright (C) 2005-2011, Thorvald Natvig <thorvald@natvig.com>
+/* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
+   Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
 
    All rights reserved.
 
@@ -29,7 +29,6 @@
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <string.h>
 #include <stdlib.h>
 #ifdef _POSIX_PRIORITY_SCHEDULING
+#if (_POSIX_PRIORITY_SCHEDULING > 0)
+#define POSIX_PRIORITY_SCHEDULING
 #include <sched.h>
 #endif
+#endif
 #include "server.h"
 #include "ssl.h"
 #include "channel.h"
 #include "client.h"
 #include "conf.h"
 #include "version.h"
+#include "config.h"
+#include "sharedmemory.h"
+#include "ban.h"
 
 char system_string[64], version_string[64];
 int bindport;
+int bindport6;
 char *bindaddr;
+char *bindaddr6;
 
 void lockfile(const char *pidfile)
 {
@@ -66,7 +73,7 @@ void lockfile(const char *pidfile)
         * unmodified if we cannot lock it.
         */
        lfp = open(pidfile, O_WRONLY|O_CREAT, 0640);
-       
+
        if (lfp < 0)
                Log_fatal("Cannot open PID-file %s for writing", pidfile);
 
@@ -87,7 +94,7 @@ void lockfile(const char *pidfile)
        }
 
        snprintf(str,16,"%d\n", getpid());
-       write(lfp, str, strlen(str)); /* record pid to lockfile */
+       (void)write(lfp, str, strlen(str)); /* record pid to lockfile */
        Log_info("PID-file: %s", pidfile);
 
        /* If uMurmur ever starts to fork()+exec(), we don't want it to
@@ -150,33 +157,33 @@ static void switch_user(void)
 
        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)
 {
        switch(sig) {
-       case SIGHUP:
-               Log_info("HUP signal received.");
-               Log_reset();
-               break;
-       case SIGTERM:
-               Log_info("TERM signal. Shutting down.");
-               Server_shutdown();
-               break;
+               case SIGHUP:
+                       Log_info("HUP signal received.");
+                       Log_reset();
+                       break;
+               case SIGTERM:
+                       Log_info("TERM signal. Shutting down.");
+                       Server_shutdown();
+                       break;
        }
 }
 
 void daemonize()
 {
        int i;
-       
+
        if (getppid() == 1)
                return; /* already a daemon */
        i = fork();
@@ -186,22 +193,26 @@ void daemonize()
        }
        if ( i > 0)
                exit(0); /* parent exits */
-       
+
        /* child (daemon) continues */
        setsid(); /* obtain a new process group */
        for (i = getdtablesize(); i >= 0; --i)
                close(i); /* close all descriptors */
-       
+
+#ifdef USE_GNUTLS
+        gnutls_global_init();
+#endif
+
        i = open("/dev/null",O_RDWR);
-       dup(i);
-       dup(i);
-       
+       (void)dup(i);
+       (void)dup(i);
+
        umask(027); /* set newly created file permissions */
-       chdir("/");
-               
+       (void)chdir("/");
+
 }
 
-#ifdef _POSIX_PRIORITY_SCHEDULING
+#ifdef POSIX_PRIORITY_SCHEDULING
 void setscheduler()
 {
        int rc;
@@ -217,16 +228,20 @@ void setscheduler()
 
 void printhelp()
 {
-       printf("uMurmur version %s. Mumble protocol %d.%d.%d\n", UMURMUR_VERSION, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
-       printf("Usage: umurmurd [-d] [-p <pidfile>] [-c <conf file>] [-h]\n");
-       printf("       -d             - Do not daemonize\n");
-       printf("       -p <pidfile>   - Write PID to this file\n");
-       printf("       -c <conf file> - Specify configuration file\n");
-#ifdef _POSIX_PRIORITY_SCHEDULING
+       printf("uMurmur version %s ('%s'). Mumble protocol %d.%d.%d\n", UMURMUR_VERSION,
+               UMURMUR_CODENAME, PROTVER_MAJOR, PROTVER_MINOR, PROTVER_PATCH);
+       printf("Usage: umurmurd [-d] [-r] [-h] [-p <pidfile>] [-t] [-c <conf file>] [-a <addr>] [-b <port>]\n");
+       printf("       -d             - Do not daemonize - run in foreground.\n");
+#ifdef POSIX_PRIORITY_SCHEDULING
        printf("       -r             - Run with realtime priority\n");
 #endif
+       printf("       -p <pidfile>   - Write PID to this file\n");
+       printf("       -c <conf file> - Specify configuration file (default %s)\n", DEFAULT_CONFIG);
+       printf("       -t             - Test config. Error message to stderr + non-zero exit code on error\n");
        printf("       -a <address>   - Bind to IP address\n");
+       printf("       -A <address>   - Bind to IPv6 address\n");
        printf("       -b <port>      - Bind to port\n");
+       printf("       -B <port>      - Bind to port (IPv6)\n");
        printf("       -h             - Print this help\n");
        exit(0);
 }
@@ -234,109 +249,135 @@ void printhelp()
 int main(int argc, char **argv)
 {
        bool_t nodaemon = false;
-#ifdef _POSIX_PRIORITY_SCHEDULING
+#ifdef POSIX_PRIORITY_SCHEDULING
        bool_t realtime = false;
 #endif
+       bool_t testconfig = false;
        char *conffile = NULL, *pidfile = NULL;
        int c;
        struct utsname utsbuf;
-       
+
        /* Arguments */
-#ifdef _POSIX_PRIORITY_SCHEDULING
-       while ((c = getopt(argc, argv, "drp:c:a:b:h")) != EOF) {
+#ifdef POSIX_PRIORITY_SCHEDULING
+       while ((c = getopt(argc, argv, "drp:c:a:A:b:B:ht")) != EOF) {
 #else
-       while ((c = getopt(argc, argv, "dp:c:a:b:h")) != EOF) {
+               while ((c = getopt(argc, argv, "dp:c:a:A:b:B:ht")) != EOF) {
 #endif
-               switch(c) {
-               case 'c':
-                       conffile = optarg;
-                       break;
-               case 'p':
-                       pidfile = optarg;
-                       break;
-               case 'a':
-                       bindaddr = optarg;
-                       break;
-               case 'b':
-                       bindport = atoi(optarg);
-                       break;
-               case 'd':
-                       nodaemon = true;
-                       break;
-               case 'h':
-                       printhelp();
-                       break;
-#ifdef _POSIX_PRIORITY_SCHEDULING
-               case 'r':
-                       realtime = true;
-                       break;
+                       switch(c) {
+                               case 'c':
+                                       conffile = optarg;
+                                       break;
+                               case 'p':
+                                       pidfile = optarg;
+                                       break;
+                               case 'a':
+                                       bindaddr = optarg;
+                                       break;
+                               case 'A':
+                                       bindaddr6 = optarg;
+                                       break;
+                               case 'b':
+                                       bindport = atoi(optarg);
+                                       break;
+                               case 'B':
+                                       bindport6 = atoi(optarg);
+                                       break;
+                               case 'd':
+                                       nodaemon = true;
+                                       break;
+                               case 'h':
+                                       printhelp();
+                                       break;
+                               case 't':
+                                       testconfig = true;
+                                       break;
+#ifdef POSIX_PRIORITY_SCHEDULING
+                               case 'r':
+                                       realtime = true;
+                                       break;
 #endif
-               default:
-                       fprintf(stderr, "Unrecognized option\n");
-                       printhelp();
-                       break;
+                               default:
+                                       fprintf(stderr, "Unrecognized option\n");
+                                       printhelp();
+                                       break;
+                       }
                }
-       }
-       
-       /* Initialize the config subsystem early;
-        * switch_user() will need to read some config variables as well as logging.
-        */
-       Conf_init(conffile);
-       
-       /* Logging to terminal if not daemonizing, otherwise to syslog or log file.
-        */
-       if (!nodaemon) {
-               daemonize();
-               Log_init(false);
-               if (pidfile != NULL)
-                       lockfile(pidfile);
 
-               switch_user();
+               if (testconfig) {
+                       if (!Conf_ok(conffile))
+                               exit(1);
+                       else
+                               exit(0);
+               }
+
+               /* Initialize the config subsystem early;
+                * switch_user() will need to read some config variables as well as logging.
+                */
+               Conf_init(conffile);
+
+               /* Logging to terminal if not daemonizing, otherwise to syslog or log file.
+               */
+               if (!nodaemon) {
+                       daemonize();
+                       Log_init(false);
+                       if (pidfile != NULL)
+                               lockfile(pidfile);
+               }
+               else Log_init(true);
+
+               signal(SIGCHLD, SIG_IGN); /* ignore child */
+               signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
+               signal(SIGTTOU, SIG_IGN);
+               signal(SIGTTIN, SIG_IGN);
+               signal(SIGPIPE, SIG_IGN);
+               signal(SIGHUP, signal_handler); /* catch hangup signal */
+               signal(SIGTERM, signal_handler); /* catch kill signal */
+
+               /* Build system string */
+               if (uname(&utsbuf) == 0) {
+                       snprintf(system_string, 64, "%s %s", utsbuf.sysname, utsbuf.machine);
+                       snprintf(version_string, 64, "%s", utsbuf.release);
+               }
+               else {
+                       snprintf(system_string, 64, "unknown unknown");
+                       snprintf(version_string, 64, "unknown");
+               }
+
+               /* Initializing */
+               SSLi_init();
+               Chan_init();
+               Client_init();
+               Ban_init();
+
+#ifdef USE_SHAREDMEMORY_API
+    Sharedmemory_init( bindport, bindport6 );
+#endif
+
+#ifdef POSIX_PRIORITY_SCHEDULING
+               if (realtime)
+                       setscheduler();
+#endif
 
+               switch_user();
                /* Reopen log file. If user switch results in access denied, we catch
                 * it early.
                 */
-               Log_reset(); 
-       }
-       else Log_init(true);
-       
-       signal(SIGCHLD, SIG_IGN); /* ignore child */
-       signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
-       signal(SIGTTOU, SIG_IGN);
-       signal(SIGTTIN, SIG_IGN);
-       signal(SIGPIPE, SIG_IGN);
-       signal(SIGHUP, signal_handler); /* catch hangup signal */
-       signal(SIGTERM, signal_handler); /* catch kill signal */
-       
-       /* Build system string */
-       if (uname(&utsbuf) == 0) {
-               snprintf(system_string, 64, "%s %s", utsbuf.sysname, utsbuf.machine);
-               snprintf(version_string, 64, "%s", utsbuf.release);
-       }
-       else {
-               snprintf(system_string, 64, "unknown unknown");
-               snprintf(version_string, 64, "unknown");
-       }
-       
-       /* Initializing */
-       SSLi_init();
-       Chan_init();
-       Client_init();
+               Log_reset();
 
-#ifdef _POSIX_PRIORITY_SCHEDULING
-       if (realtime)
-               setscheduler();
+               Server_run();
+
+#ifdef USE_SHAREDMEMORY_API
+    Sharedmemory_deinit();
 #endif
-       
-       Server_run();
-       
-       SSLi_deinit();
-       Chan_free();
-       Log_free();
-       Conf_deinit();
-       
-       if (pidfile != NULL)
-               unlink(pidfile);
-       
-       return 0;
-}
+
+               Ban_deinit();
+               SSLi_deinit();
+               Chan_free();
+               Log_free();
+               Conf_deinit();
+
+               if (pidfile != NULL)
+                       unlink(pidfile);
+
+               return 0;
+       }