dovecot: Initial implementation for mail_max_user_connections se...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Jun 30 21:16:32 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/21e529b8a701
changeset: 5846:21e529b8a701
user: Timo Sirainen <tss at iki.fi>
date: Sat Jun 30 19:14:08 2007 +0300
description:
Initial implementation for mail_max_user_connections setting.
diffstat:
18 files changed, 232 insertions(+), 61 deletions(-)
dovecot-example.conf | 7 +
src/imap-login/client-authenticate.c | 8 +
src/login-common/master.c | 7 -
src/login-common/master.h | 3
src/login-common/sasl-server.c | 21 +++-
src/master/child-process.c | 6 -
src/master/child-process.h | 4
src/master/dict-process.c | 1
src/master/login-process.c | 9 -
src/master/mail-process.c | 178 +++++++++++++++++++++++++++-------
src/master/mail-process.h | 13 +-
src/master/main.c | 6 -
src/master/master-login-interface.h | 9 +
src/master/master-settings-defs.c | 1
src/master/master-settings.c | 9 +
src/master/master-settings.h | 1
src/master/ssl-init.c | 2
src/pop3-login/client-authenticate.c | 8 +
diffs (truncated from 645 to 300 lines):
diff -r 9265c13c4103 -r 21e529b8a701 dovecot-example.conf
--- a/dovecot-example.conf Sat Jun 30 19:01:06 2007 +0300
+++ b/dovecot-example.conf Sat Jun 30 19:14:08 2007 +0300
@@ -333,6 +333,13 @@
# Maximum number of running mail processes. When this limit is reached,
# new users aren't allowed to log in.
#max_mail_processes = 1024
+
+# Maximum number of connections allowed for a user. The limits are enforced
+# separately for IMAP and POP3 connections, so you can move this setting
+# inside protocol {} to have separate settings for them. NOTE: The user names
+# are compared case-sensitively, so make sure your userdb returns usernames
+# always using the same casing so users can't bypass this limit!
+#mail_max_user_connections = 10
# Set max. process size in megabytes. Most of the memory goes to mmap()ing
# files, so it shouldn't harm much even if this limit is set pretty high.
diff -r 9265c13c4103 -r 21e529b8a701 src/imap-login/client-authenticate.c
--- a/src/imap-login/client-authenticate.c Sat Jun 30 19:01:06 2007 +0300
+++ b/src/imap-login/client-authenticate.c Sat Jun 30 19:14:08 2007 +0300
@@ -222,7 +222,13 @@ static void sasl_callback(struct client
}
break;
case SASL_SERVER_REPLY_MASTER_FAILED:
- client_destroy_internal_failure(client);
+ if (data == NULL)
+ client_destroy_internal_failure(client);
+ else {
+ client_send_tagline(client,
+ t_strconcat("NO ", data, NULL));
+ client_destroy(client, data);
+ }
break;
case SASL_SERVER_REPLY_CONTINUE:
data_len = strlen(data);
diff -r 9265c13c4103 -r 21e529b8a701 src/login-common/master.c
--- a/src/login-common/master.c Sat Jun 30 19:01:06 2007 +0300
+++ b/src/login-common/master.c Sat Jun 30 19:14:08 2007 +0300
@@ -22,7 +22,8 @@ static char master_buf[sizeof(struct mas
static char master_buf[sizeof(struct master_login_reply)];
static struct client destroyed_client;
-static void client_call_master_callback(struct client *client, bool success)
+static void client_call_master_callback(struct client *client,
+ enum master_login_status status)
{
master_callback_t *master_callback;
@@ -30,7 +31,7 @@ static void client_call_master_callback(
client->master_tag = 0;
client->master_callback = NULL;
- master_callback(client, success);
+ master_callback(client, status);
}
static void request_handle(struct master_login_reply *reply)
@@ -50,7 +51,7 @@ static void request_handle(struct master
hash_remove(master_requests, POINTER_CAST(reply->tag));
if (client != &destroyed_client) {
- client_call_master_callback(client, reply->success);
+ client_call_master_callback(client, reply->status);
/* NOTE: client may be destroyed now */
}
}
diff -r 9265c13c4103 -r 21e529b8a701 src/login-common/master.h
--- a/src/login-common/master.h Sat Jun 30 19:01:06 2007 +0300
+++ b/src/login-common/master.h Sat Jun 30 19:14:08 2007 +0300
@@ -5,7 +5,8 @@ struct client;
#include "../master/master-login-interface.h"
-typedef void master_callback_t(struct client *client, bool success);
+typedef void master_callback_t(struct client *client,
+ enum master_login_status status);
void master_request_login(struct client *client, master_callback_t *callback,
unsigned int auth_pid, unsigned int auth_id);
diff -r 9265c13c4103 -r 21e529b8a701 src/login-common/sasl-server.c
--- a/src/login-common/sasl-server.c Sat Jun 30 19:01:06 2007 +0300
+++ b/src/login-common/sasl-server.c Sat Jun 30 19:14:08 2007 +0300
@@ -37,11 +37,24 @@ call_client_callback(struct client *clie
/* NOTE: client may be destroyed now */
}
-static void master_callback(struct client *client, bool success)
-{
+static void
+master_callback(struct client *client, enum master_login_status status)
+{
+ enum sasl_server_reply reply = SASL_SERVER_REPLY_MASTER_FAILED;
+ const char *data = NULL;
+
client->authenticating = FALSE;
- call_client_callback(client, success ? SASL_SERVER_REPLY_SUCCESS :
- SASL_SERVER_REPLY_MASTER_FAILED, NULL, NULL);
+ switch (status) {
+ case MASTER_LOGIN_STATUS_OK:
+ reply = SASL_SERVER_REPLY_SUCCESS;
+ break;
+ case MASTER_LOGIN_STATUS_INTERNAL_ERROR:
+ break;
+ case MASTER_LOGIN_STATUS_MAX_CONNECTIONS:
+ data = "Maximum number of connections exceeded";
+ break;
+ }
+ call_client_callback(client, reply, data, NULL);
}
static void authenticate_callback(struct auth_request *request, int status,
diff -r 9265c13c4103 -r 21e529b8a701 src/master/child-process.c
--- a/src/master/child-process.c Sat Jun 30 19:01:06 2007 +0300
+++ b/src/master/child-process.c Sat Jun 30 19:14:08 2007 +0300
@@ -153,8 +153,10 @@ static void sigchld_handler(int signo __
WTERMSIG(status));
}
- if (destroy_callbacks[process_type] != NULL)
- destroy_callbacks[process_type](process, abnormal_exit);
+ if (destroy_callbacks[process_type] != NULL) {
+ destroy_callbacks[process_type](process, pid,
+ abnormal_exit);
+ }
}
if (pid == -1 && errno != EINTR && errno != ECHILD)
diff -r 9265c13c4103 -r 21e529b8a701 src/master/child-process.h
--- a/src/master/child-process.h Sat Jun 30 19:01:06 2007 +0300
+++ b/src/master/child-process.h Sat Jun 30 19:14:08 2007 +0300
@@ -18,8 +18,8 @@ struct child_process {
enum process_type type;
};
-typedef void child_process_destroy_callback_t(struct child_process *,
- bool abnormal_exit);
+typedef void child_process_destroy_callback_t(struct child_process *process,
+ pid_t pid, bool abnormal_exit);
extern const char *process_names[];
extern struct hash_table *processes;
diff -r 9265c13c4103 -r 21e529b8a701 src/master/dict-process.c
--- a/src/master/dict-process.c Sat Jun 30 19:01:06 2007 +0300
+++ b/src/master/dict-process.c Sat Jun 30 19:14:08 2007 +0300
@@ -159,6 +159,7 @@ static void dict_process_unlisten(struct
static void
dict_process_destroyed(struct child_process *process,
+ pid_t pid __attr_unused__,
bool abnormal_exit __attr_unused__)
{
struct dict_process *p = (struct dict_process *)process;
diff -r 9265c13c4103 -r 21e529b8a701 src/master/login-process.c
--- a/src/master/login-process.c Sat Jun 30 19:01:06 2007 +0300
+++ b/src/master/login-process.c Sat Jun 30 19:14:08 2007 +0300
@@ -94,12 +94,12 @@ void auth_master_callback(const char *us
memset(&master_reply, 0, sizeof(master_reply));
if (user == NULL)
- master_reply.success = FALSE;
+ master_reply.status = MASTER_LOGIN_STATUS_INTERNAL_ERROR;
else {
struct login_group *group = request->process->group;
t_push();
- master_reply.success =
+ master_reply.status =
create_mail_process(group->mail_process_type,
group->set,
request->fd, &request->local_ip,
@@ -683,7 +683,8 @@ static pid_t create_login_process(struct
}
static void
-login_process_destroyed(struct child_process *process, bool abnormal_exit)
+login_process_destroyed(struct child_process *process,
+ pid_t pid __attr_unused__, bool abnormal_exit)
{
struct login_process *p = (struct login_process *)process;
@@ -910,8 +911,6 @@ void login_processes_init(void)
void login_processes_deinit(void)
{
- login_processes_destroy_all();
-
if (to != NULL)
timeout_remove(&to);
if (io_listen != NULL)
diff -r 9265c13c4103 -r 21e529b8a701 src/master/mail-process.c
--- a/src/master/mail-process.c Sat Jun 30 19:01:06 2007 +0300
+++ b/src/master/mail-process.c Sat Jun 30 19:14:08 2007 +0300
@@ -1,7 +1,8 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002 Timo Sirainen */
#include "common.h"
#include "array.h"
+#include "hash.h"
#include "fd-close-on-exec.h"
#include "env-util.h"
#include "str.h"
@@ -12,6 +13,7 @@
#include "home-expand.h"
#include "var-expand.h"
#include "mail-process.h"
+#include "master-login-interface.h"
#include "login-process.h"
#include "log.h"
@@ -31,10 +33,76 @@
many seconds to finish. */
#define CHDIR_WARN_SECS 10
-static struct child_process imap_child_process = { PROCESS_TYPE_IMAP };
-static struct child_process pop3_child_process = { PROCESS_TYPE_POP3 };
-
+struct mail_process_group {
+ /* process.type / user identifies this process group */
+ struct child_process process;
+ char *user;
+
+ /* processes array acts also as refcount */
+ ARRAY_DEFINE(processes, pid_t);
+};
+
+/* type+user -> struct mail_process_group */
+static struct hash_table *mail_process_groups;
static unsigned int mail_process_count = 0;
+
+static unsigned int mail_process_group_hash(const void *p)
+{
+ const struct mail_process_group *group = p;
+
+ return str_hash(group->user) ^ group->process.type;
+}
+
+static int mail_process_group_cmp(const void *p1, const void *p2)
+{
+ const struct mail_process_group *group1 = p1, *group2 = p2;
+ int ret;
+
+ ret = strcmp(group1->user, group2->user);
+ if (ret == 0)
+ ret = group1->process.type - group2->process.type;
+ return ret;
+}
+
+static struct mail_process_group *
+mail_process_group_lookup(enum process_type type, const char *user)
+{
+ struct mail_process_group lookup_group;
+
+ lookup_group.process.type = type;
+ lookup_group.user = t_strdup_noconst(user);
+
+ return hash_lookup(mail_process_groups, &lookup_group);
+}
+
+static struct mail_process_group *
+mail_process_group_create(enum process_type type, const char *user)
+{
+ struct mail_process_group *group;
+
+ group = i_new(struct mail_process_group, 1);
+ group->process.type = type;
+ group->user = i_strdup(user);
+
+ i_array_init(&group->processes, 10);
+ hash_insert(mail_process_groups, group, group);
+ return group;
+}
+
+static void
+mail_process_group_add(struct mail_process_group *group, pid_t pid)
+{
+ mail_process_count++;
+ array_append(&group->processes, &pid, 1);
+ child_process_add(pid, &group->process);
+}
+
+static void mail_process_group_free(struct mail_process_group *group)
+{
+ array_free(&group->processes);
+ i_free(group->user);
+ i_free(group);
+}
static bool validate_uid_gid(struct settings *set, uid_t uid, gid_t gid,
const char *user)
@@ -422,15 +490,17 @@ static void nfs_warn_if_found(const char
"If you're sure this check was wrong, set nfs_check=no.", path);
}
-bool create_mail_process(enum process_type process_type, struct settings *set,
- int socket, const struct ip_addr *local_ip,
- const struct ip_addr *remote_ip,
- const char *user, const char *const *args,
- bool dump_capability)
+enum master_login_status
More information about the dovecot-cvs
mailing list