[dovecot-cvs]
dovecot/src/master auth-process.c,1.46,1.47 common.h,1.15,1.16
login-process.c,1.46,1.47 login-process.h,1.5,1.6
mail-process.c,1.24,1.25 mail-process.h,1.3,1.4 main.c,1.44,1.45
master-settings.c,1.20,1.21 master-settings.h,1.13,1.14
ssl-init.c,1.10,1.11
cras at procontrol.fi
cras at procontrol.fi
Thu Jul 10 07:04:09 EEST 2003
Update of /home/cvs/dovecot/src/master
In directory danu:/tmp/cvs-serv32098/src/master
Modified Files:
auth-process.c common.h login-process.c login-process.h
mail-process.c mail-process.h main.c master-settings.c
master-settings.h ssl-init.c
Log Message:
New configuration file code. Some syntax changes, but tries to be somewhat
backwards compatible. SIGHUP now reverts back to old configuration if it
detected errors in new one.
Index: auth-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/auth-process.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- auth-process.c 26 May 2003 15:26:29 -0000 1.46
+++ auth-process.c 10 Jul 2003 03:04:07 -0000 1.47
@@ -295,7 +295,7 @@
if (dup2(null_fd, 1) < 0)
i_fatal("login: dup2(1) failed: %m");
- child_process_init_env();
+ child_process_init_env(group->set->parent->defaults);
/* move login communication handle to 3. do it last so we can be
sure it's not closed afterwards. */
@@ -371,7 +371,8 @@
group->set = auth_set;
/* create socket for listening auth requests from login */
- path = t_strconcat(set->login_dir, "/", auth_set->name, NULL);
+ path = t_strconcat(auth_set->parent->defaults->login_dir, "/",
+ auth_set->name, NULL);
(void)unlink(path);
(void)umask(0117); /* we want 0660 mode for the socket */
@@ -382,9 +383,10 @@
fd_close_on_exec(group->listen_fd, TRUE);
/* set correct permissions */
- if (chown(path, geteuid(), set->login_gid) < 0) {
+ if (chown(path, geteuid(), auth_set->parent->defaults->login_gid) < 0) {
i_fatal("login: chown(%s, %s, %s) failed: %m",
- path, dec2str(geteuid()), dec2str(set->login_gid));
+ path, dec2str(geteuid()),
+ dec2str(auth_set->parent->defaults->login_gid));
}
group->next = process_groups;
@@ -401,7 +403,8 @@
group->processes = next;
}
- (void)unlink(t_strconcat(set->login_dir, "/", group->set->name, NULL));
+ (void)unlink(t_strconcat(group->set->parent->defaults->login_dir, "/",
+ group->set->name, NULL));
if (close(group->listen_fd) < 0)
i_error("close(auth group %s) failed: %m", group->set->name);
@@ -419,18 +422,28 @@
}
}
+static void auth_process_groups_create(struct server_settings *server)
+{
+ struct auth_settings *auth_set;
+
+ while (server != NULL) {
+ auth_set = server->auths;
+ for (; auth_set != NULL; auth_set = auth_set->next)
+ auth_process_group_create(auth_set);
+
+ server = server->next;
+ }
+}
+
static void
auth_processes_start_missing(void *context __attr_unused__)
{
- struct auth_settings *auth_set;
struct auth_process_group *group;
unsigned int count;
if (process_groups == NULL) {
/* first time here, create the groups */
- auth_set = set->auths;
- for (; auth_set != NULL; auth_set = auth_set->next)
- auth_process_group_create(auth_set);
+ auth_process_groups_create(settings_root);
}
for (group = process_groups; group != NULL; group = group->next) {
Index: common.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/common.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- common.h 15 Apr 2003 16:58:48 -0000 1.15
+++ common.h 10 Jul 2003 03:04:07 -0000 1.16
@@ -20,18 +20,9 @@
PROCESS_TYPE_MAX
};
-enum {
- FD_IMAP,
- FD_IMAPS,
- FD_POP3,
- FD_POP3S,
-
- FD_MAX
-};
-
extern struct ioloop *ioloop;
extern struct hash_table *pids;
-extern int null_fd, mail_fd[FD_MAX], inetd_login_fd;
+extern int null_fd, inetd_login_fd;
#define IS_INETD() \
(inetd_login_fd != -1)
@@ -46,7 +37,7 @@
#define PID_REMOVE_PROCESS_TYPE(pid) \
hash_remove(pids, POINTER_CAST(pid))
-void child_process_init_env(void);
+void child_process_init_env(struct settings *set);
/* misc */
#define VALIDATE_STR(str) \
Index: login-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/login-process.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- login-process.c 26 May 2003 15:26:29 -0000 1.46
+++ login-process.c 10 Jul 2003 03:04:07 -0000 1.47
@@ -17,25 +17,6 @@
#include <unistd.h>
#include <syslog.h>
-struct login_group {
- struct login_group *next;
-
- struct login_settings *set;
-
- unsigned int processes;
- unsigned int listening_processes;
- unsigned int wanted_processes_count;
-
- struct login_process *oldest_nonlisten_process;
- struct login_process *newest_nonlisten_process;
-
- const char *executable;
- const char *module_dir;
- unsigned int process_size;
- int process_type;
- int *listen_fd, *ssl_listen_fd;
-};
-
struct login_process {
struct login_group *group;
struct login_process *prev_nonlisten, *next_nonlisten;
@@ -71,36 +52,14 @@
static void login_process_unref(struct login_process *p);
static int login_process_init_group(struct login_process *p);
-static void login_group_create(struct login_settings *login_set)
+static void login_group_create(struct settings *set)
{
struct login_group *group;
- if (strstr(set->protocols, login_set->name) == NULL) {
- /* not enabled */
- return;
- }
-
group = i_new(struct login_group, 1);
- group->set = login_set;
-
- if (strcmp(login_set->name, "imap") == 0) {
- group->executable = set->imap_executable;
- group->process_size = set->imap_process_size;
- group->process_type = PROCESS_TYPE_IMAP;
- group->listen_fd = &mail_fd[FD_IMAP];
- group->ssl_listen_fd = &mail_fd[FD_IMAPS];
- group->module_dir = !set->imap_use_modules ? NULL :
- set->imap_modules;
- } else if (strcmp(login_set->name, "pop3") == 0) {
- group->executable = set->pop3_executable;
- group->process_size = set->pop3_process_size;
- group->process_type = PROCESS_TYPE_POP3;
- group->listen_fd = &mail_fd[FD_POP3];
- group->ssl_listen_fd = &mail_fd[FD_POP3S];
- group->module_dir = !set->pop3_use_modules ? NULL :
- set->pop3_modules;
- } else
- i_panic("Unknown login group name '%s'", login_set->name);
+ group->set = set;
+ group->process_type = set->protocol == MAIL_PROTOCOL_IMAP ?
+ PROCESS_TYPE_IMAP : PROCESS_TYPE_POP3;
group->next = login_groups;
login_groups = group;
@@ -123,11 +82,7 @@
struct login_group *group = request->process->group;
master_reply.success =
- create_mail_process(request->fd, &request->ip,
- group->executable,
- group->module_dir,
- group->process_size,
- group->process_type,
+ create_mail_process(group, request->fd, &request->ip,
reply, (const char *) data);
}
@@ -168,18 +123,29 @@
}
}
-static struct login_group *login_group_process_find(const char *name)
+static void login_process_groups_create(void)
{
- struct login_group *group;
- struct login_settings *login;
+ struct server_settings *server;
- if (login_groups == NULL) {
- for (login = set->logins; login != NULL; login = login->next)
- login_group_create(login);
+ for (server = settings_root; server != NULL; server = server->next) {
+ if (server->imap != NULL)
+ login_group_create(server->imap);
+ if (server->pop3 != NULL)
+ login_group_create(server->pop3);
}
+}
+
+static struct login_group *
+login_group_process_find(const char *name, enum mail_protocol protocol)
+{
+ struct login_group *group;
+
+ if (login_groups == NULL)
+ login_process_groups_create();
for (group = login_groups; group != NULL; group = group->next) {
- if (strcmp(group->set->name, name) == 0)
+ if (strcmp(group->set->server->name, name) == 0 &&
+ group->set->protocol == protocol)
return group;
}
@@ -189,8 +155,9 @@
static int login_process_read_group(struct login_process *p)
{
struct login_group *group;
- const char *name;
+ const char *name, *proto;
char buf[256];
+ enum mail_protocol protocol;
unsigned int len;
ssize_t ret;
@@ -201,7 +168,7 @@
else {
len = buf[0];
if (len >= sizeof(buf)) {
- i_error("login: Process name length too large");
+ i_error("login: Server name length too large");
return FALSE;
}
@@ -211,12 +178,29 @@
if (ret < 0)
i_error("login: read() failed: %m");
else if (len == 0 || (size_t)ret != len)
- i_error("login: Process name wasn't sent");
+ i_error("login: Server name wasn't sent");
else {
name = t_strndup(buf, len);
- group = login_group_process_find(name);
+ proto = strchr(buf, '/');
+ if (proto == NULL) {
+ i_error("login: Missing protocol from server name '%s'",
+ name);
+ return FALSE;
+ }
+ name = t_strdup_until(buf, proto++);
+
+ if (strcmp(proto, "imap") == 0)
+ protocol = MAIL_PROTOCOL_IMAP;
+ else if (strcmp(proto, "pop3") == 0)
+ protocol = MAIL_PROTOCOL_IMAP;
+ else {
+ i_error("login: Unknown protocol '%s'", proto);
+ return FALSE;
+ }
+
+ group = login_group_process_find(name, protocol);
if (group == NULL) {
- i_error("login: Unknown process group '%s'", name);
+ i_error("login: Unknown server name '%s'", name);
return FALSE;
}
@@ -384,12 +368,13 @@
static void login_process_init_env(struct login_group *group, pid_t pid)
{
- child_process_init_env();
+ struct settings *set = group->set;
+
+ child_process_init_env(set);
/* setup access environment - needs to be done after
clean_child_process() since it clears environment */
- restrict_access_set_env(group->set->user,
- group->set->uid, set->login_gid,
+ restrict_access_set_env(set->login_user, set->login_uid, set->login_gid,
set->login_chroot ? set->login_dir : NULL,
0, 0);
@@ -398,7 +383,8 @@
if (!set->ssl_disable) {
env_put(t_strconcat("SSL_CERT_FILE=",
set->ssl_cert_file, NULL));
- env_put(t_strconcat("SSL_KEY_FILE=", set->ssl_key_file, NULL));
+ env_put(t_strconcat("SSL_KEY_FILE=",
+ set->ssl_key_file, NULL));
env_put(t_strconcat("SSL_PARAM_FILE=",
set->ssl_parameters_file, NULL));
}
@@ -410,12 +396,12 @@
if (set->verbose_ssl)
env_put("VERBOSE_SSL=1");
- if (group->set->process_per_connection) {
+ if (set->login_process_per_connection) {
env_put("PROCESS_PER_CONNECTION=1");
env_put("MAX_LOGGING_USERS=1");
} else {
env_put(t_strdup_printf("MAX_LOGGING_USERS=%u",
- group->set->max_logging_users));
+ set->login_max_logging_users));
}
env_put(t_strdup_printf("PROCESS_UID=%s", dec2str(pid)));
@@ -427,14 +413,14 @@
pid_t pid;
int fd[2];
- if (group->set->process_per_connection &&
+ if (group->set->login_process_per_connection &&
group->processes - group->listening_processes >=
- group->set->max_logging_users) {
+ group->set->login_max_logging_users) {
if (group->oldest_nonlisten_process != NULL)
login_process_destroy(group->oldest_nonlisten_process);
}
- if (group->set->uid == 0)
+ if (group->set->login_uid == 0)
i_fatal("Login process must not run as root");
/* create communication to process with a socket pair */
@@ -461,12 +447,12 @@
}
/* move the listen handle */
- if (dup2(*group->listen_fd, LOGIN_LISTEN_FD) < 0)
+ if (dup2(group->set->listen_fd, LOGIN_LISTEN_FD) < 0)
i_fatal("login: dup2(listen_fd) failed: %m");
fd_close_on_exec(LOGIN_LISTEN_FD, FALSE);
/* move the SSL listen handle */
- if (dup2(*group->ssl_listen_fd, LOGIN_SSL_LISTEN_FD) < 0)
+ if (dup2(group->set->ssl_listen_fd, LOGIN_SSL_LISTEN_FD) < 0)
i_fatal("login: dup2(ssl_listen_fd) failed: %m");
fd_close_on_exec(LOGIN_SSL_LISTEN_FD, FALSE);
@@ -480,26 +466,31 @@
login_process_init_env(group, getpid());
- if (!set->login_chroot) {
+ if (!group->set->login_chroot) {
/* no chrooting, but still change to the directory */
- if (chdir(set->login_dir) < 0)
- i_fatal("chdir(%s) failed: %m", set->login_dir);
+ if (chdir(group->set->login_dir) < 0) {
+ i_fatal("chdir(%s) failed: %m",
+ group->set->login_dir);
+ }
}
- restrict_process_size(group->set->process_size, (unsigned int)-1);
+ restrict_process_size(group->set->login_process_size, (unsigned int)-1);
/* make sure we don't leak syslog fd, but do it last so that
any errors above will be logged */
closelog();
/* hide the path, it's ugly */
- argv[0] = strrchr(group->set->executable, '/');
- if (argv[0] == NULL) argv[0] = group->set->executable; else argv[0]++;
+ argv[0] = strrchr(group->set->login_executable, '/');
+ if (argv[0] == NULL)
+ argv[0] = group->set->login_executable;
+ else
+ argv[0]++;
- execv(group->set->executable, (char **) argv);
+ execv(group->set->login_executable, (char **) argv);
i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
- group->set->executable);
+ group->set->login_executable);
return -1;
}
@@ -534,10 +525,11 @@
static void login_group_start_missings(struct login_group *group)
{
- if (!group->set->process_per_connection) {
+ if (!group->set->login_process_per_connection) {
/* create max. one process every second, that way if it keeps
dying all the time we don't eat all cpu with fork()ing. */
- if (group->listening_processes < group->set->processes_count)
+ if (group->listening_processes <
+ group->set->login_processes_count)
(void)create_login_process(group);
return;
}
@@ -549,15 +541,20 @@
double their amount (unless we've hit the high limit).
Then for each second that didn't use all existing processes,
drop the max. process count by one. */
- if (group->wanted_processes_count < group->set->processes_count)
- group->wanted_processes_count = group->set->processes_count;
- else if (group->listening_processes == 0)
+ if (group->wanted_processes_count < group->set->login_processes_count) {
+ group->wanted_processes_count =
+ group->set->login_processes_count;
+ } else if (group->listening_processes == 0)
group->wanted_processes_count *= 2;
- else if (group->wanted_processes_count > group->set->processes_count)
+ else if (group->wanted_processes_count >
+ group->set->login_processes_count)
group->wanted_processes_count--;
- if (group->wanted_processes_count > group->set->max_processes_count)
- group->wanted_processes_count = group->set->max_processes_count;
+ if (group->wanted_processes_count >
+ group->set->login_max_processes_count) {
+ group->wanted_processes_count =
+ group->set->login_max_processes_count;
+ }
while (group->listening_processes < group->wanted_processes_count)
(void)create_login_process(group);
@@ -567,12 +564,9 @@
login_processes_start_missing(void *context __attr_unused__)
{
struct login_group *group;
- struct login_settings *login;
- if (login_groups == NULL) {
- for (login = set->logins; login != NULL; login = login->next)
- login_group_create(login);
- }
+ if (login_groups == NULL)
+ login_process_groups_create();
for (group = login_groups; group != NULL; group = group->next)
login_group_start_missings(group);
Index: login-process.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/login-process.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- login-process.h 27 Jan 2003 01:33:40 -0000 1.5
+++ login-process.h 10 Jul 2003 03:04:07 -0000 1.6
@@ -1,6 +1,20 @@
#ifndef __LOGIN_PROCESS_H
#define __LOGIN_PROCESS_H
+struct login_group {
+ struct login_group *next;
+
+ int process_type;
+ struct settings *set;
+
+ unsigned int processes;
+ unsigned int listening_processes;
+ unsigned int wanted_processes_count;
+
+ struct login_process *oldest_nonlisten_process;
+ struct login_process *newest_nonlisten_process;
+};
+
void login_process_abormal_exit(pid_t pid);
void login_processes_destroy_all(void);
Index: mail-process.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/mail-process.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- mail-process.c 2 Jul 2003 01:02:27 -0000 1.24
+++ mail-process.c 10 Jul 2003 03:04:07 -0000 1.25
@@ -9,6 +9,7 @@
#include "restrict-process-size.h"
#include "var-expand.h"
#include "mail-process.h"
+#include "login-process.h"
#include <stdlib.h>
#include <unistd.h>
@@ -18,13 +19,20 @@
static unsigned int mail_process_count = 0;
-static int validate_uid_gid(uid_t uid, gid_t gid, const char *user)
+static int validate_uid_gid(struct settings *set, uid_t uid, gid_t gid,
+ const char *user)
{
if (uid == 0) {
i_error("Logins with UID 0 not permitted (user %s)", user);
return FALSE;
}
+ if (set->login_uid == uid && geteuid() != uid) {
+ i_error("Can't log in using login processes UID %s (user %s) "
+ "(see login_user in config file).",
+ dec2str(uid), user);
+ }
+
if (uid < (uid_t)set->first_valid_uid ||
(set->last_valid_uid != 0 && uid > (uid_t)set->last_valid_uid)) {
i_error("Logins with UID %s (user %s) not permitted "
@@ -44,7 +52,7 @@
return TRUE;
}
-static int validate_chroot(const char *dir)
+static int validate_chroot(struct settings *set, const char *dir)
{
const char *const *chroot_dirs;
@@ -95,30 +103,31 @@
return str_c(str);
}
-int create_mail_process(int socket, struct ip_addr *ip,
- const char *executable, const char *module_dir,
- unsigned int process_size, int process_type,
+int create_mail_process(struct login_group *group, int socket,
+ struct ip_addr *ip,
struct auth_master_reply *reply, const char *data)
{
static const char *argv[] = { NULL, NULL, NULL };
+ struct settings *set = group->set;
const char *addr, *mail, *chroot_dir, *home_dir, *full_home_dir;
char title[1024];
pid_t pid;
int i, err;
+ // FIXME: per-group
if (mail_process_count == set->max_mail_processes) {
i_error("Maximum number of mail processes exceeded");
return FALSE;
}
- if (!validate_uid_gid(reply->uid, reply->gid,
+ if (!validate_uid_gid(set, reply->uid, reply->gid,
data + reply->virtual_user_idx))
return FALSE;
home_dir = data + reply->home_idx;
chroot_dir = data + reply->chroot_idx;
- if (*chroot_dir != '\0' && !validate_chroot(chroot_dir)) {
+ if (*chroot_dir != '\0' && !validate_chroot(set, chroot_dir)) {
i_error("Invalid chroot directory: %s", chroot_dir);
return FALSE;
}
@@ -132,11 +141,11 @@
if (pid != 0) {
/* master */
mail_process_count++;
- PID_ADD_PROCESS_TYPE(pid, process_type);
+ PID_ADD_PROCESS_TYPE(pid, group->process_type);
return TRUE;
}
- child_process_init_env();
+ child_process_init_env(set);
/* move the client socket into stdin and stdout fds */
fd_close_on_exec(socket, FALSE);
@@ -154,7 +163,7 @@
reply->uid, reply->gid, chroot_dir,
set->first_valid_gid, set->last_valid_gid);
- restrict_process_size(process_size, (unsigned int)-1);
+ restrict_process_size(group->set->mail_process_size, (unsigned int)-1);
if (*home_dir != '\0') {
full_home_dir = *chroot_dir == '\0' ? home_dir :
@@ -200,8 +209,12 @@
if (set->mbox_read_dotlock)
env_put("MBOX_READ_DOTLOCK=1");
- if (module_dir != NULL && *module_dir != '\0')
- env_put(t_strconcat("MODULE_DIR=", module_dir, NULL));
+ if (group->set->mail_use_modules &&
+ group->set->mail_modules != NULL &&
+ *group->set->mail_modules != '\0') {
+ env_put(t_strconcat("MODULE_DIR=",
+ group->set->mail_modules, NULL));
+ }
/* user given environment - may be malicious. virtual_user comes from
auth process, but don't trust that too much either. Some auth
@@ -236,16 +249,20 @@
restrict_access_by_env(TRUE);
/* hide the path, it's ugly */
- argv[0] = strrchr(executable, '/');
- if (argv[0] == NULL) argv[0] = executable; else argv[0]++;
+ argv[0] = strrchr(group->set->mail_executable, '/');
+ if (argv[0] == NULL)
+ argv[0] = group->set->mail_executable;
+ else
+ argv[0]++;
- execv(executable, (char **) argv);
+ execv(group->set->mail_executable, (char **) argv);
err = errno;
for (i = 0; i < 3; i++)
(void)close(i);
- i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", executable);
+ i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",
+ group->set->mail_executable);
/* not reached */
return FALSE;
Index: mail-process.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/mail-process.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mail-process.h 14 May 2003 18:23:05 -0000 1.3
+++ mail-process.h 10 Jul 2003 03:04:07 -0000 1.4
@@ -1,11 +1,11 @@
#ifndef __MAIL_PROCESS_H
#define __MAIL_PROCESS_H
+struct login_group;
struct auth_master_reply;
-int create_mail_process(int socket, struct ip_addr *ip,
- const char *executable, const char *module_dir,
- unsigned int process_size, int process_type,
+int create_mail_process(struct login_group *group, int socket,
+ struct ip_addr *ip,
struct auth_master_reply *reply, const char *data);
void mail_process_destroyed(pid_t pid);
Index: main.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/main.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- main.c 4 May 2003 16:16:26 -0000 1.44
+++ main.c 10 Jul 2003 03:04:07 -0000 1.45
@@ -34,7 +34,7 @@
struct ioloop *ioloop;
struct hash_table *pids;
-int null_fd, mail_fd[FD_MAX], inetd_login_fd;
+int null_fd, inetd_login_fd;
int validate_str(const char *str, size_t max_len)
{
@@ -48,7 +48,7 @@
return FALSE;
}
-void child_process_init_env(void)
+void child_process_init_env(struct settings *set)
{
/* remove all environment, we don't need them */
env_clean();
@@ -83,7 +83,8 @@
login_processes_destroy_all();
auth_processes_destroy_all();
- master_settings_read(configfile);
+ if (!master_settings_read(configfile))
+ i_warning("Invalid configuration, keeping old one");
}
static const char *get_exit_status_message(enum fatal_exit_status status)
@@ -218,57 +219,65 @@
return ip;
}
-static void listen_protocols(void)
+static void listen_protocols(struct settings *set)
{
- struct ip_addr *imap_ip, *imaps_ip, *pop3_ip, *pop3s_ip, *ip;
+ struct ip_addr *normal_ip, *ssl_ip, *ip;
const char *const *proto;
- unsigned int imap_port = 143;
- unsigned int pop3_port = 110;
+ unsigned int normal_port, ssl_port, port;
+ int *fd;
+
+ normal_port = set->protocol == MAIL_PROTOCOL_IMAP ? 143 : 110;
#ifdef HAVE_SSL
- unsigned int imaps_port = 993;
- unsigned int pop3s_port = 995;
+ ssl_port = set->protocol == MAIL_PROTOCOL_IMAP ? 993 : 995;
#else
- unsigned int imaps_port = 0;
- unsigned int pop3s_port = 0;
+ ssl_port = 0;
#endif
- unsigned int port;
- int *fd, i;
/* resolve */
- imap_ip = resolve_ip(set->imap_listen, &imap_port);
- imaps_ip = resolve_ip(set->imaps_listen, &imaps_port);
- pop3_ip = resolve_ip(set->pop3_listen, &pop3_port);
- pop3s_ip = resolve_ip(set->pop3s_listen, &pop3s_port);
+ normal_ip = resolve_ip(set->listen, &normal_port);
+ ssl_ip = resolve_ip(set->ssl_listen, &ssl_port);
- if (imaps_ip == NULL && set->imaps_listen == NULL)
- imaps_ip = imap_ip;
- if (pop3s_ip == NULL && set->pop3s_listen == NULL)
- pop3s_ip = pop3_ip;
+ if (ssl_ip == NULL && set->ssl_listen == NULL)
+ ssl_ip = normal_ip;
/* register wanted protocols */
for (proto = t_strsplit(set->protocols, " "); *proto != NULL; proto++) {
+ fd = NULL; ip = NULL; port = 0;
if (strcasecmp(*proto, "imap") == 0) {
- fd = &mail_fd[FD_IMAP]; ip = imap_ip; port = imap_port;
+ if (set->protocol == MAIL_PROTOCOL_IMAP) {
+ fd = &set->listen_fd;
+ port = normal_port; ip = normal_ip;
+ }
} else if (strcasecmp(*proto, "imaps") == 0) {
- fd = &mail_fd[FD_IMAPS]; ip = imaps_ip;
- port = set->ssl_disable ? 0 : imaps_port;
+ if (set->protocol == MAIL_PROTOCOL_IMAP &&
+ !set->ssl_disable) {
+ fd = &set->ssl_listen_fd;
+ port = ssl_port; ip = ssl_ip;
+ }
} else if (strcasecmp(*proto, "pop3") == 0) {
- fd = &mail_fd[FD_POP3]; ip = pop3_ip; port = pop3_port;
+ if (set->protocol == MAIL_PROTOCOL_POP3) {
+ fd = &set->listen_fd;
+ port = normal_port; ip = normal_ip;
+ }
} else if (strcasecmp(*proto, "pop3s") == 0) {
- fd = &mail_fd[FD_POP3S]; ip = pop3s_ip;
- port = set->ssl_disable ? 0 : pop3s_port;
+ if (set->protocol == MAIL_PROTOCOL_POP3 &&
+ !set->ssl_disable) {
+ fd = &set->ssl_listen_fd;
+ port = ssl_port; ip = ssl_ip;
+ }
} else {
i_fatal("Unknown protocol %s", *proto);
}
+ if (fd == NULL)
+ continue;
+
if (*fd != -1)
i_fatal("Protocol %s given more than once", *proto);
- if (port == 0) {
- *fd = dup(null_fd);
- if (*fd == -1)
- i_fatal("dup(null_fd) failed: %m");
- } else {
+ if (port == 0)
+ *fd = null_fd;
+ else {
*fd = net_listen(ip, &port);
if (*fd == -1)
i_fatal("listen(%d) failed: %m", port);
@@ -277,19 +286,42 @@
fd_close_on_exec(*fd, TRUE);
}
- for (i = 0; i < FD_MAX; i++) {
- if (mail_fd[i] == -1) {
- mail_fd[i] = dup(null_fd);
- if (mail_fd[i] == -1)
- i_fatal("dup(mail_fd[%d]) failed: %m", i);
- fd_close_on_exec(mail_fd[i], TRUE);
- }
+ if (set->listen_fd == -1)
+ set->listen_fd = null_fd;
+ if (set->ssl_listen_fd == -1)
+ set->ssl_listen_fd = null_fd;
+}
+
+static int have_stderr_set(struct settings *set)
+{
+ if (set->log_path != NULL &&
+ strcmp(set->log_path, "/dev/stderr") == 0)
+ return TRUE;
+
+ if (set->info_log_path != NULL &&
+ strcmp(set->info_log_path, "/dev/stderr") == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static int have_stderr(struct server_settings *server)
+{
+ while (server != NULL) {
+ if (server->imap != NULL && have_stderr_set(server->imap))
+ return TRUE;
+ if (server->pop3 != NULL && have_stderr_set(server->pop3))
+ return TRUE;
+
+ server = server->next;
}
+
+ return FALSE;
}
static void open_fds(void)
{
- int i;
+ struct server_settings *server;
/* initialize fds. */
null_fd = open("/dev/null", O_RDONLY);
@@ -303,11 +335,15 @@
fd_close_on_exec(null_fd, TRUE);
}
- for (i = 0; i < FD_MAX; i++)
- mail_fd[i] = -1;
-
- if (!IS_INETD())
- listen_protocols();
+ if (!IS_INETD()) {
+ server = settings_root;
+ for (; server != NULL; server = server->next) {
+ if (server->imap != NULL)
+ listen_protocols(server->imap);
+ if (server->pop3 != NULL)
+ listen_protocols(server->pop3);
+ }
+ }
/* close stdin and stdout. close stderr unless we're logging
into /dev/stderr. */
@@ -316,16 +352,13 @@
if (dup2(null_fd, 1) < 0)
i_fatal("dup2(1) failed: %m");
- if ((set->log_path == NULL ||
- strcmp(set->log_path, "/dev/stderr") != 0) &&
- (set->info_log_path == NULL ||
- strcmp(set->info_log_path, "/dev/stderr") != 0)) {
+ if (!have_stderr(settings_root)) {
if (dup2(null_fd, 2) < 0)
i_fatal("dup2(2) failed: %m");
}
}
-static void open_logfile(void)
+static void open_logfile(struct settings *set)
{
if (set->log_path == NULL)
i_set_failure_syslog("dovecot", LOG_NDELAY, LOG_MAIL);
@@ -347,7 +380,7 @@
/* deny file access from everyone else except owner */
(void)umask(0077);
- open_logfile();
+ open_logfile(settings_root->defaults);
lib_init_signals(sig_quit);
@@ -361,8 +394,6 @@
static void main_deinit(void)
{
- int i;
-
if (lib_signal_kill != 0)
i_warning("Killed with signal %d", lib_signal_kill);
@@ -378,18 +409,11 @@
if (close(null_fd) < 0)
i_error("close(null_fd) failed: %m");
- for (i = 0; i < FD_MAX; i++) {
- if (mail_fd[i] != -1) {
- if (close(mail_fd[i]) < 0)
- i_error("close(mail_fd[%d]) failed: %m", i);
- }
- }
-
hash_destroy(pids);
closelog();
}
-static void daemonize(void)
+static void daemonize(struct settings *set)
{
pid_t pid;
@@ -448,14 +472,15 @@
/* read and verify settings before forking */
master_settings_init();
- master_settings_read(configfile);
+ if (!master_settings_read(configfile))
+ exit(FATAL_DEFAULT);
open_fds();
/* we don't need any environment */
env_clean();
if (!foreground)
- daemonize();
+ daemonize(settings_root->defaults);
ioloop = io_loop_create(system_pool);
Index: master-settings.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/master-settings.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- master-settings.c 2 Jul 2003 01:02:27 -0000 1.20
+++ master-settings.c 10 Jul 2003 03:04:07 -0000 1.21
@@ -12,6 +12,22 @@
#include <fcntl.h>
#include <pwd.h>
+enum settings_type {
+ SETTINGS_TYPE_ROOT,
+ SETTINGS_TYPE_SERVER,
+ SETTINGS_TYPE_AUTH
+};
+
+struct settings_parse_ctx {
+ enum settings_type type, parent_type;
+ enum mail_protocol protocol;
+
+ struct server_settings *root, *server;
+ struct auth_settings *auth;
+
+ int level;
+};
+
#define DEF(type, name) \
{ type, #name, offsetof(struct settings, name) }
@@ -24,10 +40,8 @@
/* general */
DEF(SET_STR, protocols),
- DEF(SET_STR, imap_listen),
- DEF(SET_STR, imaps_listen),
- DEF(SET_STR, pop3_listen),
- DEF(SET_STR, pop3s_listen),
+ DEF(SET_STR, listen),
+ DEF(SET_STR, ssl_listen),
DEF(SET_BOOL, ssl_disable),
DEF(SET_STR, ssl_cert_file),
@@ -35,11 +49,20 @@
DEF(SET_STR, ssl_parameters_file),
DEF(SET_STR, ssl_parameters_regenerate),
DEF(SET_BOOL, disable_plaintext_auth),
+ DEF(SET_BOOL, verbose_ssl),
/* login */
DEF(SET_STR, login_dir),
+ DEF(SET_STR, login_executable),
+ DEF(SET_STR, login_user),
+
+ DEF(SET_BOOL, login_process_per_connection),
DEF(SET_BOOL, login_chroot),
- DEF(SET_BOOL, verbose_ssl),
+
+ DEF(SET_INT, login_process_size),
+ DEF(SET_INT, login_processes_count),
+ DEF(SET_INT, login_max_processes_count),
+ DEF(SET_INT, login_max_logging_users),
/* mail */
DEF(SET_STR, valid_chroot_dirs),
@@ -70,36 +93,13 @@
DEF(SET_INT, umask),
DEF(SET_BOOL, mail_drop_priv_before_exec),
+ DEF(SET_STR, mail_executable),
+ DEF(SET_INT, mail_process_size),
+ DEF(SET_BOOL, mail_use_modules),
+ DEF(SET_STR, mail_modules),
+
/* imap */
- DEF(SET_STR, imap_executable),
- DEF(SET_INT, imap_process_size),
DEF(SET_INT, imap_max_line_length),
- DEF(SET_BOOL, imap_use_modules),
- DEF(SET_STR, imap_modules),
-
- /* pop3 */
- DEF(SET_STR, pop3_executable),
- DEF(SET_INT, pop3_process_size),
- DEF(SET_BOOL, pop3_use_modules),
- DEF(SET_STR, pop3_modules),
-
- { 0, NULL, 0 }
-};
-
-#undef DEF
-#define DEF(type, name) \
- { type, #name, offsetof(struct login_settings, name) }
-
-static struct setting_def login_setting_defs[] = {
- DEF(SET_STR, executable),
- DEF(SET_STR, user),
-
- DEF(SET_BOOL, process_per_connection),
-
- DEF(SET_INT, process_size),
- DEF(SET_INT, processes_count),
- DEF(SET_INT, max_processes_count),
- DEF(SET_INT, max_logging_users),
{ 0, NULL, 0 }
};
@@ -130,6 +130,9 @@
};
struct settings default_settings = {
+ MEMBER(server) NULL,
+ MEMBER(protocol) 0,
+
/* common */
MEMBER(base_dir) PKG_RUNDIR,
MEMBER(log_path) NULL,
@@ -138,10 +141,8 @@
/* general */
MEMBER(protocols) "imap imaps",
- MEMBER(imap_listen) "*",
- MEMBER(imaps_listen) NULL,
- MEMBER(pop3_listen) "*",
- MEMBER(pop3s_listen) NULL,
+ MEMBER(listen) "*",
+ MEMBER(ssl_listen) NULL,
MEMBER(ssl_disable) FALSE,
MEMBER(ssl_cert_file) SSLDIR"/certs/dovecot.pem",
@@ -149,11 +150,20 @@
MEMBER(ssl_parameters_file) "ssl-parameters.dat",
MEMBER(ssl_parameters_regenerate) 24,
MEMBER(disable_plaintext_auth) FALSE,
+ MEMBER(verbose_ssl) FALSE,
/* login */
MEMBER(login_dir) "login",
+ MEMBER(login_executable) NULL,
+ MEMBER(login_user) "dovecot",
+
+ MEMBER(login_process_per_connection) TRUE,
MEMBER(login_chroot) TRUE,
- MEMBER(verbose_ssl) FALSE,
+
+ MEMBER(login_process_size) 16,
+ MEMBER(login_processes_count) 3,
+ MEMBER(login_max_processes_count) 128,
+ MEMBER(login_max_logging_users) 256,
/* mail */
MEMBER(valid_chroot_dirs) NULL,
@@ -184,42 +194,23 @@
MEMBER(umask) 0077,
MEMBER(mail_drop_priv_before_exec) FALSE,
+ MEMBER(mail_executable) PKG_LIBEXECDIR"/imap",
+ MEMBER(mail_process_size) 256,
+ MEMBER(mail_use_modules) FALSE,
+ MEMBER(mail_modules) PKG_LIBDIR"/imap",
+
/* imap */
- MEMBER(imap_executable) PKG_LIBEXECDIR"/imap",
- MEMBER(imap_process_size) 256,
MEMBER(imap_max_line_length) 65536,
- MEMBER(imap_use_modules) FALSE,
- MEMBER(imap_modules) PKG_LIBDIR"/imap",
-
- /* pop3 */
- MEMBER(pop3_executable) PKG_LIBEXECDIR"/pop3",
- MEMBER(pop3_process_size) 256,
- MEMBER(pop3_use_modules) FALSE,
- MEMBER(pop3_modules) PKG_LIBDIR"/imap",
+ /* .. */
+ MEMBER(login_uid) 0,
MEMBER(login_gid) 0,
- MEMBER(auths) NULL,
- MEMBER(logins) NULL
-};
-
-struct login_settings default_login_settings = {
- MEMBER(next) NULL,
- MEMBER(name) NULL,
-
- MEMBER(executable) NULL,
- MEMBER(user) "dovecot",
-
- MEMBER(process_per_connection) TRUE,
-
- MEMBER(process_size) 16,
- MEMBER(processes_count) 3,
- MEMBER(max_processes_count) 128,
- MEMBER(max_logging_users) 256,
-
- MEMBER(uid) 0 /* generated */
+ MEMBER(listen_fd) -1,
+ MEMBER(ssl_listen_fd) -1
};
struct auth_settings default_auth_settings = {
+ MEMBER(parent) NULL,
MEMBER(next) NULL,
MEMBER(name) NULL,
@@ -241,8 +232,8 @@
MEMBER(process_size) 256
};
-static pool_t settings_pool;
-struct settings *set = NULL;
+static pool_t settings_pool, settings2_pool;
+struct server_settings *settings_root = NULL;
static void fix_base_path(struct settings *set, const char **str)
{
@@ -252,49 +243,42 @@
}
}
-static void get_login_uid(struct settings *set,
- struct login_settings *login_set)
+static int get_login_uid(struct settings *set)
{
struct passwd *pw;
- if ((pw = getpwnam(login_set->user)) == NULL)
- i_fatal("Login user doesn't exist: %s", login_set->user);
+ if ((pw = getpwnam(set->login_user)) == NULL) {
+ i_error("Login user doesn't exist: %s", set->login_user);
+ return FALSE;
+ }
if (set->login_gid == 0)
set->login_gid = pw->pw_gid;
else if (set->login_gid != pw->pw_gid) {
- i_fatal("All login process users must belong to same group "
+ i_error("All login process users must belong to same group "
"(%s vs %s)", dec2str(set->login_gid),
dec2str(pw->pw_gid));
+ return FALSE;
}
- login_set->uid = pw->pw_uid;
+ set->login_uid = pw->pw_uid;
+ return TRUE;
}
-static void auth_settings_verify(struct auth_settings *auth)
+static int auth_settings_verify(struct auth_settings *auth)
{
- if (access(auth->executable, X_OK) < 0)
- i_fatal("Can't use auth executable %s: %m", auth->executable);
+ if (access(auth->executable, X_OK) < 0) {
+ i_error("Can't use auth executable %s: %m", auth->executable);
+ return FALSE;
+ }
- fix_base_path(set, &auth->chroot);
+ fix_base_path(auth->parent->defaults, &auth->chroot);
if (auth->chroot != NULL && access(auth->chroot, X_OK) < 0) {
- i_fatal("Can't access auth chroot directory %s: %m",
+ i_error("Can't access auth chroot directory %s: %m",
auth->chroot);
+ return FALSE;
}
-}
-
-static void login_settings_verify(struct login_settings *login)
-{
- if (strstr(set->protocols, login->name) != NULL) {
- if (access(login->executable, X_OK) < 0)
- i_fatal("Can't use login executable %s: %m",
- login->executable);
- }
-
- if (login->processes_count < 1)
- i_fatal("login_processes_count must be at least 1");
- if (login->max_logging_users < 1)
- i_fatal("max_logging_users must be at least 1");
+ return TRUE;
}
static const char *get_directory(const char *path)
@@ -311,82 +295,78 @@
}
}
-static void settings_verify(struct settings *set)
+static int settings_is_active(struct settings *set)
+{
+ if (set->protocol == MAIL_PROTOCOL_IMAP) {
+ if (strstr(set->protocols, "imap") == NULL)
+ return FALSE;
+ } else {
+ if (strstr(set->protocols, "pop3") == NULL)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int settings_verify(struct settings *set)
{
- struct login_settings *login;
- struct auth_settings *auth;
const char *const *str;
const char *dir;
int dotlock_got, fcntl_got, flock_got;
- for (login = set->logins; login != NULL; login = login->next) {
- get_login_uid(set, login);
- login_settings_verify(login);
- }
+ if (!get_login_uid(set))
+ return FALSE;
- if (strstr(set->protocols, "imap") != NULL) {
- if (access(set->imap_executable, X_OK) < 0) {
- i_fatal("Can't use imap executable %s: %m",
- set->imap_executable);
- }
-#ifdef HAVE_MODULES
- if (set->imap_use_modules &&
- access(set->imap_modules, R_OK | X_OK) < 0) {
- i_fatal("Can't access imap module directory: %s: %m",
- set->imap_modules);
- }
-#else
- if (set->imap_use_modules) {
- i_warning("Module support wasn't built into Dovecot, "
- "ignoring imap_use_modules setting");
- }
-#endif
+ if (access(set->mail_executable, X_OK) < 0) {
+ i_error("Can't use mail executable %s: %m",
+ set->mail_executable);
+ return FALSE;
}
- if (strstr(set->protocols, "pop3") != NULL) {
- if (access(set->pop3_executable, X_OK) < 0) {
- i_fatal("Can't use pop3 executable %s: %m",
- set->pop3_executable);
- }
#ifdef HAVE_MODULES
- if (set->pop3_use_modules &&
- access(set->pop3_modules, R_OK | X_OK) < 0) {
- i_fatal("Can't access pop3 module directory: %s: %m",
- set->imap_modules);
- }
+ if (set->mail_use_modules &&
+ access(set->mail_modules, R_OK | X_OK) < 0) {
+ i_error("Can't access mail module directory: %s: %m",
+ set->mail_modules);
+ return FALSE;
+ }
#else
- if (set->pop3_use_modules) {
- i_warning("Module support wasn't built into Dovecot, "
- "ignoring pop3_use_modules setting");
- }
-#endif
+ if (set->mail_use_modules) {
+ i_warning("Module support wasn't built into Dovecot, "
+ "ignoring mail_use_modules setting");
}
+#endif
if (set->log_path != NULL && access(set->log_path, W_OK) < 0) {
dir = get_directory(set->log_path);
- if (access(dir, W_OK) < 0)
- i_fatal("Can't write to log directory %s: %m", dir);
+ if (access(dir, W_OK) < 0) {
+ i_error("Can't write to log directory %s: %m", dir);
+ return FALSE;
+ }
}
if (set->info_log_path != NULL &&
access(set->info_log_path, W_OK) < 0) {
dir = get_directory(set->info_log_path);
if (access(dir, W_OK) < 0) {
- i_fatal("Can't write to info log directory %s: %m",
+ i_error("Can't write to info log directory %s: %m",
dir);
+ return FALSE;
}
}
#ifdef HAVE_SSL
if (!set->ssl_disable) {
if (access(set->ssl_cert_file, R_OK) < 0) {
- i_fatal("Can't use SSL certificate %s: %m",
+ i_error("Can't use SSL certificate %s: %m",
set->ssl_cert_file);
+ return FALSE;
}
if (access(set->ssl_key_file, R_OK) < 0) {
- i_fatal("Can't use SSL key file %s: %m",
+ i_error("Can't use SSL key file %s: %m",
set->ssl_key_file);
+ return FALSE;
}
}
#endif
@@ -403,23 +383,31 @@
}
/* wipe out contents of login directory, if it exists */
- if (unlink_directory(set->login_dir, FALSE) < 0)
- i_fatal("unlink_directory() failed for %s: %m", set->login_dir);
+ if (unlink_directory(set->login_dir, FALSE) < 0) {
+ i_error("unlink_directory() failed for %s: %m", set->login_dir);
+ return FALSE;
+ }
if (safe_mkdir(set->login_dir, 0750, geteuid(), set->login_gid) == 0) {
i_warning("Corrected permissions for login directory %s",
set->login_dir);
}
- if (set->max_mail_processes < 1)
- i_fatal("max_mail_processes must be at least 1");
+ if (set->max_mail_processes < 1) {
+ i_error("max_mail_processes must be at least 1");
+ return FALSE;
+ }
if (set->last_valid_uid != 0 &&
- set->first_valid_uid > set->last_valid_uid)
- i_fatal("first_valid_uid can't be larger than last_valid_uid");
+ set->first_valid_uid > set->last_valid_uid) {
+ i_error("first_valid_uid can't be larger than last_valid_uid");
+ return FALSE;
+ }
if (set->last_valid_gid != 0 &&
- set->first_valid_gid > set->last_valid_gid)
- i_fatal("first_valid_gid can't be larger than last_valid_gid");
+ set->first_valid_gid > set->last_valid_gid) {
+ i_error("first_valid_gid can't be larger than last_valid_gid");
+ return FALSE;
+ }
dotlock_got = fcntl_got = flock_got = FALSE;
for (str = t_strsplit(set->mbox_locks, " "); *str != NULL; str++) {
@@ -429,20 +417,25 @@
fcntl_got = TRUE;
else if (strcasecmp(*str, "flock") == 0)
flock_got = TRUE;
- else
- i_fatal("mbox_locks: Invalid value %s", *str);
+ else {
+ i_error("mbox_locks: Invalid value %s", *str);
+ return FALSE;
+ }
}
#ifndef HAVE_FLOCK
if (fcntl_got && !dotlock_got && !flock_got) {
- i_fatal("mbox_locks: Only flock selected, "
+ i_error("mbox_locks: Only flock selected, "
"and flock() isn't supported in this system");
+ return FALSE;
}
flock_got = FALSE;
#endif
- if (!dotlock_got && !fcntl_got && !flock_got)
- i_fatal("mbox_locks: No mbox locking methods selected");
+ if (!dotlock_got && !fcntl_got && !flock_got) {
+ i_error("mbox_locks: No mbox locking methods selected");
+ return FALSE;
+ }
if (dotlock_got && !set->mbox_read_dotlock &&
!fcntl_got && !flock_got) {
@@ -451,11 +444,26 @@
set->mbox_read_dotlock = TRUE;
}
- for (auth = set->auths; auth != NULL; auth = auth->next)
- auth_settings_verify(auth);
+ if (access(set->login_executable, X_OK) < 0) {
+ i_error("Can't use login executable %s: %m",
+ set->login_executable);
+ return FALSE;
+ }
+
+ if (set->login_processes_count < 1) {
+ i_error("login_processes_count must be at least 1");
+ return FALSE;
+ }
+ if (set->login_max_logging_users < 1) {
+ i_error("login_max_logging_users must be at least 1");
+ return FALSE;
+ }
+
+ return TRUE;
}
-static void auth_settings_new(struct settings *set, const char *name)
+static struct auth_settings *
+auth_settings_new(struct server_settings *server, const char *name)
{
struct auth_settings *auth;
@@ -463,124 +471,282 @@
/* copy defaults */
*auth = default_auth_settings;
+ auth->parent = server;
auth->name = p_strdup(settings_pool, name);
- auth->next = set->auths;
- set->auths = auth;
+ auth->next = server->auths;
+ server->auths = auth;
+
+ return auth;
}
-static const char *parse_new_auth(struct settings *set, const char *name)
+static struct auth_settings *
+parse_new_auth(struct server_settings *server, const char *name,
+ const char **errormsg)
{
struct auth_settings *auth;
- if (strchr(name, '/') != NULL)
- return "Authentication process name must not contain '/'";
+ if (strchr(name, '/') != NULL) {
+ *errormsg = "Authentication process name must not contain '/'";
+ return NULL;
+ }
- for (auth = set->auths; auth != NULL; auth = auth->next) {
+ for (auth = server->auths; auth != NULL; auth = auth->next) {
if (strcmp(auth->name, name) == 0) {
- return "Authentication process already exists "
+ *errormsg = "Authentication process already exists "
"with the same name";
+ return NULL;
}
}
- auth_settings_new(set, name);
- return NULL;
+ return auth_settings_new(server, name);
}
-static void login_settings_new(struct settings *set, const char *name)
+static const char *parse_setting(const char *key, const char *value,
+ void *context)
{
- struct login_settings *login;
+ struct settings_parse_ctx *ctx = context;
+ const char *error;
- login = p_new(settings_pool, struct login_settings, 1);
+ /* backwards compatibility */
+ if (strcmp(key, "auth") == 0) {
+ ctx->auth = parse_new_auth(ctx->server, value, &error);
+ return ctx->auth == NULL ? error : NULL;
+ }
- /* copy defaults */
- *login = set->logins != NULL ? *set->logins :
- default_login_settings;
+ if (strcmp(key, "login") == 0) {
+ i_warning("Ignoring deprecated 'login' section handling. "
+ "Use protocol imap/pop3 { .. } instead. "
+ "Some settings may have been read incorrectly.");
+ return NULL;
+ }
- if (strcasecmp(name, "imap") == 0) {
- login->name = "imap";
- login->executable = PKG_LIBEXECDIR"/imap-login";
- } else if (strcasecmp(name, "pop3") == 0) {
- login->name = "pop3";
- login->executable = PKG_LIBEXECDIR"/pop3-login";
- } else {
- i_fatal("Unknown login process type '%s'", name);
+ switch (ctx->type) {
+ case SETTINGS_TYPE_ROOT:
+ case SETTINGS_TYPE_SERVER:
+ error = NULL;
+ if (ctx->protocol == MAIL_PROTOCOL_ANY ||
+ ctx->protocol == MAIL_PROTOCOL_IMAP) {
+ error = parse_setting_from_defs(settings_pool,
+ setting_defs,
+ ctx->server->imap,
+ key, value);
+ }
+
+ if (error == NULL &&
+ (ctx->protocol == MAIL_PROTOCOL_ANY ||
+ ctx->protocol == MAIL_PROTOCOL_POP3)) {
+ error = parse_setting_from_defs(settings_pool,
+ setting_defs,
+ ctx->server->pop3,
+ key, value);
+ }
+
+ if (error == NULL)
+ return NULL;
+
+ /* backwards compatibility */
+ if (strncmp(key, "auth_", 5) == 0) {
+ if (ctx->auth == NULL) {
+ return "Authentication process name "
+ "not defined yet";
+ }
+
+ return parse_setting_from_defs(settings_pool,
+ auth_setting_defs,
+ ctx->auth,
+ key + 5, value);
+ }
+ return error;
+ case SETTINGS_TYPE_AUTH:
+ return parse_setting_from_defs(settings_pool, auth_setting_defs,
+ ctx->auth, key + 5, value);
}
- login->next = set->logins;
- set->logins = login;
+ i_unreached();
}
-static const char *parse_new_login(struct settings *set, const char *name)
+static struct server_settings *
+create_new_server(const char *name,
+ struct settings *imap_defaults,
+ struct settings *pop3_defaults)
{
- struct login_settings *login;
+ struct server_settings *server;
- for (login = set->logins; login != NULL; login = login->next) {
- if (strcmp(login->name, name) == 0) {
- return "Login process already exists "
- "with the same name";
- }
- }
+ server = p_new(settings_pool, struct server_settings, 1);
+ server->name = p_strdup(settings_pool, name);
+ server->imap = p_new(settings_pool, struct settings, 1);
+ server->pop3 = p_new(settings_pool, struct settings, 1);
- login_settings_new(set, name);
- return NULL;
+ *server->imap = *imap_defaults;
+ *server->pop3 = *pop3_defaults;
+
+ server->imap->protocol = MAIL_PROTOCOL_IMAP;
+ server->imap->login_executable = PKG_LIBEXECDIR"/imap-login";
+ server->imap->mail_executable = PKG_LIBEXECDIR"/imap";
+
+ server->pop3->protocol = MAIL_PROTOCOL_POP3;
+ server->pop3->login_executable = PKG_LIBEXECDIR"/pop3-login";
+ server->pop3->mail_executable = PKG_LIBEXECDIR"/pop3";
+
+ return server;
}
-static const char *parse_setting(const char *key, const char *value,
- void *context)
+static int parse_section(const char *type, const char *name, void *context,
+ const char **errormsg)
{
- struct settings *set = context;
- const char *error;
+ struct settings_parse_ctx *ctx = context;
+ struct server_settings *server;
- /* check defaults first, there's a few login_ settings defined in it
- which need to be checked before trying to feed it to login
- handler.. */
- error = parse_setting_from_defs(settings_pool, setting_defs,
- set, key, value);
- if (error == NULL)
- return NULL;
+ if (type == NULL) {
+ /* section closing */
+ if (ctx->level > 0) {
+ ctx->level--;
+ ctx->protocol = MAIL_PROTOCOL_ANY;
+ } else {
+ ctx->type = ctx->parent_type;
+ ctx->parent_type = SETTINGS_TYPE_ROOT;
+ ctx->server = ctx->root;
+ ctx->auth = NULL;
+ }
+ return TRUE;
+ }
- if (strcmp(key, "auth") == 0)
- return parse_new_auth(set, value);
- if (strncmp(key, "auth_", 5) == 0) {
- if (set->auths == NULL)
- return "Authentication process name not defined yet";
+ if (strcmp(type, "server") == 0) {
+ if (ctx->type != SETTINGS_TYPE_ROOT) {
+ *errormsg = "Server section not allowed here";
+ return FALSE;
+ }
- return parse_setting_from_defs(settings_pool, auth_setting_defs,
- set->auths, key + 5, value);
+ ctx->parent_type = ctx->type;
+ ctx->type = SETTINGS_TYPE_SERVER;
+
+ ctx->server = create_new_server(name,
+ ctx->server->imap,
+ ctx->server->pop3);
+ server = ctx->root;
+ while (server->next != NULL)
+ server = server->next;
+ server->next = ctx->server;
+ return TRUE;
}
- if (strcmp(key, "login") == 0)
- return parse_new_login(set, value);
- if (strncmp(key, "login_", 6) == 0) {
- if (set->logins == NULL)
- return "Login process name not defined yet";
+ if (strcmp(type, "protocol") == 0) {
+ if ((ctx->type != SETTINGS_TYPE_ROOT &&
+ ctx->type != SETTINGS_TYPE_SERVER) ||
+ ctx->level != 0) {
+ *errormsg = "Protocol section not allowed here";
+ return FALSE;
+ }
- return parse_setting_from_defs(settings_pool,
- login_setting_defs,
- set->logins, key + 6, value);
+ if (strcmp(name, "imap") == 0)
+ ctx->protocol = MAIL_PROTOCOL_IMAP;
+ else if (strcmp(name, "pop3") == 0)
+ ctx->protocol = MAIL_PROTOCOL_POP3;
+ else {
+ *errormsg = "Unknown protocol name";
+ return FALSE;
+ }
+ ctx->level++;
+ return TRUE;
}
- return error;
+ if (strcmp(type, "auth") == 0) {
+ if (ctx->type != SETTINGS_TYPE_ROOT &&
+ ctx->type != SETTINGS_TYPE_SERVER) {
+ *errormsg = "Auth section not allowed here";
+ return FALSE;
+ }
+
+ ctx->type = SETTINGS_TYPE_AUTH;
+ ctx->auth = parse_new_auth(ctx->server, name, errormsg);
+ return ctx->auth != NULL;
+ }
+
+ *errormsg = "Unknown section type";
+ return FALSE;
}
-void master_settings_read(const char *path)
+int master_settings_read(const char *path)
{
+ struct settings_parse_ctx ctx;
+ struct server_settings *server, *prev;
+ struct auth_settings *auth;
+ pool_t temp;
+
+ memset(&ctx, 0, sizeof(ctx));
+
p_clear(settings_pool);
- set = p_new(settings_pool, struct settings, 1);
- *set = default_settings;
- settings_read(path, parse_setting, set);
+ ctx.type = SETTINGS_TYPE_ROOT;
+ ctx.protocol = MAIL_PROTOCOL_ANY;
+ ctx.server = ctx.root =
+ create_new_server("default",
+ &default_settings, &default_settings);
- settings_verify(set);
+ if (!settings_read(path, NULL, parse_setting, parse_section, &ctx))
+ return FALSE;
+
+ if (ctx.level != 0) {
+ i_error("Missing '}'");
+ return FALSE;
+ }
+
+ /* If server sections were defined, skip the root */
+ if (ctx.root->next != NULL)
+ ctx.root = ctx.root->next;
+
+ prev = NULL;
+ for (server = ctx.root; server != NULL; server = server->next) {
+ if (!settings_is_active(server->imap))
+ server->imap = NULL;
+ else {
+ if (!settings_verify(server->imap))
+ return FALSE;
+ server->defaults = server->imap;
+ }
+
+ if (!settings_is_active(server->pop3))
+ server->pop3 = NULL;
+ else {
+ if (!settings_verify(server->pop3))
+ return FALSE;
+ if (server->defaults == NULL)
+ server->defaults = server->pop3;
+ }
+
+ if (server->defaults == NULL) {
+ if (prev == NULL)
+ ctx.root = server->next;
+ else
+ prev->next = server->next;
+ } else {
+ auth = server->auths;
+ for (; auth != NULL; auth = auth->next) {
+ if (!auth_settings_verify(auth))
+ return FALSE;
+ }
+ prev = server;
+ }
+ }
+
+ /* settings ok, swap them */
+ temp = settings_pool;
+ settings_pool = settings2_pool;
+ settings2_pool = temp;
+
+ settings_root = ctx.root;
+ return TRUE;
}
void master_settings_init(void)
{
- settings_pool = pool_alloconly_create("settings", 1024);
+ settings_pool = pool_alloconly_create("settings", 2048);
+ settings2_pool = pool_alloconly_create("settings2", 2048);
}
void master_settings_deinit(void)
{
pool_unref(settings_pool);
+ pool_unref(settings2_pool);
}
Index: master-settings.h
===================================================================
RCS file: /home/cvs/dovecot/src/master/master-settings.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- master-settings.h 2 Jul 2003 01:02:27 -0000 1.13
+++ master-settings.h 10 Jul 2003 03:04:07 -0000 1.14
@@ -1,7 +1,26 @@
#ifndef __MASTER_SETTINGS_H
#define __MASTER_SETTINGS_H
+enum mail_protocol {
+ MAIL_PROTOCOL_ANY,
+ MAIL_PROTOCOL_IMAP,
+ MAIL_PROTOCOL_POP3
+};
+
+struct server_settings {
+ struct server_settings *next;
+
+ const char *name;
+ struct settings *defaults;
+ struct settings *imap;
+ struct settings *pop3;
+ struct auth_settings *auths;
+};
+
struct settings {
+ struct server_settings *server;
+ enum mail_protocol protocol;
+
/* common */
const char *base_dir;
const char *log_path;
@@ -10,10 +29,8 @@
/* general */
const char *protocols;
- const char *imap_listen;
- const char *imaps_listen;
- const char *pop3_listen;
- const char *pop3s_listen;
+ const char *listen;
+ const char *ssl_listen;
int ssl_disable;
const char *ssl_cert_file;
@@ -21,11 +38,20 @@
const char *ssl_parameters_file;
unsigned int ssl_parameters_regenerate;
int disable_plaintext_auth;
+ int verbose_ssl;
/* login */
const char *login_dir;
+ const char *login_executable;
+ const char *login_user;
+
+ int login_process_per_connection;
int login_chroot;
- int verbose_ssl;
+
+ unsigned int login_process_size;
+ unsigned int login_processes_count;
+ unsigned int login_max_processes_count;
+ unsigned int login_max_logging_users;
/* mail */
const char *valid_chroot_dirs;
@@ -47,51 +73,30 @@
int mail_read_mmaped;
int maildir_copy_with_hardlinks;
int maildir_check_content_changes;
- char *mbox_locks;
+ const char *mbox_locks;
int mbox_read_dotlock;
unsigned int mbox_lock_timeout;
unsigned int mbox_dotlock_change_timeout;
unsigned int umask;
int mail_drop_priv_before_exec;
+ const char *mail_executable;
+ unsigned int mail_process_size;
+ int mail_use_modules;
+ const char *mail_modules;
+
/* imap */
- const char *imap_executable;
- unsigned int imap_process_size;
unsigned int imap_max_line_length;
- int imap_use_modules;
- const char *imap_modules;
-
- /* pop3 */
- const char *pop3_executable;
- unsigned int pop3_process_size;
- int pop3_use_modules;
- const char *pop3_modules;
/* .. */
+ uid_t login_uid;
gid_t login_gid;
- struct auth_settings *auths;
- struct login_settings *logins;
-};
-
-struct login_settings {
- struct login_settings *next;
-
- const char *name;
- const char *executable;
- const char *user;
-
- int process_per_connection;
-
- unsigned int process_size;
- unsigned int processes_count;
- unsigned int max_processes_count;
- unsigned int max_logging_users;
-
- uid_t uid; /* gid must be always same with all login processes */
+ int listen_fd, ssl_listen_fd;
};
struct auth_settings {
+ struct server_settings *parent;
struct auth_settings *next;
const char *name;
@@ -112,9 +117,9 @@
unsigned int process_size;
};
-extern struct settings *set;
+extern struct server_settings *settings_root;
-void master_settings_read(const char *path);
+int master_settings_read(const char *path);
void master_settings_init(void);
void master_settings_deinit(void);
Index: ssl-init.c
===================================================================
RCS file: /home/cvs/dovecot/src/master/ssl-init.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- ssl-init.c 30 Jan 2003 17:59:32 -0000 1.10
+++ ssl-init.c 10 Jul 2003 03:04:07 -0000 1.11
@@ -38,7 +38,7 @@
i_fatal("rename(%s, %s) failed: %m", temp_fname, fname);
}
-static void start_generate_process(void)
+static void start_generate_process(struct settings *set)
{
pid_t pid;
@@ -64,19 +64,19 @@
generating = FALSE;
}
-static void check_parameters_file(void *context __attr_unused__)
+static int check_parameters_file_set(struct settings *set)
{
struct stat st;
time_t regen_time;
- if (set->ssl_parameters_file == NULL || set->ssl_disable || generating)
- return;
+ if (set->ssl_parameters_file == NULL || set->ssl_disable)
+ return TRUE;
if (lstat(set->ssl_parameters_file, &st) < 0) {
if (errno != ENOENT) {
i_error("lstat() failed for SSL parameters file %s: %m",
set->ssl_parameters_file);
- return;
+ return TRUE;
}
st.st_mtime = 0;
@@ -86,8 +86,29 @@
regen_time = st.st_mtime +
(time_t)(set->ssl_parameters_regenerate*3600);
if (regen_time < ioloop_time || (st.st_mode & 077) != 0 ||
- st.st_uid != geteuid() || st.st_gid != getegid())
- start_generate_process();
+ st.st_uid != geteuid() || st.st_gid != getegid()) {
+ start_generate_process(set);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void check_parameters_file(void *context __attr_unused__)
+{
+ struct server_settings *server;
+
+ if (generating)
+ return;
+
+ for (server = settings_root; server != NULL; server = server->next) {
+ if (server->imap != NULL &&
+ !check_parameters_file_set(server->imap))
+ break;
+ if (server->pop3 != NULL &&
+ !check_parameters_file_set(server->pop3))
+ break;
+ }
}
void ssl_init(void)
More information about the dovecot-cvs
mailing list