mail-storage-service.c revision 1b04762685272a53643ac2179939537a44c7c044
/* Copyright (c) 2009 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "hostpid.h"
#include "module-dir.h"
#include "restrict-access.h"
#include "str.h"
#include "var-expand.h"
#include "dict.h"
#include "settings-parser.h"
#include "auth-master.h"
#include "master-service-private.h"
#include "master-service-settings.h"
#include "mail-user.h"
#include "mail-namespace.h"
#include "mail-storage.h"
#include "mail-storage-service.h"
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
struct mail_storage_service_multi_ctx {
struct master_service *service;
unsigned int modules_initialized:1;
};
static void
{
const char *str;
}
}
const char *dir)
{
const char *const *chroot_dirs;
if (*dir == '\0')
return FALSE;
return FALSE;
while (*chroot_dirs != NULL) {
if (**chroot_dirs != '\0' &&
return TRUE;
chroot_dirs++;
}
return FALSE;
}
static int
const struct mail_user_settings *user_set,
const struct auth_user_reply *reply,
const char **system_groups_user_r, const char **error_r)
{
unsigned int i, count;
int ret = 0;
*error_r = "userdb returned 0 as uid";
return -1;
}
}
"userdb returned invalid chroot directory: %s "
"(see valid_chroot_dirs setting)",
return -1;
}
}
continue;
}
else
/* assume it's a plugin setting */
}
} T_END;
if (ret < 0) {
}
return ret;
}
static int
const struct mail_user_settings *user_set,
const char **user, const char **system_groups_user_r,
const char **error_r)
{
struct auth_master_connection *conn;
struct auth_user_reply reply;
unsigned int len;
int ret;
if (ret > 0) {
&system_groups_user, error_r) < 0)
ret = -1;
} else {
if (ret == 0)
*error_r = "unknown user";
else
*error_r = "userdb lookup failed";
}
*user));
}
pool_unref(&pool);
return ret;
}
{
char *p;
if (*p == '\0')
return TRUE;
}
return FALSE;
return TRUE;
}
{
char *p;
if (*p == '\0')
return TRUE;
}
return FALSE;
return TRUE;
}
static void
const char *system_groups_user, const char *home,
bool disallow_root, bool keep_setuid_root)
{
struct restrict_access_settings rset;
current_euid = geteuid();
(set->last_valid_uid != 0 &&
i_fatal("Mail access for users with UID %s "
"not permitted (see first_valid_uid in config file).",
}
}
(set->last_valid_gid != 0 &&
i_fatal("Mail access for users with GID %s "
"not permitted (see first_valid_gid in config file).",
}
}
}
/* we can't chroot if we want to switch between users. there's not
much point either (from security point of view) */
if (disallow_root &&
i_fatal("Mail access not allowed for root");
if (current_euid != 0) {
/* we're changing the UID, switch back to root first */
if (seteuid(0) < 0)
i_fatal("seteuid(0) failed: %m");
}
}
if (keep_setuid_root) {
if (seteuid(setuid_uid) < 0)
}
}
static void
const struct setting_parser_info *set_root,
bool preserve_home)
{
const char *error;
(void)umask(0077);
/* read settings after registering storages so they can have their
own setting definitions too */
preserve_home, &error) < 0)
}
static int
const struct mail_user_settings *user_set,
struct mail_user **mail_user_r,
const char **error_r)
{
const struct mail_storage_settings *mail_set;
if (mail_set->mail_debug) {
i_info("Effective uid=%s, gid=%s, home=%s",
}
/* If possible chdir to home directory, so that core file
could be written in case we crash. */
if (*home != '\0') {
else if (mail_set->mail_debug)
}
}
if (*home != '\0')
return -1;
}
return -1;
}
*mail_user_r = mail_user;
return 0;
}
static const struct var_expand_table *
{
static struct var_expand_table static_tab[] = {
};
struct var_expand_table *tab;
return tab;
}
static const char *
const char *str)
{
if (*str == SETTING_STRVAR_EXPANDED[0])
return str + 1;
}
struct mail_user *
const struct setting_parser_info *set_root,
{
const struct master_service_settings *set;
const struct mail_user_settings *user_set;
const struct mail_storage_settings *mail_set;
void **sets;
unsigned int len;
bool userdb_lookup;
if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
/* now that we've read settings, we can set up logging */
if (userdb_lookup) {
/* userdb lookup may change settings, do it as soon as
possible. */
&error) <= 0)
}
/* variable strings are expanded in mail_user_init(),
but we need the home sooner so do it separately here. */
if (!userdb_lookup) {
}
}
/* If chroot ends with "/.", strip chroot dir from home dir */
}
if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS) == 0) {
(flags & MAIL_STORAGE_SERVICE_FLAG_DISALLOW_ROOT) != 0,
FALSE);
}
/* privileges are now dropped */
return mail_user;
}
void mail_storage_service_deinit_user(void)
{
}
struct mail_storage_service_multi_ctx *
const struct setting_parser_info *set_root,
{
struct mail_storage_service_multi_ctx *ctx;
const struct master_service_settings *set;
const struct mail_user_settings *user_set;
const struct mail_storage_settings *mail_set;
void **sets;
/* do all the global initialization. delay initializing plugins until
we drop privileges the first time. */
return ctx;
}
const char *user,
struct mail_user **mail_user_r,
const char **error_r)
{
const struct mail_user_settings *user_set;
const struct mail_storage_settings *mail_set;
void **sets;
unsigned int len;
int ret;
error_r);
if (ret <= 0)
return ret;
} else {
}
/* variable strings are expanded in mail_user_init(),
but we need the home sooner so do it separately here. */
TRUE);
}
if (!ctx->modules_initialized) {
/* privileges dropped for the first time. initialize the
modules now to avoid code running as root. */
}
/* we couldn't do chrooting, so if chrooting was enabled fix
the home directory */
/* home dir already contains the chroot dir */
} else if (len > 0) {
}
mail_user_r, error_r) < 0)
return -1;
return 1;
}
{
}
{
void **sets;
return sets[1];
}