changeset 2097:4e77cb0aff21 HEAD

Added %l, %r and %P variables and mail_log_prefix setting.
author Timo Sirainen <tss@iki.fi>
date Mon, 31 May 2004 21:04:46 +0300
parents 7e46cf0f3522
children 24e382b88232
files doc/Makefile.am doc/variables.txt dovecot-example.conf src/auth/auth-client-interface.h src/auth/mech.c src/auth/mech.h src/imap-login/client-authenticate.c src/imap-login/client.c src/imap-login/client.h src/lib-auth/auth-client.h src/lib-auth/auth-server-request.c src/login-common/client-common.h src/login-common/main.c src/login-common/master.c src/master/login-process.c src/master/mail-process.c src/master/mail-process.h src/master/master-login-interface.h src/master/master-settings.c src/master/master-settings.h src/pop3-login/client-authenticate.c src/pop3-login/client.c src/pop3-login/client.h
diffstat 23 files changed, 241 insertions(+), 106 deletions(-) [+]
line wrap: on
line diff
--- a/doc/Makefile.am	Mon May 31 00:15:19 2004 +0300
+++ b/doc/Makefile.am	Mon May 31 21:04:46 2004 +0300
@@ -8,7 +8,8 @@
 	mail-storages.txt \
 	multiaccess.txt \
 	nfs.txt \
-	securecoding.txt
+	securecoding.txt \
+	variables.txt
 
 EXTRA_DIST = \
 	mkcert.sh \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/variables.txt	Mon May 31 21:04:46 2004 +0300
@@ -0,0 +1,27 @@
+You can use special variables in several places:
+ - default_mail_env setting
+ - namespace locations
+ - static userdb template string
+ - LDAP and SQL userdb query strings
+ - log prefix for imap/pop3 process
+
+The variables are:
+
+ %u - username
+ %n - user part in user@domain, same as %u if there's no domain
+ %d - domain part in user@domain, empty if user there's no domain
+ %h - home directory
+ %p - protocol (IMAP or POP3)
+ %P - PID of the current process (login or imap/pop3 process)
+ %l - local IP address
+ %r - remote IP address
+
+You can apply a modifiers for each variable (eg. %Lp = pop3):
+
+ %L - lowercase
+ %U - uppercase
+ %E - escape '"', "'" and '\' characters by inserting '\' before them.
+
+You can also limit a width of string by giving the number of max. characters
+after the '%' character. For example %1u gives the first character of
+username.
--- a/dovecot-example.conf	Mon May 31 00:15:19 2004 +0300
+++ b/dovecot-example.conf	Mon May 31 21:04:46 2004 +0300
@@ -160,22 +160,14 @@
 
 # Default MAIL environment to use when it's not set. By leaving this empty
 # dovecot tries to do some automatic detection as described in
-# doc/mail-storages.txt. There's a few special variables you can use:
+# doc/mail-storages.txt. There's a few special variables you can use, eg.:
 #
 #   %u - username
 #   %n - user part in user@domain, same as %u if there's no domain
 #   %d - domain part in user@domain, empty if user there's no domain
 #   %h - home directory
-#   %p - protocol (IMAP or POP3)
 #
-# You can apply a modifiers for each variable (eg. %Lp = pop3):
-#   %L - lowercase
-#   %U - uppercase
-#   %E - escape '"', "'" and '\' characters by inserting '\' before them.
-#
-# You can also limit a width of string by giving the number of max. characters
-# after the '%' character. For example %1u gives the first character of
-# username. Some examples:
+# See doc/variables.txt for full list. Some examples:
 #
 #   default_mail_env = maildir:/var/mail/%1u/%u/Maildir
 #   default_mail_env = mbox:~/mail/:INBOX=/var/mail/%u
@@ -330,6 +322,10 @@
 # files, so it shouldn't harm much even if this limit is set pretty high.
 #mail_process_size = 256
 
+# Log prefix for mail processes. See doc/variables.txt for list of possible
+# variables you can use.
+#mail_log_prefix = "%Up(%u): "
+
 ##
 ## IMAP specific settings
 ##
--- a/src/auth/auth-client-interface.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/auth/auth-client-interface.h	Mon May 31 21:04:46 2004 +0300
@@ -50,6 +50,8 @@
 
 	enum auth_client_request_new_flags flags;
 
+	uint32_t ip_family; /* if non-zero, data begins with local/remote IPs */
+
 	uint32_t protocol_idx;
 	uint32_t mech_idx;
 	uint32_t initial_resp_idx;
--- a/src/auth/mech.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/auth/mech.c	Mon May 31 21:04:46 2004 +0300
@@ -77,9 +77,17 @@
 {
         struct mech_module *mech;
 	struct auth_request *auth_request;
+	size_t ip_size = 1;
+
+	if (request->ip_family == AF_INET)
+		ip_size = 4;
+	else if (request->ip_family != 0)
+		ip_size = sizeof(auth_request->local_ip.ip);
+	else
+		ip_size = 0;
 
 	/* make sure data is NUL-terminated */
-	if (request->data_size == 0 || request->initial_resp_idx == 0 ||
+	if (request->data_size <= ip_size*2 || request->initial_resp_idx == 0 ||
 	    request->mech_idx >= request->data_size ||
 	    request->protocol_idx >= request->data_size ||
 	    request->initial_resp_idx > request->data_size ||
@@ -127,6 +135,16 @@
 			p_strdup(auth_request->pool,
 				 (const char *)data + request->protocol_idx);
 
+		if (request->ip_family != 0) {
+			auth_request->local_ip.family = request->ip_family;
+			auth_request->remote_ip.family = request->ip_family;
+				
+
+			memcpy(&auth_request->local_ip, data, ip_size);
+			memcpy(&auth_request->remote_ip, data + ip_size,
+			       ip_size);
+		}
+
 		hash_insert(conn->auth_requests, POINTER_CAST(request->id),
 			    auth_request);
 
@@ -265,6 +283,10 @@
 		{ 'n', NULL },
 		{ 'd', NULL },
 		{ 'p', NULL },
+		{ 'h', NULL },
+		{ 'l', NULL },
+		{ 'r', NULL },
+		{ 'P', NULL },
 		{ '\0', NULL }
 	};
 	struct var_expand_table *tab;
@@ -281,6 +303,12 @@
 	if (tab[2].value != NULL)
 		tab[2].value = escape_func(tab[2].value+1);
 	tab[3].value = auth_request->protocol;
+	/* tab[4] = we have no home dir */
+	if (auth_request->local_ip.family != 0)
+		tab[5].value = net_ip2addr(&auth_request->local_ip);
+	if (auth_request->remote_ip.family != 0)
+		tab[6].value = net_ip2addr(&auth_request->remote_ip);
+	tab[7].value = dec2str(auth_request->conn->pid);
 	return tab;
 }
 
--- a/src/auth/mech.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/auth/mech.h	Mon May 31 21:04:46 2004 +0300
@@ -1,6 +1,7 @@
 #ifndef __MECH_H
 #define __MECH_H
 
+#include "network.h"
 #include "auth-client-interface.h"
 
 struct auth_client_connection;
@@ -20,6 +21,7 @@
 	time_t created;
 
 	char *protocol;
+	struct ip_addr local_ip, remote_ip;
 	mech_callback_t *callback;
 
 	int (*auth_initial)(struct auth_request *auth_request,
--- a/src/imap-login/client-authenticate.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/imap-login/client-authenticate.c	Mon May 31 21:04:46 2004 +0300
@@ -107,8 +107,6 @@
 {
 	struct imap_client *client = context;
 	const char *error;
-	const void *ptr;
-	size_t size;
 
 	switch (auth_callback(request, reply, data, &client->common,
 			      master_callback, &error)) {
@@ -141,7 +139,8 @@
 int cmd_login(struct imap_client *client, struct imap_arg *args)
 {
 	const char *user, *pass, *error;
-	string_t *str;
+	struct auth_request_info info;
+	string_t *plain_login;
 
 	/* two arguments: username and password */
 	if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
@@ -165,20 +164,26 @@
 	}
 
 	/* authorization ID \0 authentication ID \0 pass */
-	str = t_str_new(64);
-	str_append_c(str, '\0');
-	str_append(str, user);
-	str_append_c(str, '\0');
-	str_append(str, pass);
+	plain_login = t_str_new(64);
+	str_append_c(plain_login, '\0');
+	str_append(plain_login, user);
+	str_append_c(plain_login, '\0');
+	str_append(plain_login, pass);
+
+	memset(&info, 0, sizeof(info));
+	info.mech = "PLAIN";
+	info.protocol = "IMAP";
+	info.flags = client_get_auth_flags(client);
+	info.local_ip = client->common.local_ip;
+	info.remote_ip = client->common.ip;
+	info.initial_resp_data = str_data(plain_login);
+	info.initial_resp_size = str_len(plain_login);
 
 	client_ref(client);
 
 	client->common.auth_request =
-		auth_client_request_new(auth_client, "PLAIN", "IMAP",
-					client_get_auth_flags(client),
-					str_data(str), str_len(str),
-					login_callback,
-					client, &error);
+		auth_client_request_new(auth_client, &info,
+					login_callback, client, &error);
 	if (client->common.auth_request == NULL) {
 		client_send_tagline(client, t_strconcat(
 			"NO Login failed: ", error, NULL));
@@ -278,6 +283,7 @@
 {
 	const struct auth_mech_desc *mech;
 	const char *mech_name, *error;
+	struct auth_request_info info;
 
 	/* we want only one argument: authentication mechanism name */
 	if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
@@ -302,12 +308,17 @@
 		return TRUE;
 	}
 
+	memset(&info, 0, sizeof(info));
+	info.mech = mech->name;
+	info.protocol = "IMAP";
+	info.flags = client_get_auth_flags(client);
+	info.local_ip = client->common.local_ip;
+	info.remote_ip = client->common.ip;
+
 	client_ref(client);
 	client->common.auth_request =
-		auth_client_request_new(auth_client, mech->name, "IMAP",
-					client_get_auth_flags(client),
-					NULL, 0, authenticate_callback,
-					client, &error);
+		auth_client_request_new(auth_client, &info,
+					authenticate_callback, client, &error);
 	if (client->common.auth_request != NULL) {
 		/* following input data will go to authentication */
 		if (client->common.io != NULL)
--- a/src/imap-login/client.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/imap-login/client.c	Mon May 31 21:04:46 2004 +0300
@@ -348,7 +348,8 @@
 	}
 }
 
-struct client *client_create(int fd, struct ip_addr *ip, int ssl)
+struct client *client_create(int fd, int ssl, const struct ip_addr *local_ip,
+			     const struct ip_addr *ip)
 {
 	struct imap_client *client;
 	const char *addr;
@@ -373,6 +374,7 @@
 		(IPADDR_IS_V4(ip) && strncmp(addr, "127.", 4) == 0) ||
 		(IPADDR_IS_V6(ip) && strcmp(addr, "::1") == 0);
 
+	client->common.local_ip = *local_ip;
 	client->common.ip = *ip;
 	client->common.fd = fd;
 
--- a/src/imap-login/client.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/imap-login/client.h	Mon May 31 21:04:46 2004 +0300
@@ -29,7 +29,6 @@
 	unsigned int destroyed:1;
 };
 
-struct client *client_create(int fd, struct ip_addr *ip, int ssl);
 void client_destroy(struct imap_client *client, const char *reason);
 
 void client_send_line(struct imap_client *client, const char *line);
--- a/src/lib-auth/auth-client.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/lib-auth/auth-client.h	Mon May 31 21:04:46 2004 +0300
@@ -1,6 +1,7 @@
 #ifndef __AUTH_CLIENT_H
 #define __AUTH_CLIENT_H
 
+#include "network.h"
 #include "../auth/auth-client-interface.h"
 
 struct auth_client;
@@ -12,6 +13,17 @@
 	unsigned int advertise:1;
 };
 
+struct auth_request_info {
+	const char *mech;
+	const char *protocol;
+	enum auth_client_request_new_flags flags;
+
+	struct ip_addr local_ip, remote_ip;
+
+	const unsigned char *initial_resp_data;
+	size_t initial_resp_size;
+};
+
 /* reply is NULL if auth connection died */
 typedef void auth_request_callback_t(struct auth_request *request,
 				     struct auth_client_request_reply *reply,
@@ -38,10 +50,7 @@
    happens for the request. */
 struct auth_request *
 auth_client_request_new(struct auth_client *client,
-			const char *mech, const char *protocol,
-			enum auth_client_request_new_flags flags,
-			const unsigned char *initial_resp_data,
-			size_t initial_resp_size,
+			const struct auth_request_info *request_info,
 			auth_request_callback_t *callback, void *context,
 			const char **error_r);
 
--- a/src/lib-auth/auth-server-request.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/lib-auth/auth-server-request.c	Mon May 31 21:04:46 2004 +0300
@@ -11,10 +11,11 @@
 struct auth_request {
         struct auth_server_connection *conn;
 
+	unsigned int id;
+
 	char *mech, *protocol;
 	enum auth_client_request_new_flags flags;
-
-	unsigned int id;
+	struct ip_addr local_ip, remote_ip;
 
 	unsigned char *initial_resp_data;
 	size_t initial_resp_size;
@@ -73,6 +74,7 @@
 {
 	struct auth_client_request_new auth_request;
 	buffer_t *buf;
+	size_t size;
 	int ret;
 
 	memset(&auth_request, 0, sizeof(auth_request));
@@ -80,10 +82,20 @@
 	auth_request.id = request->id;
 	auth_request.flags = request->flags;
 
+	if (request->local_ip.family == request->remote_ip.family)
+		auth_request.ip_family = request->local_ip.family;
+
 	t_push();
 	buf = buffer_create_dynamic(pool_datastack_create(), 256, (size_t)-1);
 	buffer_set_used_size(buf, sizeof(auth_request));
 
+	if (auth_request.ip_family != 0) {
+		size = IPADDR_IS_V4(&request->local_ip) ? 4 :
+			sizeof(request->local_ip.ip);
+		buffer_append(buf, &request->local_ip.ip, size);
+		buffer_append(buf, &request->remote_ip.ip, size);
+	}
+
 	auth_request.mech_idx =
 		buffer_get_used_size(buf) - sizeof(auth_request);
 	buffer_append(buf, request->mech, strlen(request->mech)+1);
@@ -236,32 +248,34 @@
 
 struct auth_request *
 auth_client_request_new(struct auth_client *client,
-			const char *mech, const char *protocol,
-			enum auth_client_request_new_flags flags,
-			const unsigned char *initial_resp_data,
-			size_t initial_resp_size,
+			const struct auth_request_info *request_info,
 			auth_request_callback_t *callback, void *context,
 			const char **error_r)
 {
 	struct auth_server_connection *conn;
 	struct auth_request *request;
 
-	conn = auth_server_connection_find_mech(client, mech, error_r);
+	conn = auth_server_connection_find_mech(client, request_info->mech,
+						error_r);
 	if (conn == NULL)
 		return NULL;
 
 	request = i_new(struct auth_request, 1);
 	request->conn = conn;
-	request->mech = i_strdup(mech);
-	request->protocol = i_strdup(protocol);
-	request->flags = flags;
+	request->mech = i_strdup(request_info->mech);
+	request->protocol = i_strdup(request_info->protocol);
+	request->flags = request_info->flags;
+	request->local_ip = request_info->local_ip;
+	request->remote_ip = request_info->remote_ip;
 	request->id = ++client->request_id_counter;
 
-	if (initial_resp_size != 0) {
-		request->initial_resp_size = initial_resp_size;
-		request->initial_resp_data = i_malloc(initial_resp_size);
-		memcpy(request->initial_resp_data, initial_resp_data,
-		       initial_resp_size);
+	if (request_info->initial_resp_size != 0) {
+		request->initial_resp_size = request_info->initial_resp_size;
+		request->initial_resp_data =
+			i_malloc(request_info->initial_resp_size);
+		memcpy(request->initial_resp_data,
+		       request_info->initial_resp_data,
+		       request_info->initial_resp_size);
 	}
 	
 	if (request->id == 0) {
--- a/src/login-common/client-common.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/login-common/client-common.h	Mon May 31 21:04:46 2004 +0300
@@ -5,6 +5,7 @@
 #include "master.h"
 
 struct client {
+	struct ip_addr local_ip;
 	struct ip_addr ip;
 	struct ssl_proxy *proxy;
 
@@ -19,7 +20,8 @@
 	/* ... */
 };
 
-struct client *client_create(int fd, struct ip_addr *ip, int ssl);
+struct client *client_create(int fd, int ssl, const struct ip_addr *local_ip,
+			     const struct ip_addr *ip);
 
 unsigned int clients_get_count(void);
 void clients_notify_auth_connected(void);
--- a/src/login-common/main.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/login-common/main.c	Mon May 31 21:04:46 2004 +0300
@@ -76,7 +76,7 @@
 
 static void login_accept(void *context __attr_unused__)
 {
-	struct ip_addr ip;
+	struct ip_addr ip, local_ip;
 	int fd;
 
 	fd = net_accept(LOGIN_LISTEN_FD, &ip, NULL);
@@ -89,12 +89,15 @@
 	if (process_per_connection)
 		main_close_listen();
 
-	(void)client_create(fd, &ip, FALSE);
+	if (net_getsockname(fd, &local_ip, NULL) < 0)
+		memset(&local_ip, 0, sizeof(local_ip));
+
+	(void)client_create(fd, FALSE, &local_ip, &ip);
 }
 
 static void login_accept_ssl(void *context __attr_unused__)
 {
-	struct ip_addr ip;
+	struct ip_addr ip, local_ip;
 	struct client *client;
 	struct ssl_proxy *proxy;
 	int fd, fd_ssl;
@@ -108,12 +111,14 @@
 
 	if (process_per_connection)
 		main_close_listen();
+	if (net_getsockname(fd, &local_ip, NULL) < 0)
+		memset(&local_ip, 0, sizeof(local_ip));
 
 	fd_ssl = ssl_proxy_new(fd, &ip, &proxy);
 	if (fd_ssl == -1)
 		net_disconnect(fd);
 	else {
-		client = client_create(fd_ssl, &ip, TRUE);
+		client = client_create(fd_ssl, TRUE, &local_ip, &ip);
 		client->proxy = proxy;
 	}
 }
@@ -216,7 +221,7 @@
 int main(int argc __attr_unused__, char *argv[], char *envp[])
 {
 	const char *name, *group_name;
-	struct ip_addr ip;
+	struct ip_addr ip, local_ip;
 	struct ssl_proxy *proxy = NULL;
 	struct client *client;
 	int i, fd = -1, master_fd = -1;
@@ -256,10 +261,12 @@
 	main_init();
 
 	if (is_inetd) {
-		if (net_getsockname(1, &ip, NULL) < 0) {
+		if (net_getpeername(1, &ip, NULL) < 0) {
 			i_fatal("%s can be started only through dovecot "
 				"master process, inetd or equilevant", argv[0]);
 		}
+		if (net_getsockname(1, &local_ip, NULL) < 0)
+			memset(&local_ip, 0, sizeof(local_ip));
 
 		fd = 1;
 		for (i = 1; i < argc; i++) {
@@ -273,11 +280,11 @@
 
 		master_init(master_fd, FALSE);
 		closing_down = TRUE;
-	}
 
-	if (fd != -1) {
-		client = client_create(fd, &ip, TRUE);
-		client->proxy = proxy;
+		if (fd != -1) {
+			client = client_create(fd, TRUE, &local_ip, &ip);
+			client->proxy = proxy;
+		}
 	}
 
 	io_loop_run(ioloop);
--- a/src/login-common/master.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/login-common/master.c	Mon May 31 21:04:46 2004 +0300
@@ -49,7 +49,8 @@
 		req.tag = ++master_tag_counter;
 	req.auth_pid = auth_pid;
 	req.auth_id = auth_id;
-	req.ip = client->ip;
+	req.local_ip = client->local_ip;
+	req.remote_ip = client->ip;
 
 	if (fd_send(master_fd, client->fd, &req, sizeof(req)) != sizeof(req))
 		i_fatal("fd_send(%d) failed: %m", client->fd);
--- a/src/master/login-process.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/master/login-process.c	Mon May 31 21:04:46 2004 +0300
@@ -39,7 +39,7 @@
 	unsigned int login_tag;
 	int fd;
 
-	struct ip_addr ip;
+	struct ip_addr local_ip, remote_ip;
 };
 
 static unsigned int auth_id_counter, login_pid_counter;
@@ -82,9 +82,13 @@
 	else {
 		struct login_group *group = request->process->group;
 
+		t_push();
 		master_reply.success =
-			create_mail_process(group, request->fd, &request->ip,
+			create_mail_process(group, request->fd,
+					    &request->local_ip,
+					    &request->remote_ip,
 					    reply, (const char *) data);
+		t_pop();
 	}
 
 	/* reply to login */
@@ -268,7 +272,8 @@
 	authreq->tag = ++auth_id_counter;
 	authreq->login_tag = req.tag;
 	authreq->fd = client_fd;
-	authreq->ip = req.ip;
+	authreq->local_ip = req.local_ip;
+	authreq->remote_ip = req.remote_ip;
 
 	auth_process = auth_process_find(req.auth_pid);
 	if (auth_process == NULL) {
--- a/src/master/mail-process.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/master/mail-process.c	Mon May 31 21:04:46 2004 +0300
@@ -75,8 +75,10 @@
 }
 
 static const struct var_expand_table *
-get_var_expand_table(const char *user, const char *home,
-		     enum process_type process_type)
+get_var_expand_table(enum process_type process_type,
+		     const char *user, const char *home,
+		     const struct ip_addr *local_ip,
+		     const struct ip_addr *remote_ip, pid_t pid)
 {
 	static struct var_expand_table static_tab[] = {
 		{ 'u', NULL },
@@ -84,6 +86,9 @@
 		{ 'd', NULL },
 		{ 'p', NULL },
 		{ 'h', NULL },
+		{ 'l', NULL },
+		{ 'r', NULL },
+		{ 'P', NULL },
 		{ '\0', NULL }
 	};
 	struct var_expand_table *tab;
@@ -97,6 +102,9 @@
 	if (tab[2].value != NULL) tab[2].value++;
 	tab[3].value = t_str_ucase(process_names[process_type]);
 	tab[4].value = home;
+	tab[5].value = net_ip2addr(local_ip);
+	tab[6].value = net_ip2addr(remote_ip);
+	tab[7].value = dec2str(pid);
 
 	return tab;
 }
@@ -173,16 +181,18 @@
 }
 
 int create_mail_process(struct login_group *group, int socket,
-			struct ip_addr *ip,
+			const struct ip_addr *local_ip,
+			const struct ip_addr *remote_ip,
 			struct auth_master_reply *reply, const char *data)
 {
 	struct settings *set = group->set;
 	const struct var_expand_table *var_expand_table;
 	const char *argv[4];
 	const char *addr, *mail, *user, *chroot_dir, *home_dir, *full_home_dir;
-	const char *executable, *p, *prefix;
+	const char *executable, *p;
 	struct log_io *log;
 	char title[1024];
+	string_t *str;
 	pid_t pid;
 	int i, err, ret, log_fd;
 
@@ -196,6 +206,8 @@
 			      data + reply->virtual_user_idx))
 		return FALSE;
 
+	user = data + reply->virtual_user_idx;
+	mail = data + reply->mail_idx;
 	home_dir = data + reply->home_idx;
 	chroot_dir = data + reply->chroot_idx;
 
@@ -217,12 +229,16 @@
 		return FALSE;
 	}
 
+	var_expand_table =
+		get_var_expand_table(group->process_type, user, home_dir,
+				     local_ip, remote_ip,
+				     pid != 0 ? pid : getpid());
+	str = t_str_new(128);
+
 	if (pid != 0) {
 		/* master */
-		prefix = t_strdup_printf("%s(%s): ",
-					 process_names[group->process_type],
-					 data + reply->virtual_user_idx);
-		log_set_prefix(log, prefix);
+		var_expand(str, set->mail_log_prefix, var_expand_table);
+		log_set_prefix(log, str_c(str));
 
 		mail_process_count++;
 		PID_ADD_PROCESS_TYPE(pid, group->process_type);
@@ -230,10 +246,9 @@
 		return TRUE;
 	}
 
-	prefix = t_strdup_printf("master-%s(%s): ",
-				 process_names[group->process_type],
-				 data + reply->virtual_user_idx);
-	log_set_prefix(log, prefix);
+	str_append(str, "master-");
+	var_expand(str, set->mail_log_prefix, var_expand_table);
+	log_set_prefix(log, str_c(str));
 
 	child_process_init_env();
 
@@ -345,12 +360,6 @@
 	/* user given environment - may be malicious. virtual_user comes from
 	   auth process, but don't trust that too much either. Some auth
 	   mechanism might allow leaving extra data there. */
-	mail = data + reply->mail_idx;
-	user = data + reply->virtual_user_idx;
-
-	var_expand_table =
-		get_var_expand_table(user, home_dir, group->process_type);
-
 	if (*mail == '\0' && set->default_mail_env != NULL)
 		mail = expand_mail_env(set->default_mail_env, var_expand_table);
 
@@ -362,7 +371,7 @@
 	env_put(t_strconcat("MAIL=", mail, NULL));
 	env_put(t_strconcat("USER=", data + reply->virtual_user_idx, NULL));
 
-	addr = net_ip2addr(ip);
+	addr = net_ip2addr(remote_ip);
 	env_put(t_strconcat("IP=", addr, NULL));
 
 	if (!set->verbose_proctitle)
--- a/src/master/mail-process.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/master/mail-process.h	Mon May 31 21:04:46 2004 +0300
@@ -5,7 +5,8 @@
 struct auth_master_reply;
 
 int create_mail_process(struct login_group *group, int socket,
-			struct ip_addr *ip,
+			const struct ip_addr *local_ip,
+			const struct ip_addr *remote_ip,
 			struct auth_master_reply *reply, const char *data);
 
 void mail_process_destroyed(pid_t pid);
--- a/src/master/master-login-interface.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/master/master-login-interface.h	Mon May 31 21:04:46 2004 +0300
@@ -13,7 +13,7 @@
 	unsigned int auth_pid;
 	unsigned int auth_id;
 
-	struct ip_addr ip;
+	struct ip_addr local_ip, remote_ip;
 };
 
 struct master_login_reply {
--- a/src/master/master-settings.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/master/master-settings.c	Mon May 31 21:04:46 2004 +0300
@@ -107,6 +107,7 @@
 	DEF(SET_INT, mail_process_size),
 	DEF(SET_BOOL, mail_use_modules),
 	DEF(SET_STR, mail_modules),
+	DEF(SET_STR, mail_log_prefix),
 
 	/* imap */
 	DEF(SET_INT, imap_max_line_length),
@@ -241,6 +242,7 @@
 	MEMBER(mail_process_size) 256,
 	MEMBER(mail_use_modules) FALSE,
 	MEMBER(mail_modules) MODULEDIR"/imap",
+	MEMBER(mail_log_prefix) "%Up(%u): ",
 
 	/* imap */
 	MEMBER(imap_max_line_length) 65536,
--- a/src/master/master-settings.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/master/master-settings.h	Mon May 31 21:04:46 2004 +0300
@@ -82,6 +82,7 @@
 	unsigned int mail_process_size;
 	int mail_use_modules;
 	const char *mail_modules;
+	const char *mail_log_prefix;
 
 	/* imap */
 	unsigned int imap_max_line_length;
--- a/src/pop3-login/client-authenticate.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/pop3-login/client-authenticate.c	Mon May 31 21:04:46 2004 +0300
@@ -148,10 +148,8 @@
 		return TRUE;
 	}
 
-	/* authorization ID \0 authentication ID \0 pass */
-	buffer_set_used_size(client->plain_login, 0);
-	buffer_append_c(client->plain_login, '\0');
-	buffer_append(client->plain_login, args, strlen(args));
+	i_free(client->last_user);
+	client->last_user = i_strdup(args);
 
 	client_send_line(client, "+OK");
 	return TRUE;
@@ -160,23 +158,34 @@
 int cmd_pass(struct pop3_client *client, const char *args)
 {
 	const char *error;
+	struct auth_request_info info;
+	string_t *plain_login;
 
-	if (buffer_get_used_size(client->plain_login) == 0) {
+	if (client->last_user == NULL) {
 		client_send_line(client, "-ERR No username given.");
 		return TRUE;
 	}
 
-	buffer_append_c(client->plain_login, '\0');
-	buffer_append(client->plain_login, args, strlen(args));
+	/* authorization ID \0 authentication ID \0 pass */
+	plain_login = t_str_new(128);
+	str_append_c(plain_login, '\0');
+	str_append(plain_login, client->last_user);
+	str_append_c(plain_login, '\0');
+	str_append(plain_login, args);
+
+	memset(&info, 0, sizeof(info));
+	info.mech = "PLAIN";
+	info.protocol = "POP3";
+	info.flags = client_get_auth_flags(client);
+	info.local_ip = client->common.local_ip;
+	info.remote_ip = client->common.ip;
+	info.initial_resp_data = str_data(plain_login);
+	info.initial_resp_size = str_len(plain_login);
 
 	client_ref(client);
 	client->common.auth_request =
-		auth_client_request_new(auth_client, "PLAIN", "POP3",
-                                        client_get_auth_flags(client),
-					str_data(client->plain_login),
-					str_len(client->plain_login),
+		auth_client_request_new(auth_client, &info,
 					login_callback, client, &error);
-	buffer_set_used_size(client->plain_login, 0);
 
 	if (client->common.auth_request != NULL) {
 		/* don't read any input from client until login is finished */
@@ -265,6 +274,7 @@
 
 int cmd_auth(struct pop3_client *client, const char *args)
 {
+	struct auth_request_info info;
 	const struct auth_mech_desc *mech;
 	const char *mech_name, *error, *p;
 	string_t *buf;
@@ -303,11 +313,18 @@
 		return TRUE;
 	}
 
+	memset(&info, 0, sizeof(info));
+	info.mech = mech->name;
+	info.protocol = "POP3";
+	info.flags = client_get_auth_flags(client);
+	info.local_ip = client->common.local_ip;
+	info.remote_ip = client->common.ip;
+	info.initial_resp_data = str_data(buf);
+	info.initial_resp_size = str_len(buf);
+
 	client_ref(client);
 	client->common.auth_request =
-		auth_client_request_new(auth_client, mech->name, "POP3",
-                                        client_get_auth_flags(client),
-					str_data(buf), str_len(buf),
+		auth_client_request_new(auth_client, &info,
 					authenticate_callback, client, &error);
 	if (client->common.auth_request != NULL) {
 		/* following input data will go to authentication */
--- a/src/pop3-login/client.c	Mon May 31 00:15:19 2004 +0300
+++ b/src/pop3-login/client.c	Mon May 31 21:04:46 2004 +0300
@@ -228,7 +228,8 @@
 	}
 }
 
-struct client *client_create(int fd, struct ip_addr *ip, int ssl)
+struct client *client_create(int fd, int ssl, const struct ip_addr *local_ip,
+			     const struct ip_addr *ip)
 {
 	struct pop3_client *client;
 	const char *addr;
@@ -253,11 +254,11 @@
 		(IPADDR_IS_V4(ip) && strncmp(addr, "127.", 4) == 0) ||
 		(IPADDR_IS_V6(ip) && strcmp(addr, "::1") == 0);
 
+	client->common.local_ip = *local_ip;
 	client->common.ip = *ip;
 	client->common.fd = fd;
 	client->common.io = io_add(fd, IO_READ, client_input, client);
 	client_open_streams(client, fd);
-	client->plain_login = buffer_create_dynamic(system_pool, 128, 8192);
 
 	client->last_input = ioloop_time;
 	hash_insert(clients, client, client);
@@ -317,7 +318,6 @@
 	i_stream_unref(client->input);
 	o_stream_unref(client->output);
 
-	buffer_free(client->plain_login);
 	i_free(client->common.virtual_user);
 	i_free(client);
 
--- a/src/pop3-login/client.h	Mon May 31 00:15:19 2004 +0300
+++ b/src/pop3-login/client.h	Mon May 31 21:04:46 2004 +0300
@@ -17,7 +17,7 @@
 	time_t last_input;
 	unsigned int bad_counter;
 
-	buffer_t *plain_login;
+	char *last_user;
 
 	unsigned int tls:1;
 	unsigned int secured:1;
@@ -25,7 +25,6 @@
 	unsigned int destroyed:1;
 };
 
-struct client *client_create(int fd, struct ip_addr *ip, int ssl);
 void client_destroy(struct pop3_client *client, const char *reason);
 
 void client_send_line(struct pop3_client *client, const char *line);