changeset 9283:02721ba17309 HEAD

login processes: Added initial support for per-connection configuration.
author Timo Sirainen <tss@iki.fi>
date Thu, 14 May 2009 19:01:28 -0400
parents 6bb773332683
children 90312c7416c3
files src/imap-login/client-authenticate.c src/imap-login/client-authenticate.h src/imap-login/client.c src/imap-login/imap-proxy.c src/login-common/client-common.c src/login-common/client-common.h src/login-common/common.h src/login-common/login-proxy.c src/login-common/login-settings.c src/login-common/login-settings.h src/login-common/main.c src/login-common/sasl-server.c src/login-common/ssl-proxy-openssl.c src/login-common/ssl-proxy.h src/pop3-login/client-authenticate.c src/pop3-login/client.c src/pop3-login/pop3-proxy.c
diffstat 17 files changed, 145 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap-login/client-authenticate.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/imap-login/client-authenticate.c	Thu May 14 19:01:28 2009 -0400
@@ -22,7 +22,7 @@
 
 #define IMAP_SERVICE_NAME "imap"
 
-const char *client_authenticate_get_capabilities(bool secured)
+const char *client_authenticate_get_capabilities(struct imap_client *client)
 {
 	const struct auth_mech_desc *mech;
 	unsigned int i, count;
@@ -36,7 +36,8 @@
 		   c) we allow insecure authentication
 		*/
 		if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
-		    (secured || !login_settings->disable_plaintext_auth ||
+		    (client->common.secured ||
+		     !client->common.set->disable_plaintext_auth ||
 		     (mech[i].flags & MECH_SEC_PLAINTEXT) == 0)) {
 			str_append_c(str, ' ');
 			str_append(str, "AUTH=");
@@ -165,7 +166,7 @@
 			master_user = value;
 		else if (strcmp(key, "user") == 0) {
 			/* already handled in login-common */
-		} else if (login_settings->auth_debug)
+		} else if (client->common.set->auth_debug)
 			i_info("Ignoring unknown passdb extra field: %s", key);
 	}
 
@@ -353,8 +354,8 @@
 	}
 
 	if (!client->common.secured &&
-	    strcmp(login_settings->ssl, "required") == 0) {
-		if (login_settings->verbose_auth) {
+	    strcmp(client->common.set->ssl, "required") == 0) {
+		if (client->common.set->verbose_auth) {
 			client_syslog(&client->common, "Login failed: "
 				      "SSL required for authentication");
 		}
@@ -387,8 +388,9 @@
 	user = IMAP_ARG_STR(&args[0]);
 	pass = IMAP_ARG_STR(&args[1]);
 
-	if (!client->common.secured && login_settings->disable_plaintext_auth) {
-		if (login_settings->verbose_auth) {
+	if (!client->common.secured &&
+	    client->common.set->disable_plaintext_auth) {
+		if (client->common.set->verbose_auth) {
 			client_syslog(&client->common, "Login failed: "
 				      "Plaintext authentication disabled");
 		}
--- a/src/imap-login/client-authenticate.h	Thu May 14 18:52:54 2009 -0400
+++ b/src/imap-login/client-authenticate.h	Thu May 14 19:01:28 2009 -0400
@@ -8,7 +8,7 @@
 #define IMAP_AUTHZ_FAILED_MSG \
 	"["IMAP_RESP_CODE_AUTHZFAILED"] Authorization failed"
 
-const char *client_authenticate_get_capabilities(bool secured);
+const char *client_authenticate_get_capabilities(struct imap_client *client);
 
 int cmd_login(struct imap_client *client, const struct imap_arg *args);
 int cmd_authenticate(struct imap_client *client, const struct imap_arg *args);
--- a/src/imap-login/client.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/imap-login/client.c	Thu May 14 19:01:28 2009 -0400
@@ -56,8 +56,8 @@
 {
 	const char *addr;
 
-	if (!login_settings->verbose_proctitle ||
-	    !login_settings->login_process_per_connection)
+	if (!client->common.set->verbose_proctitle ||
+	    !client->common.set->login_process_per_connection)
 		return;
 
 	addr = net_ip2addr(&client->common.ip);
@@ -100,12 +100,12 @@
 {
 	const char *auths;
 
-	auths = client_authenticate_get_capabilities(client->common.secured);
-	return t_strconcat(full ? login_settings->capability_string :
+	auths = client_authenticate_get_capabilities(client);
+	return t_strconcat(full ? client->common.set->capability_string :
 			   CAPABILITY_BANNER_STRING,
 			   (ssl_initialized && !client->common.tls) ?
 			   " STARTTLS" : "",
-			   login_settings->disable_plaintext_auth &&
+			   client->common.set->disable_plaintext_auth &&
 			   !client->common.secured ?
 			   " LOGINDISABLED" : "", auths, NULL);
 }
@@ -128,7 +128,7 @@
 		return;
 
 	fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
-			       &client->common.proxy);
+			       client->common.set, &client->common.proxy);
 	if (fd_ssl == -1) {
 		client_send_line(client, "* BYE TLS initialization failed.");
 		client_destroy(client,
@@ -431,7 +431,8 @@
 
 void client_destroy_oldest(void)
 {
-	unsigned int max_connections = login_settings->login_max_connections;
+	unsigned int max_connections =
+		global_login_settings->login_max_connections;
 	struct client *client;
 	struct imap_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
 	unsigned int i, destroy_count;
@@ -474,7 +475,7 @@
 	greet = t_str_new(128);
 	str_append(greet, "* OK ");
 	str_printfa(greet, "[CAPABILITY %s] ", get_capability(client, FALSE));
-	str_append(greet, login_settings->login_greeting);
+	str_append(greet, client->common.set->login_greeting);
 
 	client_send_line(client, str_c(greet));
 	client->greeting_sent = TRUE;
@@ -501,14 +502,16 @@
 			    client_auth_waiting_timeout, client);
 }
 
-struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip,
-			     const struct ip_addr *ip)
+struct client *client_create(int fd, bool ssl, pool_t pool,
+			     const struct login_settings *set,
+			     const struct ip_addr *local_ip,
+			     const struct ip_addr *remote_ip)
 {
 	struct imap_client *client;
 
 	i_assert(fd != -1);
 
-	if (clients_get_count() >= login_settings->login_max_connections) {
+	if (clients_get_count() >= set->login_max_connections) {
 		/* reached max. users count, kill few of the
 		   oldest connections */
 		client_destroy_oldest();
@@ -517,17 +520,19 @@
 	/* always use nonblocking I/O */
 	net_set_nonblock(fd, TRUE);
 
-	client = i_new(struct imap_client, 1);
+	client = p_new(pool, struct imap_client, 1);
 	client->created = ioloop_time;
 	client->refcount = 1;
 
+	client->common.pool = pool;
+	client->common.set = set;
 	client->common.local_ip = *local_ip;
-	client->common.ip = *ip;
+	client->common.ip = *remote_ip;
 	client->common.fd = fd;
 	client->common.tls = ssl;
 	client->common.trusted = client_is_trusted(&client->common);
 	client->common.secured = ssl || client->common.trusted ||
-		net_ip_compare(ip, local_ip);
+		net_ip_compare(remote_ip, local_ip);
 
 	client_open_streams(client, fd);
 	client->io = io_add(fd, IO_READ, client_input, client);
--- a/src/imap-login/imap-proxy.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/imap-login/imap-proxy.c	Thu May 14 19:01:28 2009 -0400
@@ -128,7 +128,7 @@
 	backend_capabilities =
 		capabilities_strip_prelogin(t_strsplit(capability, " "));
 	proxy_capabilities =
-		capabilities_strip_prelogin(t_strsplit(login_settings->capability_string, " "));
+		capabilities_strip_prelogin(t_strsplit(client->common.set->capability_string, " "));
 
 	if (str_array_icmp(backend_capabilities, proxy_capabilities))
 		return;
@@ -290,7 +290,7 @@
 		return 1;
 	} else if (strncmp(line, "L ", 2) == 0) {
 		line += 2;
-		if (login_settings->verbose_auth) {
+		if (client->common.set->verbose_auth) {
 			str = t_str_new(128);
 			str_printfa(str, "proxy(%s): Login failed to %s:%u",
 				    client->common.virtual_user,
--- a/src/login-common/client-common.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/client-common.c	Thu May 14 19:01:28 2009 -0400
@@ -90,7 +90,6 @@
 		tab[12].value = ssl_proxy_get_security_string(client->proxy);
 	}
 	tab[13].value = dec2str(client->mail_pid);
-
 	return tab;
 }
 
@@ -119,7 +118,8 @@
 	};
 	const struct var_expand_table *var_expand_table;
 	struct var_expand_table *tab;
-	const char *p, *const *e;
+	const char *p;
+	char *const *e;
 	string_t *str;
 
 	var_expand_table = get_var_expand_table(client);
@@ -128,7 +128,7 @@
 	memcpy(tab, static_tab, sizeof(static_tab));
 
 	str = t_str_new(256);
-	for (e = login_settings->log_format_elements_split; *e != NULL; e++) {
+	for (e = client->set->log_format_elements_split; *e != NULL; e++) {
 		for (p = *e; *p != '\0'; p++) {
 			if (*p != '%' || p[1] == '\0')
 				continue;
@@ -147,7 +147,7 @@
 	tab[1].value = msg;
 	str_truncate(str, 0);
 
-	var_expand(str, login_settings->login_log_format, tab);
+	var_expand(str, client->set->login_log_format, tab);
 	return str_c(str);
 }
 
@@ -171,10 +171,10 @@
 	struct ip_addr net_ip;
 	unsigned int bits;
 
-	if (login_settings->login_trusted_networks == NULL)
+	if (client->set->login_trusted_networks == NULL)
 		return FALSE;
 
-	net = t_strsplit_spaces(login_settings->login_trusted_networks, ", ");
+	net = t_strsplit_spaces(client->set->login_trusted_networks, ", ");
 	for (; *net != NULL; net++) {
 		if (net_parse_range(*net, &net_ip, &bits) < 0) {
 			i_error("login_trusted_networks: "
@@ -190,7 +190,7 @@
 
 const char *client_get_extra_disconnect_reason(struct client *client)
 {
-	if (login_settings->ssl_require_client_cert && client->proxy != NULL) {
+	if (client->set->ssl_require_client_cert && client->proxy != NULL) {
 		if (ssl_proxy_has_broken_client_cert(client->proxy))
 			return "(client sent an invalid cert)";
 		if (!ssl_proxy_has_valid_client_cert(client->proxy))
@@ -203,7 +203,7 @@
 	/* some auth attempts without SSL/TLS */
 	if (client->auth_tried_disabled_plaintext)
 		return "(tried to use disabled plaintext auth)";
-	if (login_settings->ssl_require_client_cert)
+	if (client->set->ssl_require_client_cert)
 		return "(cert required, client didn't start TLS)";
 
 	return t_strdup_printf("(auth failed, %u attempts)",
--- a/src/login-common/client-common.h	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/client-common.h	Thu May 14 19:01:28 2009 -0400
@@ -14,11 +14,13 @@
 
 struct client {
 	struct client *prev, *next;
+	pool_t pool;
 
 	struct ip_addr local_ip;
 	struct ip_addr ip;
 	unsigned int local_port, remote_port;
 	struct ssl_proxy *proxy;
+	const struct login_settings *set;
 
 	int fd;
 	struct istream *input;
@@ -45,8 +47,10 @@
 
 extern struct client *clients;
 
-struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip,
-			     const struct ip_addr *ip);
+struct client *client_create(int fd, bool ssl, pool_t pool,
+			     const struct login_settings *set,
+			     const struct ip_addr *local_ip,
+			     const struct ip_addr *remote_ip);
 
 void client_link(struct client *client);
 void client_unlink(struct client *client);
--- a/src/login-common/common.h	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/common.h	Thu May 14 19:01:28 2009 -0400
@@ -19,6 +19,6 @@
 extern int anvil_fd;
 
 extern struct master_service *service;
-extern struct login_settings *login_settings;
+extern const struct login_settings *global_login_settings;
 
 #endif
--- a/src/login-common/login-proxy.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/login-proxy.c	Thu May 14 19:01:28 2009 -0400
@@ -358,6 +358,7 @@
 	io_remove(&proxy->server_io);
 
 	fd = ssl_proxy_client_new(proxy->server_fd, &proxy->ip,
+				  proxy->prelogin_client->set,
 				  login_proxy_ssl_handshaked, proxy,
 				  &proxy->ssl_proxy);
 	if (fd < 0) {
--- a/src/login-common/login-settings.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/login-settings.c	Thu May 14 19:01:28 2009 -0400
@@ -51,7 +51,7 @@
 static struct login_settings login_default_settings = {
 	MEMBER(login_chroot) TRUE,
 	MEMBER(login_trusted_networks) "",
-	MEMBER(login_greeting) PACKAGE" ready.",
+	MEMBER(login_greeting) PACKAGE_NAME" ready.",
 	MEMBER(login_log_format_elements) "user=<%u> method=%m rip=%r lip=%l %c",
 	MEMBER(login_log_format) "%$: %s",
 
@@ -127,13 +127,12 @@
 #endif
 }
 
-static bool login_settings_check(void *_set, pool_t pool ATTR_UNUSED,
-				 const char **error_r)
+static bool login_settings_check(void *_set, pool_t pool, const char **error_r)
 {
 	struct login_settings *set = _set;
 
 	set->log_format_elements_split =
-		t_strsplit(set->login_log_format_elements, " ");
+		p_strsplit(pool, set->login_log_format_elements, " ");
 
 	if (set->ssl_require_client_cert || set->ssl_username_from_cert) {
 		/* if we require valid cert, make sure we also ask for it */
@@ -162,7 +161,10 @@
 }
 /* </settings checks> */
 
-struct login_settings *login_settings_read(struct master_service *service)
+struct login_settings *
+login_settings_read(struct master_service *service, pool_t pool,
+		    const struct ip_addr *local_ip,
+		    const struct ip_addr *remote_ip)
 {
 	static const struct setting_parser_info *set_roots[] = {
 		&login_setting_parser_info,
@@ -171,15 +173,27 @@
 	struct master_service_settings_input input;
 	const char *error;
 	void **sets;
+	struct login_settings *set;
 
 	memset(&input, 0, sizeof(input));
 	input.roots = set_roots;
 	input.module = "login";
 	input.service = login_protocol;
 
+	if (local_ip != NULL)
+		input.local_ip = *local_ip;
+	if (remote_ip != NULL)
+		input.remote_ip = *remote_ip;
+
+	/* this function always clears the previous settings pool. since we're
+	   doing per-connection lookups, we always need to duplicate the
+	   settings using another pool. */
 	if (master_service_settings_read(service, &input, &error) < 0)
 		i_fatal("Error reading configuration: %s", error);
 
 	sets = master_service_settings_get_others(service);
-	return sets[0];
+	set = settings_dup(&login_setting_parser_info, sets[0], pool);
+	if (!login_settings_check(set, pool, &error))
+		i_fatal("login_settings_check() failed: %s", error);
+	return set;
 }
--- a/src/login-common/login-settings.h	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/login-settings.h	Thu May 14 19:01:28 2009 -0400
@@ -34,9 +34,12 @@
 	unsigned int mail_max_userip_connections;
 
 	/* generated: */
-	const char *const *log_format_elements_split;
+	char *const *log_format_elements_split;
 };
 
-struct login_settings *login_settings_read(struct master_service *service);
+struct login_settings *
+login_settings_read(struct master_service *service, pool_t pool,
+		    const struct ip_addr *local_ip,
+		    const struct ip_addr *remote_ip);
 
 #endif
--- a/src/login-common/main.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/main.c	Thu May 14 19:01:28 2009 -0400
@@ -23,7 +23,7 @@
 int anvil_fd = -1;
 
 struct master_service *service;
-struct login_settings *login_settings;
+const struct login_settings *global_login_settings;
 
 static bool ssl_connections = FALSE;
 
@@ -32,7 +32,9 @@
 	struct client *client;
 	struct ssl_proxy *proxy;
 	struct ip_addr local_ip;
+	const struct login_settings *set;
 	unsigned int local_port;
+	pool_t pool;
 	int fd_ssl;
 
 	if (net_getsockname(conn->fd, &local_ip, &local_port) < 0) {
@@ -40,21 +42,26 @@
 		local_port = 0;
 	}
 
+	pool = pool_alloconly_create("login client", 1024);
+	set = login_settings_read(service, pool, &local_ip, &conn->remote_ip);
+
 	if (!ssl_connections && !conn->ssl) {
-		client = client_create(conn->fd, FALSE, &local_ip,
+		client = client_create(conn->fd, FALSE, pool, set, &local_ip,
 				       &conn->remote_ip);
 	} else {
-		fd_ssl = ssl_proxy_new(conn->fd, &conn->remote_ip, &proxy);
+		fd_ssl = ssl_proxy_new(conn->fd, &conn->remote_ip, set, &proxy);
 		if (fd_ssl == -1) {
 			net_disconnect(conn->fd);
+			pool_unref(&pool);
 			return;
 		}
 
-		client = client_create(fd_ssl, TRUE,
+		client = client_create(fd_ssl, TRUE, pool, set,
 				       &local_ip, &conn->remote_ip);
 		client->proxying = TRUE;
 		client->proxy = proxy;
 	}
+
 	client->remote_port = conn->remote_port;
 	client->local_port = local_port;
 }
@@ -95,13 +102,14 @@
 	   normal connections each use one fd, but SSL connections use two */
 	max_fds = MASTER_LISTEN_FD_FIRST + 16 +
 		master_service_get_socket_count(service) +
-		login_settings->login_max_connections*2;
+		global_login_settings->login_max_connections*2;
 	restrict_fd_limit(max_fds);
 	io_loop_set_max_fd_count(current_ioloop, max_fds);
 
-	i_assert(strcmp(login_settings->ssl, "no") == 0 || ssl_initialized);
+	i_assert(strcmp(global_login_settings->ssl, "no") == 0 ||
+		 ssl_initialized);
 
-	if (login_settings->mail_max_userip_connections > 0)
+	if (global_login_settings->mail_max_userip_connections > 0)
 		anvil_fd = anvil_connect();
 
 	restrict_access_by_env(NULL, TRUE);
@@ -143,11 +151,14 @@
 int main(int argc, char *argv[], char *envp[])
 {
 	const char *getopt_str;
+	pool_t set_pool;
 	int c;
 
 	//FIXME:is_inetd = getenv("DOVECOT_MASTER") == NULL;
 
-	service = master_service_init(login_process_name, 0, argc, argv);
+	service = master_service_init(login_process_name,
+				      MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN,
+				      argc, argv);
 	master_service_init_log(service, t_strconcat(login_process_name, ": ",
 						     NULL), 0);
 
@@ -176,7 +187,9 @@
 #endif
 
 	process_title_init(argv, envp);
-        login_settings = login_settings_read(service);
+	set_pool = pool_alloconly_create("global login settings", 1024);
+	global_login_settings =
+		login_settings_read(service, set_pool, NULL, NULL);
 
 	main_preinit();
 	master_service_init_finish(service);
@@ -184,6 +197,7 @@
 
 	master_service_run(service, client_connected);
 	main_deinit();
+	pool_unref(&set_pool);
 	master_service_deinit(&service);
         return 0;
 }
--- a/src/login-common/sasl-server.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/sasl-server.c	Thu May 14 19:01:28 2009 -0400
@@ -105,7 +105,7 @@
 
 	if (client->virtual_user == NULL)
 		return FALSE;
-	if (login_settings->mail_max_userip_connections == 0)
+	if (client->set->mail_max_userip_connections == 0)
 		return FALSE;
 
 	ident = t_strconcat("LOOKUP\t", net_ip2addr(&client->ip), "/",
@@ -123,7 +123,7 @@
 	buf[ret-1] = '\0';
 
 	return strtoul(buf, NULL, 10) >=
-		login_settings->mail_max_userip_connections;
+		client->set->mail_max_userip_connections;
 }
 
 static void authenticate_callback(struct auth_request *request, int status,
@@ -219,7 +219,7 @@
 		return;
 	}
 
-	if (!client->secured && login_settings->disable_plaintext_auth &&
+	if (!client->secured && client->set->disable_plaintext_auth &&
 	    (mech->flags & MECH_SEC_PLAINTEXT) != 0) {
 		sasl_server_auth_failed(client,
 			"Plaintext authentication disabled.");
@@ -252,7 +252,7 @@
 {
 	i_assert(client->authenticating);
 
-	if (login_settings->verbose_auth && reason != NULL) {
+	if (client->set->verbose_auth && reason != NULL) {
 		const char *auth_name =
 			str_sanitize(client->auth_mech_name, MAX_MECH_NAME);
 		client_syslog(client,
--- a/src/login-common/ssl-proxy-openssl.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/ssl-proxy-openssl.c	Thu May 14 19:01:28 2009 -0400
@@ -42,6 +42,7 @@
 
 	SSL *ssl;
 	struct ip_addr ip;
+	const struct login_settings *set;
 
 	int fd_ssl, fd_plain;
 	struct io *io_ssl_read, *io_ssl_write, *io_plain_read, *io_plain_write;
@@ -496,6 +497,7 @@
 
 static int
 ssl_proxy_new_common(SSL_CTX *ssl_ctx, int fd, const struct ip_addr *ip,
+		     const struct login_settings *set,
 		     struct ssl_proxy **proxy_r)
 {
 	struct ssl_proxy *proxy;
@@ -538,6 +540,7 @@
 	proxy = i_new(struct ssl_proxy, 1);
 	proxy->refcount = 2;
 	proxy->ssl = ssl;
+	proxy->set = set;
 	proxy->fd_ssl = fd;
 	proxy->fd_plain = sfd[0];
 	proxy->ip = *ip;
@@ -550,11 +553,13 @@
 	return sfd[1];
 }
 
-int ssl_proxy_new(int fd, const struct ip_addr *ip, struct ssl_proxy **proxy_r)
+int ssl_proxy_new(int fd, const struct ip_addr *ip,
+		  const struct login_settings *set, struct ssl_proxy **proxy_r)
 {
 	int ret;
 
-	if ((ret = ssl_proxy_new_common(ssl_server_ctx, fd, ip, proxy_r)) < 0)
+	ret = ssl_proxy_new_common(ssl_server_ctx, fd, ip, set, proxy_r);
+	if (ret < 0)
 		return -1;
 
 	ssl_step(*proxy_r);
@@ -562,12 +567,14 @@
 }
 
 int ssl_proxy_client_new(int fd, struct ip_addr *ip,
+			 const struct login_settings *set,
 			 ssl_handshake_callback_t *callback, void *context,
 			 struct ssl_proxy **proxy_r)
 {
 	int ret;
 
-	if ((ret = ssl_proxy_new_common(ssl_client_ctx, fd, ip, proxy_r)) < 0)
+	ret = ssl_proxy_new_common(ssl_client_ctx, fd, ip, set, proxy_r);
+	if (ret < 0)
 		return -1;
 
 	(*proxy_r)->handshake_callback = callback;
@@ -724,8 +731,8 @@
 	proxy = SSL_get_ex_data(ssl, extdata_index);
 	proxy->cert_received = TRUE;
 
-	if (login_settings->verbose_ssl ||
-	    (login_settings->verbose_auth && !preverify_ok)) {
+	if (proxy->set->verbose_ssl ||
+	    (proxy->set->verbose_auth && !preverify_ok)) {
 		char buf[1024];
 		X509_NAME *subject;
 
@@ -927,7 +934,7 @@
 
 void ssl_proxy_init(void)
 {
-	const struct login_settings *set = login_settings;
+	const struct login_settings *set = global_login_settings;
 	static char dovecot[] = "dovecot";
 	unsigned char buf;
 
--- a/src/login-common/ssl-proxy.h	Thu May 14 18:52:54 2009 -0400
+++ b/src/login-common/ssl-proxy.h	Thu May 14 19:01:28 2009 -0400
@@ -5,6 +5,7 @@
 
 struct ip_addr;
 struct ssl_proxy;
+struct login_settings;
 
 extern bool ssl_initialized;
 
@@ -13,8 +14,10 @@
 /* establish SSL connection with the given fd, returns a new fd which you
    must use from now on, or -1 if error occurred. Unless -1 is returned,
    the given fd must be simply forgotten. */
-int ssl_proxy_new(int fd, const struct ip_addr *ip, struct ssl_proxy **proxy_r);
+int ssl_proxy_new(int fd, const struct ip_addr *ip,
+		  const struct login_settings *set, struct ssl_proxy **proxy_r);
 int ssl_proxy_client_new(int fd, struct ip_addr *ip,
+			 const struct login_settings *set,
 			 ssl_handshake_callback_t *callback, void *context,
 			 struct ssl_proxy **proxy_r);
 bool ssl_proxy_has_valid_client_cert(const struct ssl_proxy *proxy) ATTR_PURE;
--- a/src/pop3-login/client-authenticate.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/pop3-login/client-authenticate.c	Thu May 14 19:01:28 2009 -0400
@@ -36,7 +36,8 @@
 
 	if (ssl_initialized && !client->common.tls)
 		str_append(str, "STLS\r\n");
-	if (!login_settings->disable_plaintext_auth || client->common.secured)
+	if (!client->common.set->disable_plaintext_auth ||
+	    client->common.secured)
 		str_append(str, "USER\r\n");
 
 	str_append(str, "SASL");
@@ -48,7 +49,7 @@
 		*/
 		if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
 		    (client->common.secured ||
-		     !login_settings->disable_plaintext_auth ||
+		     !client->common.set->disable_plaintext_auth ||
 		     (mech[i].flags & MECH_SEC_PLAINTEXT) == 0)) {
 			str_append_c(str, ' ');
 			str_append(str, mech[i].name);
@@ -166,7 +167,7 @@
 			master_user = value;
 		else if (strcmp(key, "user") == 0) {
 			/* already handled in login-common */
-		} else if (login_settings->auth_debug)
+		} else if (client->common.set->auth_debug)
 			i_info("Ignoring unknown passdb extra field: %s", key);
 	}
 
@@ -280,8 +281,8 @@
 	const char *mech_name, *p;
 
 	if (!client->common.secured &&
-	    strcmp(login_settings->ssl, "required") == 0) {
-		if (login_settings->verbose_auth) {
+	    strcmp(client->common.set->ssl, "required") == 0) {
+		if (client->common.set->verbose_auth) {
 			client_syslog(&client->common, "Login failed: "
 				      "SSL required for authentication");
 		}
@@ -300,7 +301,7 @@
 		for (i = 0; i < count; i++) {
 			if ((mech[i].flags & MECH_SEC_PRIVATE) == 0 &&
 			    (client->common.secured ||
-			     login_settings->disable_plaintext_auth ||
+			     client->common.set->disable_plaintext_auth ||
 			     (mech[i].flags & MECH_SEC_PLAINTEXT) == 0))
 		 		client_send_line(client, mech[i].name);
 		}
@@ -333,10 +334,10 @@
 static bool check_plaintext_auth(struct pop3_client *client)
 {
 	if (client->common.secured ||
-	    !login_settings->disable_plaintext_auth)
+	    !client->common.set->disable_plaintext_auth)
 		return TRUE;
 
-	if (login_settings->verbose_auth) {
+	if (client->common.set->verbose_auth) {
 		client_syslog(&client->common, "Login failed: "
 			      "Plaintext authentication disabled");
 	}
@@ -406,7 +407,7 @@
 	const char *p;
 
 	if (client->apop_challenge == NULL) {
-		if (login_settings->verbose_auth) {
+		if (client->common.set->verbose_auth) {
 			client_syslog(&client->common,
 				      "APOP failed: APOP not enabled");
 		}
@@ -417,7 +418,7 @@
 	/* <username> <md5 sum in hex> */
 	p = strchr(args, ' ');
 	if (p == NULL || strlen(p+1) != 32) {
-		if (login_settings->verbose_auth) {
+		if (client->common.set->verbose_auth) {
 			client_syslog(&client->common,
 				      "APOP failed: Invalid parameters");
 		}
@@ -433,7 +434,7 @@
 	buffer_append_c(apop_data, '\0');
 
 	if (hex_to_binary(p+1, apop_data) < 0) {
-		if (login_settings->verbose_auth) {
+		if (client->common.set->verbose_auth) {
 			client_syslog(&client->common, "APOP failed: "
 				      "Invalid characters in MD5 response");
 		}
--- a/src/pop3-login/client.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/pop3-login/client.c	Thu May 14 19:01:28 2009 -0400
@@ -42,8 +42,8 @@
 {
 	const char *addr;
 
-	if (!login_settings->verbose_proctitle ||
-	    !login_settings->login_process_per_connection)
+	if (!client->common.set->verbose_proctitle ||
+	    !client->common.set->login_process_per_connection)
 		return;
 
 	addr = net_ip2addr(&client->common.ip);
@@ -70,7 +70,7 @@
 		return;
 
 	fd_ssl = ssl_proxy_new(client->common.fd, &client->common.ip,
-			       &client->common.proxy);
+			       client->common.set, &client->common.proxy);
 	if (fd_ssl == -1) {
 		client_send_line(client, "-ERR TLS initialization failed.");
 		client_destroy(client,
@@ -229,7 +229,8 @@
 
 void client_destroy_oldest(void)
 {
-	unsigned int max_connections = login_settings->login_max_connections;
+	unsigned int max_connections =
+		global_login_settings->login_max_connections;
 	struct client *client;
 	struct pop3_client *destroy_buf[CLIENT_DESTROY_OLDEST_COUNT];
 	unsigned int i, destroy_count;
@@ -292,7 +293,7 @@
 
 	client->apop_challenge = get_apop_challenge(client);
 	client_send_line(client, t_strconcat("+OK ",
-					     login_settings->login_greeting,
+					     client->common.set->login_greeting,
 					     client->apop_challenge != NULL ?
 					     " " : NULL,
 					     client->apop_challenge, NULL));
@@ -303,14 +304,16 @@
 	client_destroy(client, "Disconnected: Inactivity");
 }
 
-struct client *client_create(int fd, bool ssl, const struct ip_addr *local_ip,
-			     const struct ip_addr *ip)
+struct client *client_create(int fd, bool ssl, pool_t pool,
+			     const struct login_settings *set,
+			     const struct ip_addr *local_ip,
+			     const struct ip_addr *remote_ip)
 {
 	struct pop3_client *client;
 
 	i_assert(fd != -1);
 
-	if (clients_get_count() >= login_settings->login_max_connections) {
+	if (clients_get_count() >= set->login_max_connections) {
 		/* reached max. users count, kill few of the
 		   oldest connections */
 		client_destroy_oldest();
@@ -319,17 +322,19 @@
 	/* always use nonblocking I/O */
 	net_set_nonblock(fd, TRUE);
 
-	client = i_new(struct pop3_client, 1);
+	client = p_new(pool, struct pop3_client, 1);
 	client->created = ioloop_time;
 	client->refcount = 1;
 
+	client->common.pool = pool;
+	client->common.set = set;
 	client->common.local_ip = *local_ip;
-	client->common.ip = *ip;
+	client->common.ip = *remote_ip;
 	client->common.fd = fd;
 	client->common.tls = ssl;
 	client->common.trusted = client_is_trusted(&client->common);
 	client->common.secured = ssl || client->common.trusted ||
-		net_ip_compare(ip, local_ip);
+		net_ip_compare(remote_ip, local_ip);
 
 	client_open_streams(client, fd);
 	client_link(&client->common);
--- a/src/pop3-login/pop3-proxy.c	Thu May 14 18:52:54 2009 -0400
+++ b/src/pop3-login/pop3-proxy.c	Thu May 14 19:01:28 2009 -0400
@@ -188,7 +188,7 @@
 	else
 		client_send_line(client, line);
 
-	if (login_settings->verbose_auth) {
+	if (client->common.set->verbose_auth) {
 		str = t_str_new(128);
 		str_printfa(str, "proxy(%s): Login failed to %s:%u",
 			    client->common.virtual_user,