changeset 7928:9e226056a208 HEAD

Send login command OK reply in IMAP/POP3 process.
author Timo Sirainen <tss@iki.fi>
date Sat, 21 Jun 2008 12:50:28 +0300
parents 2351a81ce699
children 55d1a2bf4573
files src/imap-login/client-authenticate.c src/imap-login/client.c src/imap-login/client.h src/imap/main.c src/login-common/client-common.h 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/pop3-login/client-authenticate.c src/pop3/main.c
diffstat 13 files changed, 97 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap-login/client-authenticate.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/imap-login/client-authenticate.c	Sat Jun 21 12:50:28 2008 +0300
@@ -82,6 +82,7 @@
 		io_remove(&client->io);
 	client->io = io_add(client->common.fd, IO_READ,
 			    client_input, client);
+	client->common.auth_command_tag = NULL;
 }
 
 static bool client_handle_args(struct imap_client *client,
@@ -207,14 +208,6 @@
 			if (client_handle_args(client, args, TRUE))
 				break;
 		}
-
-		if (client->full_capability_sent)
-			client_send_tagline(client, "OK Logged in.");
-		else {
-			client_send_tagline(client, t_strdup_printf(
-				"OK [CAPABILITY %s] Logged in.",
-				capability_string));
-		}
 		client_destroy_success(client, "Login");
 		break;
 	case SASL_SERVER_REPLY_AUTH_FAILED:
@@ -271,6 +264,8 @@
 static int client_auth_begin(struct imap_client *client, const char *mech_name,
 			     const char *init_resp)
 {
+	client->common.auth_command_tag = client->cmd_tag;
+
 	client_ref(client);
 	sasl_server_auth_begin(&client->common, IMAP_SERVICE_NAME, mech_name,
 			       init_resp, sasl_callback);
--- a/src/imap-login/client.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/imap-login/client.c	Sat Jun 21 12:50:28 2008 +0300
@@ -108,7 +108,8 @@
 
 static int cmd_capability(struct imap_client *client)
 {
-	client->full_capability_sent = TRUE;
+	client->common.master_login_flags |=
+		LOGIN_IMAP_FLAG_FULL_CAPABILITY_SENT;
 	client_send_line(client, t_strconcat(
 		"* CAPABILITY ", get_capability(client, TRUE), NULL));
 	client_send_tagline(client, "OK Capability completed.");
--- a/src/imap-login/client.h	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/imap-login/client.h	Sat Jun 21 12:50:28 2008 +0300
@@ -31,7 +31,6 @@
 	unsigned int destroyed:1;
 	unsigned int greeting_sent:1;
 	unsigned int id_logged:1;
-	unsigned int full_capability_sent:1;
 };
 
 void client_destroy(struct imap_client *client, const char *reason);
--- a/src/imap/main.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/imap/main.c	Sat Jun 21 12:50:28 2008 +0300
@@ -24,7 +24,7 @@
 #include <syslog.h>
 
 #define IS_STANDALONE() \
-        (getenv("LOGGED_IN") == NULL && getenv("IMAPLOGINTAG") == NULL)
+        (getenv("IMAPLOGINTAG") == NULL)
 
 struct client_workaround_list {
 	const char *name;
@@ -167,7 +167,7 @@
 	struct client *client;
 	struct ostream *output;
 	struct mail_namespace *ns;
-	const char *user, *str;
+	const char *user, *str, *tag;
 
 	lib_signals_init();
         lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
@@ -244,15 +244,21 @@
 	output = client->output;
 	o_stream_ref(output);
 	o_stream_cork(output);
-	if (IS_STANDALONE()) {
+
+	/* IMAPLOGINTAG environment is compatible with mailfront */
+	tag = getenv("IMAPLOGINTAG");
+	if (tag == NULL) {
 		client_send_line(client, t_strconcat(
 			"* PREAUTH [CAPABILITY ",
 			str_c(capability_string), "] "
 			"Logged in as ", user, NULL));
-	} else if (getenv("IMAPLOGINTAG") != NULL) {
-		/* Support for mailfront */
-		client_send_line(client, t_strconcat(getenv("IMAPLOGINTAG"),
-						     " OK Logged in.", NULL));
+	} else if (getenv("CLIENT_SEND_CAPABILITY") == NULL) {
+		client_send_line(client,
+				 t_strconcat(tag, " OK Logged in.", NULL));
+	} else {
+		client_send_line(client, t_strconcat(
+			tag, " OK [CAPABILITY ",
+			str_c(capability_string), "] Logged in", NULL));
 	}
 	str = getenv("CLIENT_INPUT");
 	if (str != NULL) T_BEGIN {
@@ -290,7 +296,7 @@
 int main(int argc ATTR_UNUSED, char *argv[], char *envp[])
 {
 #ifdef DEBUG
-	if (getenv("LOGGED_IN") != NULL && getenv("GDB") == NULL)
+	if (!IS_STANDALONE() && getenv("GDB") == NULL)
 		fd_debug_verify_leaks(3, 1024);
 #endif
 	if (IS_STANDALONE() && getuid() == 0 &&
--- a/src/login-common/client-common.h	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/login-common/client-common.h	Sat Jun 21 12:50:28 2008 +0300
@@ -23,10 +23,12 @@
 
 	int fd;
 	struct istream *input;
+	const char *auth_command_tag;
 
 	char *auth_mech_name;
 	struct auth_request *auth_request;
 
+	enum master_login_flags master_login_flags;
 	unsigned int master_tag;
 	master_callback_t *master_callback;
 	sasl_server_callback_t *sasl_callback;
--- a/src/login-common/master.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/login-common/master.c	Sat Jun 21 12:50:28 2008 +0300
@@ -66,13 +66,18 @@
 	const unsigned char *data;
 	size_t size;
 	ssize_t ret;
+	unsigned int cmd_tag_size;
 
 	i_assert(auth_pid != 0);
 
 	data = i_stream_get_data(client->input, &size);
+	cmd_tag_size = client->auth_command_tag == NULL ? 0 :
+		strlen(client->auth_command_tag);
+
 	buf = buffer_create_dynamic(pool_datastack_create(),
-				    sizeof(*req) + size);
-	buffer_write(buf, sizeof(*req), data, size);
+				    sizeof(*req) + size + cmd_tag_size);
+	buffer_write(buf, sizeof(*req), client->auth_command_tag, cmd_tag_size);
+	buffer_write(buf, sizeof(*req) + cmd_tag_size, data, size);
 	req = buffer_get_space_unsafe(buf, 0, sizeof(*req));
 	req->version = MASTER_LOGIN_PROTOCOL_VERSION;
 	req->tag = ++master_tag_counter;
@@ -82,8 +87,10 @@
 	req->auth_id = auth_id;
 	req->local_ip = client->local_ip;
 	req->remote_ip = client->ip;
-	req->data_size = size;
-#if LOGIN_MAX_INBUF_SIZE != MASTER_LOGIN_MAX_DATA_SIZE
+	req->flags = client->master_login_flags;
+	req->cmd_tag_size =  cmd_tag_size;
+	req->data_size = req->cmd_tag_size + size;
+#if (LOGIN_MAX_INBUF_SIZE*2) != MASTER_LOGIN_MAX_DATA_SIZE
 #  error buffer max sizes unsynced
 #endif
 	i_assert(req->data_size <= LOGIN_MAX_INBUF_SIZE);
--- a/src/master/login-process.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/master/login-process.c	Sat Jun 21 12:50:28 2008 +0300
@@ -44,12 +44,9 @@
 struct login_auth_request {
 	struct login_process *process;
 	unsigned int tag;
+	unsigned int login_tag;
 
-	unsigned int login_tag;
-	int fd;
-
-	unsigned int data_size;
-	struct ip_addr local_ip, remote_ip;
+	struct mail_login_request mail_request;
 	unsigned char data[];
 };
 
@@ -104,11 +101,8 @@
 
 		master_reply.status =
 			create_mail_process(group->mail_process_type,
-					    group->set,
-					    request->fd, &request->local_ip,
-					    &request->remote_ip, user, args,
-					    request->data_size, request->data,
-					    FALSE);
+					    group->set, &request->mail_request,
+					    user, args, request->data, FALSE);
 	} T_END;
 
 	/* reply to login */
@@ -124,7 +118,7 @@
 		login_process_destroy(request->process);
 	}
 
-	if (close(request->fd) < 0)
+	if (close(request->mail_request.fd) < 0)
 		i_error("close(mail client) failed: %m");
 	login_process_unref(request->process);
 	i_free(request);
@@ -441,10 +435,12 @@
 	authreq->process = p;
 	authreq->tag = ++auth_id_counter;
 	authreq->login_tag = req.tag;
-	authreq->fd = client_fd;
-	authreq->local_ip = req.local_ip;
-	authreq->remote_ip = req.remote_ip;
-	authreq->data_size = req.data_size;
+	authreq->mail_request.fd = client_fd;
+	authreq->mail_request.local_ip = req.local_ip;
+	authreq->mail_request.remote_ip = req.remote_ip;
+	authreq->mail_request.flags = req.flags;
+	authreq->mail_request.cmd_tag_size = req.cmd_tag_size;
+	authreq->mail_request.data_size = req.data_size;
 	memcpy(authreq->data, data, req.data_size);
 
 	auth_process = auth_process_find(req.auth_pid);
--- a/src/master/mail-process.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/master/mail-process.c	Sat Jun 21 12:50:28 2008 +0300
@@ -522,11 +522,9 @@
 
 enum master_login_status
 create_mail_process(enum process_type process_type, struct settings *set,
-		    int socket_fd, const struct ip_addr *local_ip,
-		    const struct ip_addr *remote_ip,
+		    const struct mail_login_request *request,
 		    const char *user, const char *const *args,
-		    unsigned int input_size, const unsigned char *input,
-		    bool dump_capability)
+		    const unsigned char *data, bool dump_capability)
 {
 	const struct var_expand_table *var_expand_table;
 	const char *p, *addr, *mail, *chroot_dir, *home_dir, *full_home_dir;
@@ -553,7 +551,8 @@
 
 	/* check process limit for this user */
 	process_group = dump_capability ? NULL :
-		mail_process_group_lookup(process_type, user, remote_ip);
+		mail_process_group_lookup(process_type, user,
+					  &request->remote_ip);
 	process_count = process_group == NULL ? 0 :
 		array_count(&process_group->processes);
 	if (process_count >= set->mail_max_userip_connections &&
@@ -684,8 +683,8 @@
 	var_expand_table =
 		get_var_expand_table(process_names[process_type],
 				     user, home_given ? home_dir : NULL,
-				     net_ip2addr(local_ip),
-				     net_ip2addr(remote_ip),
+				     net_ip2addr(&request->local_ip),
+				     net_ip2addr(&request->remote_ip),
 				     pid != 0 ? pid : getpid(), uid);
 	str = t_str_new(128);
 
@@ -697,10 +696,9 @@
 			log_set_prefix(log, str_c(str));
 			log_set_pid(log, pid);
 			if (process_group == NULL) {
-				process_group =
-					mail_process_group_create(process_type,
-								  user,
-								  remote_ip);
+				process_group = mail_process_group_create(
+							process_type, user,
+							&request->remote_ip);
 			}
 			mail_process_group_add(process_group, pid);
 		}
@@ -724,9 +722,9 @@
 	child_process_init_env();
 
 	/* move the client socket into stdin and stdout fds, log to stderr */
-	if (dup2(dump_capability ? null_fd : socket_fd, 0) < 0)
+	if (dup2(dump_capability ? null_fd : request->fd, 0) < 0)
 		i_fatal("dup2(stdin) failed: %m");
-	if (dup2(socket_fd, 1) < 0)
+	if (dup2(request->fd, 1) < 0)
 		i_fatal("dup2(stdout) failed: %m");
 	if (dup2(log_fd, 2) < 0)
 		i_fatal("dup2(stderr) failed: %m");
@@ -831,13 +829,23 @@
 	env_put(t_strconcat("HOME=", home_dir, NULL));
 	env_put(t_strconcat("USER=", user, NULL));
 
-	addr = net_ip2addr(remote_ip);
+	addr = net_ip2addr(&request->remote_ip);
 	env_put(t_strconcat("IP=", addr, NULL));
 
-	if (input_size > 0) {
+	i_assert(request->cmd_tag_size <= request->data_size);
+	if (request->cmd_tag_size > 0) {
+		env_put(t_strconcat("IMAPLOGINTAG=",
+			t_strndup(data, request->cmd_tag_size), NULL));
+	}
+	if ((request->flags & LOGIN_IMAP_FLAG_FULL_CAPABILITY_SENT) == 0 &&
+	    process_type == PROCESS_TYPE_IMAP)
+		env_put("CLIENT_SEND_CAPABILITY=1");
+
+	if (request->data_size > request->cmd_tag_size) {
 		str_truncate(str, 0);
 		str_append(str, "CLIENT_INPUT=");
-		base64_encode(input, input_size, str);
+		base64_encode(data + request->cmd_tag_size,
+			      request->data_size - request->cmd_tag_size, str);
 		env_put(str_c(str));
 	}
 
--- a/src/master/mail-process.h	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/master/mail-process.h	Sat Jun 21 12:50:28 2008 +0300
@@ -1,8 +1,17 @@
 #ifndef MAIL_PROCESS_H
 #define MAIL_PROCESS_H
 
+#include "master-login-interface.h"
 #include "child-process.h"
 
+struct mail_login_request {
+	int fd;
+	enum master_login_flags flags;
+	unsigned int cmd_tag_size;
+	unsigned int data_size;
+	struct ip_addr local_ip, remote_ip;
+};
+
 struct login_group;
 struct auth_master_reply;
 
@@ -10,11 +19,9 @@
 
 enum master_login_status
 create_mail_process(enum process_type process_type, struct settings *set,
-		    int socket_fd, const struct ip_addr *local_ip,
-		    const struct ip_addr *remote_ip,
+		    const struct mail_login_request *request,
 		    const char *user, const char *const *args,
-		    unsigned int input_size, const unsigned char *input,
-		    bool dump_capability);
+		    const unsigned char *data, bool dump_capability);
 
 void mail_processes_init(void);
 void mail_processes_deinit(void);
--- a/src/master/master-login-interface.h	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/master/master-login-interface.h	Sat Jun 21 12:50:28 2008 +0300
@@ -9,8 +9,9 @@
    (or something else) is changed. */
 #define MASTER_LOGIN_PROTOCOL_VERSION 3
 
-/* This should be kept in sync with LOGIN_MAX_INBUF_SIZE */
-#define MASTER_LOGIN_MAX_DATA_SIZE 4096
+/* This should be kept in sync with LOGIN_MAX_INBUF_SIZE. Multiply it by two
+   to make sure there's space to transfer the command tag  */
+#define MASTER_LOGIN_MAX_DATA_SIZE (4096*2)
 
 enum master_login_state {
 	/* process is accepting new connections */
@@ -24,6 +25,10 @@
 	LOGIN_STATE_COUNT
 };
 
+enum master_login_flags {
+	LOGIN_IMAP_FLAG_FULL_CAPABILITY_SENT	= 0x01
+};
+
 struct master_login_request {
 	uint32_t version;
 	/* if fd == -1, tag is used as master_login_state */
@@ -32,7 +37,9 @@
 	uint32_t auth_pid;
 	uint32_t auth_id;
 	/* request follows this many bytes of client input */
-	uint32_t data_size;
+	uint16_t data_size;
+	uint16_t cmd_tag_size;
+	uint32_t flags;
 
 	ino_t ino;
 
--- a/src/master/master-settings.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/master/master-settings.c	Sat Jun 21 12:50:28 2008 +0300
@@ -614,7 +614,7 @@
 		NULL
 	};
 	enum master_login_status login_status;
-	struct ip_addr ip;
+	struct mail_login_request request;
 	char buf[4096];
 	int fd[2], status;
 	ssize_t ret;
@@ -638,16 +638,17 @@
 		args[1] = t_strdup_printf("gid=%s", dec2str(getegid()));
 	}
 
-	memset(&ip, 0, sizeof(ip));
 	if (pipe(fd) < 0) {
 		i_error("pipe() failed: %m");
 		return FALSE;
 	}
 	fd_close_on_exec(fd[0], TRUE);
 	fd_close_on_exec(fd[1], TRUE);
-	login_status = create_mail_process(PROCESS_TYPE_IMAP, set, fd[1],
-					   &ip, &ip, "dump-capability",
-					   args, 0, NULL, TRUE);
+
+	memset(&request, 0, sizeof(request));
+	request.fd = fd[1];
+	login_status = create_mail_process(PROCESS_TYPE_IMAP, set, &request,
+					   "dump-capability", args, NULL, TRUE);
 	if (login_status != MASTER_LOGIN_STATUS_OK) {
 		(void)close(fd[0]);
 		(void)close(fd[1]);
--- a/src/pop3-login/client-authenticate.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/pop3-login/client-authenticate.c	Sat Jun 21 12:50:28 2008 +0300
@@ -169,7 +169,6 @@
 				break;
 		}
 
-		client_send_line(client, "+OK Logged in.");
 		client_destroy_success(client, "Login");
 		break;
 	case SASL_SERVER_REPLY_AUTH_FAILED:
--- a/src/pop3/main.c	Sat Jun 21 12:23:08 2008 +0300
+++ b/src/pop3/main.c	Sat Jun 21 12:50:28 2008 +0300
@@ -242,6 +242,9 @@
 	if (client == NULL)
 		return FALSE;
 
+	if (!IS_STANDALONE())
+		client_send_line(client, "+OK Logged in.");
+
 	str = getenv("CLIENT_INPUT");
 	if (str != NULL) T_BEGIN {
 		buffer_t *buf = t_base64_decode_str(str);