master-settings.c revision b6d3625636be481e28ad8f39d138344fe751b76c
/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
#include "common.h"
#include "array.h"
#include "str.h"
#include "istream.h"
#include "env-util.h"
#include "fd-close-on-exec.h"
#include "safe-mkdir.h"
#include "mkdir-parents.h"
#include "unlink-directory.h"
#include "syslog-util.h"
#include "mail-process.h"
#include "master-login-interface.h"
#include "settings-parser.h"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <signal.h>
#include <pwd.h>
#include <grp.h>
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
#endif
extern struct setting_parser_info master_auth_setting_parser_info;
extern struct setting_parser_info master_setting_parser_info;
extern struct setting_parser_info master_auth_socket_setting_parser_info;
static struct setting_define master_auth_socket_master_setting_defines[] = {
};
static struct master_auth_socket_unix_settings master_auth_socket_master_default_settings = {
};
};
static struct setting_define master_auth_socket_setting_defines[] = {
};
};
static struct setting_define master_auth_setting_defines[] = {
};
static struct master_auth_settings master_auth_default_settings = {
/* .. */
};
};
static struct setting_define master_setting_defines[] = {
/* common */
/* general */
/* login */
/* mail */
/* dict */
};
struct master_settings master_default_settings = {
/* common */
/* general */
/* login */
/* mail */
MEMBER(last_valid_uid) 0,
MEMBER(last_valid_gid) 0,
/* dict */
/* .. */
};
struct setting_parser_info master_setting_parser_info = {
};
#ifdef HAVE_MODULES
static const char *
{
/* FIXME: pretty ugly code just for getting the capability
automatically */
static const char *args[] = {
"uid=65534",
"gid=65534",
"home=/tmp",
};
struct mail_login_request request;
char buf[4096];
unsigned int pos;
if (uid != 0) {
/* use the current user */
}
i_error("pipe() failed: %m");
return NULL;
}
&pid);
if (login_status != MASTER_LOGIN_STATUS_OK) {
return NULL;
}
alarm(5);
i_fatal("%s dump-capability process %d got stuck",
}
alarm(0);
if (status != 0) {
if (WIFSIGNALED(status)) {
i_error("%s dump-capability process "
"killed with signal %d",
} else {
i_error("%s dump-capability process returned %d",
status);
}
return NULL;
}
pos = 0;
if (ret < 0) {
return NULL;
}
i_error("%s dump-capability: Couldn't read capability "
return NULL;
}
}
{
static const char *generated_capability = NULL;
if (generated_capability != NULL) {
/* Reloading configuration. Don't try to execute the imap
process again. Too risky and the wait() call below will
break it anyway. Just use the previous capability list we
already had generated. */
return TRUE;
}
if (generated_capability == NULL)
return FALSE;
return TRUE;
}
#endif
{
}
}
{
char *p;
if (*p == '\0')
return TRUE;
}
return FALSE;
return TRUE;
}
{
char *p;
if (*p == '\0')
return TRUE;
}
return FALSE;
return TRUE;
}
{
return FALSE;
}
i_error("All login process users must belong to same group "
return FALSE;
}
return TRUE;
}
struct master_auth_settings *auth)
{
struct master_auth_socket_settings *const *sockets;
unsigned int i, count;
return FALSE;
}
i_error("login_user %s (uid %s) must not be same as auth_user",
return FALSE;
}
i_error("auth_executable: Can't use %s: %m",
return FALSE;
}
i_error("Can't access auth chroot directory %s: %m",
return FALSE;
}
for (i = 0; i < count; i++) {
i_error("Currently auth process count must be 1 if "
"you're using auth socket listeners.");
return FALSE;
}
}
return TRUE;
}
static const char *get_directory(const char *path)
{
char *str, *p;
if (p == NULL)
return ".";
else {
*p = '\0';
return str;
}
}
{
/* we're probably using this with --exec-mail */
return TRUE;
}
return FALSE;
} else {
return FALSE;
}
return TRUE;
}
{
struct master_auth_settings *const *auths;
struct master_auth_socket_settings *const *sockets;
for (i = 0; i < count; i++) {
return TRUE;
}
return FALSE;
}
{
struct master_auth_settings *const *auths;
const char *const *tmp;
unsigned int i, count;
for (i = 0; i < count; i++) {
return TRUE;
}
}
return FALSE;
}
{
unsigned int prefix_len;
return;
}
continue;
continue;
str_truncate(str, 0);
continue;
}
continue;
/* try to avoid unlinking sockets if someone's already
listening in them. do this only at startup, because
when SIGHUPing a child process might catch the new
connection before it notices that it's supposed
to die. null_fd == -1 check is a bit kludgy, but works.. */
if (null_fd == -1) {
i_fatal("Dovecot is already running? "
"Socket already exists: %s",
}
}
}
}
{
const char *dir;
int facility;
if (!get_login_uid(set))
return FALSE;
return FALSE;
}
}
return FALSE;
}
}
&set->mail_priv_gid_t)) {
i_error("Non-existing mail_privileged_group: %s",
return FALSE;
}
}
i_error("mail_executable: Can't use %s: %m",
return FALSE;
}
i_error("log_path: Can't write to directory %s: %m",
dir);
return FALSE;
}
}
i_error("info_log_path: Can't write to directory %s: %m",
dir);
return FALSE;
}
}
i_error("syslog_facility: Unknown value: %s",
return FALSE;
}
return FALSE;
}
#ifndef HAVE_SSL
return FALSE;
}
#endif
i_warning("There is no way to login to this server: "
"disable_plaintext_auth=yes, ssl=no, "
"no non-plaintext auth mechanisms.");
}
i_error("max_mail_processes must be at least 1");
return FALSE;
}
if (set->last_valid_uid != 0 &&
i_error("first_valid_uid can't be larger than last_valid_uid");
return FALSE;
}
if (set->last_valid_gid != 0 &&
i_error("first_valid_gid can't be larger than last_valid_gid");
return FALSE;
}
i_error("mail_drop_priv_before_exec=yes and mail_chroot "
"don't work together");
return FALSE;
}
i_error("login_executable: Can't use %s: %m",
return FALSE;
}
i_error("login_processes_count must be at least 1");
return FALSE;
}
#if 0 //FIXME
i_error("mail_nfs_index=yes requires mmap_disable=yes");
return FALSE;
}
i_error("mail_nfs_index=yes requires fsync_disable=no");
return FALSE;
}
#ifdef HAVE_MODULES
i_error("mail_plugin_dir: Can't access directory: %s: %m",
return FALSE;
}
#else
i_error("mail_plugins: Plugin support wasn't built into Dovecot, "
return FALSE;
}
#endif
#endif
return TRUE;
}
{
deleted. */
return FALSE;
}
/* allow base_dir to be a symlink, so don't use lstat() */
return FALSE;
}
/* remove auth worker sockets left by unclean exits */
/* Make sure our permanent state directory exists */
return FALSE;
}
if (!settings_have_connect_sockets(set)) {
/* we are not using external authentication, so make sure the
login directory exists with correct permissions and it's
empty. with external auth we wouldn't want to delete
existing sockets or break the permissions required by the
auth server. */
i_warning("Corrected permissions for login directory "
}
}
#ifdef HAVE_MODULES
if (!get_imap_capability(set))
return FALSE;
}
#endif
return TRUE;
}
static bool
{
/* fix relative paths */
if (nochecks)
return TRUE;
if (!settings_verify(set))
return FALSE;
}
static void
{
#ifdef HAVE_SETRLIMIT
unsigned int fd_count = 0;
return;
/* count only log pipes needed for login and mail processes. we need
more, but they're the ones that can use up most of the fds */
i_warning("fd limit %d is lower than what Dovecot can use under "
"full load (more than %u). Either grow the limit or "
"change login_max_processes_count and "
"max_mail_processes master_settings",
}
#endif
}
static void
{
const char *p, *line;
for (p = input; *p != '\n'; p++) {
str_truncate(str, 0);
for (; *p != '='; p++) {
}
for (; *p != '\n'; p++) {
i_assert(*p != '\0');
str_append_c(str, *p);
}
}
}
struct master_settings **set_r)
{
struct setting_parser_context *parser;
int ret;
}
return ret;
}
int master_settings_read(const char *path,
struct master_server_settings **set_r)
{
struct master_server_settings *set;
return -1;
return -1;
return -1;
return 0;
}
{
struct master_auth_settings *const *auths;
unsigned int i, count;
i_error("protocols: No protocols given in configuration file");
return FALSE;
}
/* --exec-mail is used if nochecks=TRUE. Allow it regardless
of what's in protocols setting. */
return FALSE;
}
} else {
return FALSE;
}
else {
return FALSE;
}
return FALSE;
if (!nochecks) {
if (count == 0) {
i_error("Missing auth section");
return FALSE;
}
for (i = 0; i < count; i++) {
return FALSE;
}
}
if (!nochecks)
/* settings ok, swap them */
master_set = set;
return TRUE;
}
{
const char *const *sets;
unsigned int i, count;
for (i = 0; i < count; i++)
}
void master_settings_init(void)
{
}
void master_settings_deinit(void)
{
}