diff --git a/src/anvil/main.c b/src/anvil/main.c index e1a4062f80..becfbd4acc 100644 --- a/src/anvil/main.c +++ b/src/anvil/main.c @@ -65,7 +65,7 @@ int main(int argc, char *argv[]) i_fatal("Error reading configuration: %s", error); master_service_init_log(master_service, "anvil: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); anvil_restarted = getenv("ANVIL_RESTARTED") != NULL; diff --git a/src/auth/main.c b/src/auth/main.c index e6dd2e8350..7221e5e1e4 100644 --- a/src/auth/main.c +++ b/src/auth/main.c @@ -209,7 +209,7 @@ static void main_preinit(void) auth_token_init(); /* Password lookups etc. may require roots, allow it. */ - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); } diff --git a/src/config/main.c b/src/config/main.c index 6eba1b7dcc..14caa51c9b 100644 --- a/src/config/main.c +++ b/src/config/main.c @@ -23,7 +23,7 @@ int main(int argc, char *argv[]) return FATAL_DEFAULT; master_service_init_log(master_service, "config: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); config_parse_load_modules(); diff --git a/src/dict/main.c b/src/dict/main.c index 2491824fcf..f298235e6b 100644 --- a/src/dict/main.c +++ b/src/dict/main.c @@ -82,7 +82,7 @@ static void main_preinit(void) dict_driver_register(&dict_driver_cdb); #endif - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); } diff --git a/src/director/main.c b/src/director/main.c index 46ba6e8c75..96cea27864 100644 --- a/src/director/main.c +++ b/src/director/main.c @@ -291,7 +291,7 @@ static void main_preinit(void) i_fatal("Invalid value for director_mail_servers setting"); director->orig_config_hosts = mail_hosts_dup(director->mail_hosts); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); } diff --git a/src/dns/dns-client.c b/src/dns/dns-client.c index 48b9154aa4..6d685676db 100644 --- a/src/dns/dns-client.c +++ b/src/dns/dns-client.c @@ -135,7 +135,7 @@ int main(int argc, char *argv[]) return FATAL_DEFAULT; master_service_init_log(master_service, "dns-client: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); master_service_init_finish(master_service); diff --git a/src/doveadm/main.c b/src/doveadm/main.c index bdb9333212..e73e51b27b 100644 --- a/src/doveadm/main.c +++ b/src/doveadm/main.c @@ -64,7 +64,7 @@ void help_ver2(const struct doveadm_cmd_ver2 *cmd) static void main_preinit(void) { - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); } diff --git a/src/imap-hibernate/main.c b/src/imap-hibernate/main.c index c7d15a1744..0c24a116e6 100644 --- a/src/imap-hibernate/main.c +++ b/src/imap-hibernate/main.c @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) i_fatal("Error reading configuration: %s", error); master_service_init_log(master_service, "imap-hibernate: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); imap_clients_init(); diff --git a/src/indexer/indexer-worker.c b/src/indexer/indexer-worker.c index fed101e07e..32ee9d8cdc 100644 --- a/src/indexer/indexer-worker.c +++ b/src/indexer/indexer-worker.c @@ -40,7 +40,7 @@ static void drop_privileges(void) (void)master_service_settings_read(master_service, &input, &output, &error); } - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); } int main(int argc, char *argv[]) diff --git a/src/indexer/indexer.c b/src/indexer/indexer.c index 059feebe88..9b02d22d10 100644 --- a/src/indexer/indexer.c +++ b/src/indexer/indexer.c @@ -122,7 +122,7 @@ int main(int argc, char *argv[]) set = master_service_settings_get(master_service); master_service_init_log(master_service, "indexer: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); master_service_set_idle_die_callback(master_service, idle_die); diff --git a/src/ipc/main.c b/src/ipc/main.c index 1d7b599a5a..b0a9cd84b2 100644 --- a/src/ipc/main.c +++ b/src/ipc/main.c @@ -46,7 +46,7 @@ int main(int argc, char *argv[]) i_fatal("Error reading configuration: %s", error); master_service_init_log(master_service, "ipc: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); ipc_groups_init(); master_service_init_finish(master_service); diff --git a/src/lib-program-client/program-client-local.c b/src/lib-program-client/program-client-local.c index c20686af4d..b8eee657b0 100644 --- a/src/lib-program-client/program-client-local.c +++ b/src/lib-program-client/program-client-local.c @@ -235,8 +235,9 @@ int program_client_local_connect(struct program_client *pclient) /* if we want to allow root, then we will not drop root privileges */ - restrict_access(&pclient->set.restrict_set, pclient->set.home, - !pclient->set.allow_root); + restrict_access(&pclient->set.restrict_set, + pclient->set.allow_root ? RESTRICT_ACCESS_FLAG_ALLOW_ROOT : 0, + pclient->set.home); exec_child(pclient->path, pclient->args, &pclient->envs, fd_in[0], fd_out[1], child_extra_fds, diff --git a/src/lib-storage/mail-storage-service.c b/src/lib-storage/mail-storage-service.c index 1d0467c98a..8102229504 100644 --- a/src/lib-storage/mail-storage-service.c +++ b/src/lib-storage/mail-storage-service.c @@ -640,8 +640,8 @@ service_drop_privileges(struct mail_storage_service_user *user, disallow_root = FALSE; } if (!setenv_only) { - restrict_access(&rset, *priv->home == '\0' ? NULL : priv->home, - disallow_root); + restrict_access(&rset, disallow_root ? 0 : RESTRICT_ACCESS_FLAG_ALLOW_ROOT, + *priv->home == '\0' ? NULL : priv->home); } else { restrict_access_set_env(&rset); } diff --git a/src/lib/restrict-access.c b/src/lib/restrict-access.c index 72768f184f..1d5ed5c39c 100644 --- a/src/lib/restrict-access.c +++ b/src/lib/restrict-access.c @@ -256,10 +256,11 @@ get_setuid_error_str(const struct restrict_access_settings *set, uid_t target_ui } void restrict_access(const struct restrict_access_settings *set, - const char *home, bool disallow_root) + enum restrict_access_flags flags, const char *home) { bool is_root, have_root_group, preserve_groups = FALSE; bool allow_root_gid; + bool allow_root = (flags & RESTRICT_ACCESS_FLAG_ALLOW_ROOT) != 0; uid_t target_uid = set->uid; is_root = geteuid() == 0; @@ -345,9 +346,9 @@ void restrict_access(const struct restrict_access_settings *set, } /* verify that we actually dropped the privileges */ - if ((target_uid != (uid_t)-1 && target_uid != 0) || disallow_root) { + if ((target_uid != (uid_t)-1 && target_uid != 0) || !allow_root) { if (setuid(0) == 0) { - if (disallow_root && + if (!allow_root && (target_uid == 0 || target_uid == (uid_t)-1)) i_fatal("This process must not be run as root"); @@ -448,12 +449,12 @@ void restrict_access_get_env(struct restrict_access_settings *set_r) set_r->chroot_dir = null_if_empty(getenv("RESTRICT_CHROOT")); } -void restrict_access_by_env(const char *home, bool disallow_root) +void restrict_access_by_env(enum restrict_access_flags flags, const char *home) { struct restrict_access_settings set; restrict_access_get_env(&set); - restrict_access(&set, home, disallow_root); + restrict_access(&set, flags, home); /* clear the environment, so we don't fail if we get back here */ env_remove("RESTRICT_SETUID"); diff --git a/src/lib/restrict-access.h b/src/lib/restrict-access.h index de26a48ff4..6f7f476f3e 100644 --- a/src/lib/restrict-access.h +++ b/src/lib/restrict-access.h @@ -1,6 +1,13 @@ #ifndef RESTRICT_ACCESS_H #define RESTRICT_ACCESS_H +enum restrict_access_flags { + /* If flags given to restrict_access() include + * RESTRICT_ACCESS_FLAG_ALLOW_ROOT, we won't kill + * ourself when we have root privileges. */ + RESTRICT_ACCESS_FLAG_ALLOW_ROOT = 1, +}; + struct restrict_access_settings { /* UID to use, or (uid_t)-1 if you don't want to change it */ uid_t uid; @@ -37,16 +44,18 @@ void restrict_access_init(struct restrict_access_settings *set); /* Restrict access as specified by the settings. If home is not NULL, it's chdir()ed after chrooting, otherwise it chdirs to / (the chroot). */ void restrict_access(const struct restrict_access_settings *set, - const char *home, bool disallow_root) ATTR_NULL(2); + enum restrict_access_flags flags, const char *home) + ATTR_NULL(3); /* Set environment variables so they can be read with restrict_access_by_env(). */ void restrict_access_set_env(const struct restrict_access_settings *set); /* Read restrict_access_set_env() environments back into struct. */ void restrict_access_get_env(struct restrict_access_settings *set_r); /* Read restrictions from environment and call restrict_access(). - If disallow_roots is TRUE, we'll kill ourself if we didn't have the - environment settings. */ -void restrict_access_by_env(const char *home, bool disallow_root) ATTR_NULL(1); + If flags do not include RESTRICT_ACCESS_FLAG_ALLOW_ROOT, we'll kill ourself + unless the RESTRICT_* environments caused root privileges to be dropped */ +void restrict_access_by_env(enum restrict_access_flags flags, + const char *home) ATTR_NULL(2); /* Return the chrooted directory if restrict_access*() chrooted, otherwise NULL. */ diff --git a/src/lmtp/main.c b/src/lmtp/main.c index dc6d467836..b73a5e290a 100644 --- a/src/lmtp/main.c +++ b/src/lmtp/main.c @@ -63,7 +63,7 @@ static void drop_privileges(void) if (master_service_settings_read(master_service, &input, &output, &error) < 0) i_fatal("Error reading configuration: %s", error); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); } static void main_init(void) diff --git a/src/log/main.c b/src/log/main.c index 6fd2a69ec5..8e6e5b875a 100644 --- a/src/log/main.c +++ b/src/log/main.c @@ -79,7 +79,7 @@ int main(int argc, char *argv[]) verbose_proctitle = master_service_settings_get(master_service)->verbose_proctitle; - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); /* logging should never die if there are some clients */ diff --git a/src/login-common/main.c b/src/login-common/main.c index cbdaf65ba3..de0b2b0992 100644 --- a/src/login-common/main.c +++ b/src/login-common/main.c @@ -428,7 +428,7 @@ static void main_preinit(void) login_load_modules(); - restrict_access_by_env(NULL, TRUE); + restrict_access_by_env(0, NULL); if (login_debug) restrict_access_allow_coredumps(TRUE); initial_service_count = master_service_get_service_count(master_service); diff --git a/src/master/service-process.c b/src/master/service-process.c index cc804350a3..cdcc46520e 100644 --- a/src/master/service-process.c +++ b/src/master/service-process.c @@ -193,7 +193,9 @@ drop_privileges(struct service *service) restrict_access_set_env(&rset); if (service->set->drop_priv_before_exec) { disallow_root = service->type == SERVICE_TYPE_LOGIN; - restrict_access(&rset, NULL, disallow_root); + restrict_access(&rset, + disallow_root ? 0 : RESTRICT_ACCESS_FLAG_ALLOW_ROOT, + NULL); } } diff --git a/src/old-stats/main.c b/src/old-stats/main.c index 038c4ec75f..34bd8efc13 100644 --- a/src/old-stats/main.c +++ b/src/old-stats/main.c @@ -38,7 +38,7 @@ static void main_preinit(void) modules = module_dir_load(STATS_MODULE_DIR, NULL, &mod_set); module_dir_init(modules); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); } diff --git a/src/plugins/quota/quota-status.c b/src/plugins/quota/quota-status.c index 2adfdfb4ad..431a980e67 100644 --- a/src/plugins/quota/quota-status.c +++ b/src/plugins/quota/quota-status.c @@ -204,7 +204,7 @@ static const struct connection_vfuncs client_vfuncs = { static void main_preinit(void) { - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); } diff --git a/src/replication/aggregator/aggregator.c b/src/replication/aggregator/aggregator.c index 2942fb5ad7..66f82d6139 100644 --- a/src/replication/aggregator/aggregator.c +++ b/src/replication/aggregator/aggregator.c @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) main_preinit(); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); master_service_init_finish(master_service); diff --git a/src/replication/replicator/replicator.c b/src/replication/replicator/replicator.c index b5074d3481..24bacc2bce 100644 --- a/src/replication/replicator/replicator.c +++ b/src/replication/replicator/replicator.c @@ -102,7 +102,7 @@ int main(int argc, char *argv[]) i_fatal("Error reading configuration: %s", error); master_service_init_log(master_service, "replicator: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); /* finish init before we get list of users from auth, because that can take long enough for master process to kill us otherwise. */ diff --git a/src/stats/main.c b/src/stats/main.c index 702f6b3ce1..9264ae09d0 100644 --- a/src/stats/main.c +++ b/src/stats/main.c @@ -42,7 +42,7 @@ static void client_connected(struct master_service_connection *conn) static void main_preinit(void) { - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); } diff --git a/src/util/rawlog.c b/src/util/rawlog.c index 7305c122dc..34ddb47145 100644 --- a/src/util/rawlog.c +++ b/src/util/rawlog.c @@ -356,7 +356,7 @@ static void rawlog_open(enum rawlog_flags flags) } i_close_fd(&sfd[1]); - restrict_access_by_env(getenv("HOME"), TRUE); + restrict_access_by_env(0, getenv("HOME")); process_title_set(t_strdup_printf("[%s:%s rawlog]", getenv("USER"), dec2str(getppid()))); diff --git a/src/util/script-login.c b/src/util/script-login.c index ea7ffd5e4c..0954b47c50 100644 --- a/src/util/script-login.c +++ b/src/util/script-login.c @@ -121,7 +121,7 @@ static void client_connected(struct master_service_connection *conn) mail_storage_service_restrict_setenv(service_ctx, user); /* we can't exec anything in a chroot */ env_remove("RESTRICT_CHROOT"); - restrict_access_by_env(getenv("HOME"), TRUE); + restrict_access_by_env(0, getenv("HOME")); } if (dup2(fd, STDIN_FILENO) < 0) @@ -217,7 +217,7 @@ int main(int argc, char *argv[]) if (!drop_to_userdb_privileges && (flags & MASTER_SERVICE_FLAG_STANDALONE) == 0) { /* drop to privileges defined by service settings */ - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); } master_service_init_finish(master_service); diff --git a/src/util/script.c b/src/util/script.c index 38cdfeeceb..5f88cc9075 100644 --- a/src/util/script.c +++ b/src/util/script.c @@ -269,7 +269,7 @@ int main(int argc, char *argv[]) master_service_init_log(master_service, "script: "); if (argv[0] == NULL) i_fatal("Missing script path"); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); master_service_init_finish(master_service); diff --git a/src/util/tcpwrap.c b/src/util/tcpwrap.c index d060a8fcb1..8d5d20bd9a 100644 --- a/src/util/tcpwrap.c +++ b/src/util/tcpwrap.c @@ -114,7 +114,7 @@ int main(int argc, char *argv[]) return FATAL_DEFAULT; master_service_init_log(master_service, "tcpwrap: "); - restrict_access_by_env(NULL, FALSE); + restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); restrict_access_allow_coredumps(TRUE); master_service_init_finish(master_service);