]> source.dussan.org Git - rspamd.git/commitdiff
* Fix reopening of logs in case of privilleged run.
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Wed, 30 Nov 2011 16:14:26 +0000 (19:14 +0300)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Wed, 30 Nov 2011 16:14:26 +0000 (19:14 +0300)
src/logger.c
src/logger.h
src/main.c
src/main.h

index 07b0eca341dd9f424e48da46abe780a22f2e26f8..219f04cac2b3a0a7240a1c98dfdf3fa69fe9f850 100644 (file)
@@ -117,7 +117,7 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo
                if (r == -1) {
                        /* We cannot write message to file, so we need to detect error and make decision */
                        r = rspamd_snprintf (errmsg, sizeof (errmsg), "direct_write_log_line: cannot write log line: %s", strerror (errno));
-                       if (errno == EBADF || errno == EIO || errno == EINTR) {
+                       if (errno == EIO || errno == EINTR) {
                                /* Descriptor is somehow invalid, try to restart */
                                reopen_log (rspamd_log);
                                if (write (rspamd_log->fd, errmsg, r) != -1) {
@@ -130,8 +130,8 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo
                                rspamd_log->throttling = TRUE;
                                rspamd_log->throttling_time = time (NULL);
                        }
-                       else if (errno == EPIPE) {
-                               /* We write to some pipe and it disappears, disable logging */
+                       else if (errno == EPIPE || errno == EBADF) {
+                               /* We write to some pipe and it disappears, disable logging or we has opened bad file descriptor */
                                rspamd_log->enabled = FALSE;
                        }
                }
@@ -143,17 +143,16 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo
 
 /* Logging utility functions */
 gint
-open_log (rspamd_logger_t *rspamd_log)
+open_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid)
 {
-
-       rspamd_log->enabled = TRUE;
-
        switch (rspamd_log->cfg->log_type) {
        case RSPAMD_LOG_CONSOLE:
                /* Do nothing with console */
+               rspamd_log->enabled = TRUE;
                return 0;
        case RSPAMD_LOG_SYSLOG:
                openlog ("rspamd", LOG_NDELAY | LOG_PID, rspamd_log->cfg->log_facility);
+               rspamd_log->enabled = TRUE;
                return 0;
        case RSPAMD_LOG_FILE:
                rspamd_log->fd = open (rspamd_log->cfg->log_file, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
@@ -161,13 +160,18 @@ open_log (rspamd_logger_t *rspamd_log)
                        fprintf (stderr, "open_log: cannot open desired log file: %s, %s", rspamd_log->cfg->log_file, strerror (errno));
                        return -1;
                }
+               if (fchown (rspamd_log->fd, uid, gid) == -1) {
+                       fprintf (stderr, "open_log: cannot chown desired log file: %s, %s", rspamd_log->cfg->log_file, strerror (errno));
+                       return -1;
+               }
+               rspamd_log->enabled = TRUE;
                return 0;
        }
        return -1;
 }
 
 void
-close_log (rspamd_logger_t *rspamd_log)
+close_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid)
 {
        gchar                           tmpbuf[256];
        flush_log_buf (rspamd_log);
@@ -207,6 +211,43 @@ close_log (rspamd_logger_t *rspamd_log)
        rspamd_log->enabled = FALSE;
 }
 
+gint
+reopen_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid)
+{
+       close_log_priv (rspamd_log, uid, gid);
+       if (open_log_priv (rspamd_log, uid, gid) == 0) {
+               msg_info ("log file reopened");
+               return 0;
+       }
+
+       return -1;
+}
+
+/**
+ * Open log file or initialize other structures
+ */
+gint
+open_log (rspamd_logger_t *logger)
+{
+       return open_log_priv (logger, -1, -1);
+}
+/**
+ * Close log file or destroy other structures
+ */
+void
+close_log (rspamd_logger_t *logger)
+{
+       close_log_priv (logger, -1, -1);
+}
+/**
+ * Close and open log again
+ */
+gint
+reopen_log (rspamd_logger_t *logger)
+{
+       return reopen_log_priv (logger, -1, -1);
+}
+
 /*
  * Setup logger
  */
@@ -295,18 +336,6 @@ rspamd_set_logger (enum rspamd_log_type type, enum process_type ptype, struct rs
        }
 }
 
-gint
-reopen_log (rspamd_logger_t *rspamd_log)
-{
-       close_log (rspamd_log);
-       if (open_log (rspamd_log) == 0) {
-               msg_info ("log file reopened");
-               return 0;
-       }
-
-       return -1;
-}
-
 /**
  * Used after fork() for updating structure params
  */
index f44dc56d96020780762cd472e5e84be4cbf4f96e..e25d6bfff2a1d3b9d39f192d6c213495f3661933 100644 (file)
@@ -28,6 +28,20 @@ void close_log (rspamd_logger_t *logger);
  * Close and open log again
  */
 gint reopen_log (rspamd_logger_t *logger);
+
+/**
+ * Open log file or initialize other structures for privileged processes
+ */
+gint open_log_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid);
+/**
+ * Close log file or destroy other structures for privileged processes
+ */
+void close_log_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid);
+/**
+ * Close and open log again for privileged processes
+ */
+gint reopen_log_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid);
+
 /**
  * Set log pid
  */
index f91bf9b34500811785f89697eb3fa6192076cc95..03d3839cd6661e2fc9ac1874c4f06ac8ecaf3ef9 100644 (file)
@@ -191,35 +191,59 @@ read_cmd_line (gint argc, gchar **argv, struct config_file *cfg)
        cfg->pid_file = rspamd_pidfile;
 }
 
+/* Detect privilleged mode */
 static void
-drop_priv (struct config_file *cfg)
+detect_priv (struct rspamd_main *rspamd)
 {
        struct passwd                  *pwd;
        struct group                   *grp;
+       uid_t                           euid;
 
-       if (geteuid () == 0 && cfg->rspamd_user) {
-               pwd = getpwnam (cfg->rspamd_user);
+       euid = geteuid ();
+
+       if (euid == 0) {
+               if (!rspamd->cfg->rspamd_user) {
+                       msg_err ("cannot run rspamd workers as root user, please add -u and -g options to select a proper unprivilleged user");
+                       exit (EXIT_FAILURE);
+               }
+
+               rspamd->is_privilleged = TRUE;
+               pwd = getpwnam (rspamd->cfg->rspamd_user);
                if (pwd == NULL) {
                        msg_err ("user specified does not exists (%s), aborting", strerror (errno));
                        exit (-errno);
                }
-               if (cfg->rspamd_group) {
-                       grp = getgrnam (cfg->rspamd_group);
+               if (rspamd->cfg->rspamd_group) {
+                       grp = getgrnam (rspamd->cfg->rspamd_group);
                        if (grp == NULL) {
                                msg_err ("group specified does not exists (%s), aborting", strerror (errno));
                                exit (-errno);
                        }
-                       if (setgid (grp->gr_gid) == -1) {
-                               msg_err ("cannot setgid to %d (%s), aborting", (gint)grp->gr_gid, strerror (errno));
-                               exit (-errno);
-                       }
-                       if (initgroups (cfg->rspamd_user, grp->gr_gid) == -1) {
-                               msg_err ("initgroups failed (%s), aborting", strerror (errno));
-                               exit (-errno);
-                       }
+                       rspamd->workers_gid = grp->gr_gid;
+               }
+               rspamd->workers_uid = pwd->pw_uid;
+       }
+       else {
+               rspamd->is_privilleged = FALSE;
+               rspamd->workers_uid = -1;
+               rspamd->workers_gid = -1;
+       }
+}
+
+static void
+drop_priv (struct rspamd_main *rspamd)
+{
+       if (rspamd->is_privilleged) {
+               if (setgid (rspamd->workers_gid) == -1) {
+                       msg_err ("cannot setgid to %d (%s), aborting", (gint)rspamd->workers_gid, strerror (errno));
+                       exit (-errno);
+               }
+               if (initgroups (rspamd->cfg->rspamd_user, rspamd->workers_gid) == -1) {
+                       msg_err ("initgroups failed (%s), aborting", strerror (errno));
+                       exit (-errno);
                }
-               if (setuid (pwd->pw_uid) == -1) {
-                       msg_err ("cannot setuid to %d (%s), aborting", (gint)pwd->pw_uid, strerror (errno));
+               if (setuid (rspamd->workers_uid) == -1) {
+                       msg_err ("cannot setuid to %d (%s), aborting", (gint)rspamd->workers_uid, strerror (errno));
                        exit (-errno);
                }
        }
@@ -229,7 +253,7 @@ static void
 config_logger (struct rspamd_main *rspamd, gboolean is_fatal)
 {
        rspamd_set_logger (rspamd->cfg->log_type, TYPE_MAIN, rspamd);
-       if (open_log (rspamd->logger) == -1) {
+       if (open_log_priv (rspamd->logger, rspamd->workers_uid, rspamd->workers_gid) == -1) {
                if (is_fatal) {
                        fprintf (stderr, "Fatal error, cannot open logfile, exiting\n");
                        exit (EXIT_FAILURE);
@@ -346,7 +370,7 @@ fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf)
                        /* Update pid for logging */
                        update_log_pid (cf->type, rspamd->logger);
                        /* Drop privilleges */
-                       drop_priv (rspamd->cfg);
+                       drop_priv (rspamd);
                        /* Set limits */
                        set_worker_limits (cf);
                        switch (cf->type) {
@@ -887,6 +911,7 @@ main (gint argc, gchar **argv, gchar **env)
        (void)open_log (rspamd_main->logger);
        g_log_set_default_handler (rspamd_glib_log_function, rspamd_main->logger);
 
+       detect_priv (rspamd_main);
        init_lua (rspamd_main->cfg);
 
        /* Init counters */
@@ -1082,7 +1107,7 @@ main (gint argc, gchar **argv, gchar **env)
                }
                if (do_restart) {
                        do_restart = 0;
-                       reopen_log (rspamd_main->logger);
+                       reopen_log_priv (rspamd_main->logger, rspamd_main->workers_uid, rspamd_main->workers_gid);
                        msg_info ("rspamd " RVERSION " is restarting");
                        g_hash_table_foreach (rspamd_main->workers, kill_old_workers, NULL);
                        remove_all_maps ();
@@ -1091,7 +1116,7 @@ main (gint argc, gchar **argv, gchar **env)
                }
                if (do_reopen_log) {
                        do_reopen_log = 0;
-                       reopen_log (rspamd_main->logger);
+                       reopen_log_priv (rspamd_main->logger, rspamd_main->workers_uid, rspamd_main->workers_gid);
                        g_hash_table_foreach (rspamd_main->workers, reopen_log_handler, NULL);
                }
                if (got_alarm) {
index c111752da1279a20a8404036aa0fa81dac919561..7ff76afb37913d3b749bcdd00206c9cad3e4831a 100644 (file)
@@ -97,6 +97,9 @@ struct rspamd_main {
        statfile_pool_t *statfile_pool;                                                         /**< shared statfiles pool                                                      */
        GHashTable *workers;                                        /**< workers pool indexed by pid                    */
        rspamd_logger_t *logger;
+       uid_t workers_uid;                                                                                      /**< worker's uid running to                                            */
+       gid_t workers_gid;                                                                                      /**< worker's gid running to                                            */
+       gboolean is_privilleged;                                                                        /**< true if run in privilleged mode                            */
 };
 
 struct counter_data {