[dovecot-cvs] dovecot/src/auth Makefile.am, 1.42, 1.43 auth-client-connection.c, 1.32, 1.33 auth-client-connection.h, 1.8, 1.9 auth-master-connection.c, 1.24, 1.25 auth-master-connection.h, 1.7, 1.8 auth-request-handler.c, NONE, 1.1 auth-request-handler.h, NONE, 1.1 auth-request.c, 1.6, 1.7 auth-request.h, 1.6, 1.7 main.c, 1.36, 1.37 mech-apop.c, 1.14, 1.15

cras at dovecot.org cras at dovecot.org
Sun Jan 9 02:49:21 EET 2005


Update of /var/lib/cvs/dovecot/src/auth
In directory talvi:/tmp/cvs-serv27365/auth

Modified Files:
	Makefile.am auth-client-connection.c auth-client-connection.h 
	auth-master-connection.c auth-master-connection.h 
	auth-request.c auth-request.h main.c mech-apop.c 
Added Files:
	auth-request-handler.c auth-request-handler.h 
Log Message:
Moving code around.



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- Makefile.am	7 Jan 2005 19:55:49 -0000	1.42
+++ Makefile.am	9 Jan 2005 00:49:18 -0000	1.43
@@ -38,6 +38,7 @@
 	auth-master-connection.c \
 	auth-module.c \
 	auth-request.c \
+	auth-request-handler.c \
 	db-ldap.c \
 	db-sql.c \
 	db-passwd-file.c \
@@ -80,6 +81,7 @@
 	auth-master-connection.h \
 	auth-module.h \
 	auth-request.h \
+	auth-request-handler.h \
 	db-ldap.h \
 	db-sql.h \
 	db-passwd-file.h \

Index: auth-client-connection.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-connection.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- auth-client-connection.c	8 Jan 2005 21:37:32 -0000	1.32
+++ auth-client-connection.c	9 Jan 2005 00:49:18 -0000	1.33
@@ -1,39 +1,32 @@
-/* Copyright (C) 2002-2003 Timo Sirainen */
+/* Copyright (C) 2002-2005 Timo Sirainen */
 
 #include "common.h"
 #include "ioloop.h"
 #include "istream.h"
 #include "ostream.h"
 #include "network.h"
-#include "base64.h"
-#include "buffer.h"
-#include "hash.h"
 #include "str.h"
-#include "str-sanitize.h"
 #include "safe-memset.h"
-#include "auth-request.h"
+#include "auth-request-handler.h"
+#include "auth-client-interface.h"
 #include "auth-client-connection.h"
 #include "auth-master-connection.h"
 
 #include <stdlib.h>
 
-/* Used only for string sanitization. */
-#define MAX_MECH_NAME_LEN 64
-
-#define MAX_OUTBUF_SIZE (1024*50)
+#define OUTBUF_THROTTLE_SIZE (1024*50)
 
 static void auth_client_connection_unref(struct auth_client_connection *conn);
-static void
-auth_client_connection_destroy_wait(struct auth_client_connection *conn);
 
+static void auth_client_input(void *context);
 static void auth_client_send(struct auth_client_connection *conn,
 			     const char *fmt, ...) __attr_format__(2, 3);
+
 static void auth_client_send(struct auth_client_connection *conn,
 			     const char *fmt, ...)
 {
 	va_list args;
 	string_t *str;
-	ssize_t ret;
 
 	i_assert(conn->refcount > 1);
 
@@ -42,114 +35,32 @@
 	str = t_str_new(256);
 	str_vprintfa(str, fmt, args);
 	str_append_c(str, '\n');
-	ret = o_stream_send(conn->output, str_data(str), str_len(str));
-	if (ret != (ssize_t)str->used) {
-		i_warning("Authentication client %u: "
-			  "Transmit buffer full, killing it", conn->pid);
-		auth_client_connection_destroy_wait(conn);
-	}
-	va_end(args);
-	t_pop();
-}
-
-static const char *get_client_extra_fields(struct auth_request *request)
-{
-	const char **fields;
-	unsigned int src, dest;
-
-	if (request->extra_fields == NULL)
-		return NULL;
-
-	/* we only wish to remove all fields prefixed with "userdb_" */
-	if (strstr(request->extra_fields, "userdb_") == NULL)
-		return request->extra_fields;
-
-	fields = t_strsplit(request->extra_fields, "\t");
-	for (src = dest = 0; fields[src] != NULL; src++) {
-		if (strncmp(fields[src], "userdb_", 7) == 0)
-			fields[dest++] = fields[src];
-	}
-	fields[dest] = NULL;
-	return t_strarray_join(fields, "\t");
-}
-
-static void auth_callback(struct auth_request *request,
-			  enum auth_client_result result,
-			  const void *reply, size_t reply_size)
-{
-	string_t *str = NULL;
-	const char *fields;
-	ssize_t ret;
-
-	t_push();
+	(void)o_stream_send(conn->output, str_data(str), str_len(str));
 
-	switch (result) {
-	case AUTH_CLIENT_RESULT_CONTINUE:
-		str = t_str_new(32 + MAX_BASE64_ENCODED_SIZE(reply_size));
-		str_printfa(str, "CONT\t%u\t", request->id);
-		base64_encode(reply, reply_size, str);
-                request->accept_input = TRUE;
-		break;
-	case AUTH_CLIENT_RESULT_SUCCESS:
-		str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size));
-		str_printfa(str, "OK\t%u\tuser=%s", request->id, request->user);
-		if (reply_size > 0) {
-			str_append(str, "\tresp=");
-			base64_encode(reply, reply_size, str);
-		}
-		t_push();
-		fields = get_client_extra_fields(request);
-		if (fields != NULL) {
-			str_append_c(str, '\t');
-			str_append(str, fields);
-		}
-		t_pop();
-		break;
-	case AUTH_CLIENT_RESULT_FAILURE:
-		str = t_str_new(128);
-		str_printfa(str, "FAIL\t%u", request->id);
-		if (request->user != NULL)
-			str_printfa(str, "\tuser=%s", request->user);
-		if (request->internal_failure)
-			str_append(str, "\ttemp");
-		t_push();
-		fields = get_client_extra_fields(request);
-		if (fields != NULL) {
-			str_append_c(str, '\t');
-			str_append(str, fields);
+	if (o_stream_get_buffer_used_size(conn->output) >=
+	    OUTBUF_THROTTLE_SIZE) {
+		/* stop reading new requests until client has read the pending
+		   replies. */
+		if (conn->io != NULL) {
+			io_remove(conn->io);
+			conn->io = NULL;
 		}
-		t_pop();
-		break;
-	}
-
-	str_append_c(str, '\n');
-
-	ret = o_stream_send(request->conn->output, str->data, str->used);
-	if (ret < 0)
-		auth_client_connection_destroy(request->conn);
-	else if ((size_t)ret != str->used) {
-		i_warning("Authentication client %u: "
-			  "Transmit buffer full, killing it",
-			  request->conn->pid);
-		auth_client_connection_destroy_wait(request->conn);
 	}
+	va_end(args);
 	t_pop();
-
-	auth_client_connection_unref(request->conn);
 }
 
-struct auth_client_connection *
-auth_client_connection_lookup(struct auth_master_connection *master,
-			      unsigned int pid)
+static void auth_callback(const char *reply, void *context)
 {
-	struct auth_client_connection *conn;
+	struct auth_client_connection *conn = context;
 
-	for (conn = master->clients; conn != NULL; conn = conn->next) {
-		if (conn->pid == pid)
-			return conn;
+	if (reply == NULL) {
+		/* handler destroyed */
+		auth_client_connection_unref(conn);
+		return;
 	}
 
-	return NULL;
+	auth_client_send(conn, "%s", reply);
 }
 
 static int
@@ -158,10 +69,7 @@
         struct auth_client_connection *old;
 	unsigned int pid;
 
-	if (conn->pid != 0) {
-		i_error("BUG: Authentication client re-handshaking");
-		return FALSE;
-	}
+	i_assert(conn->pid == 0);
 
 	pid = (unsigned int)strtoul(args, NULL, 10);
 	if (pid == 0) {
@@ -173,6 +81,7 @@
 	if (old != NULL) {
 		/* already exists. it's possible that it just reconnected,
 		   see if the old connection is still there. */
+		i_assert(old != conn);
 		if (i_stream_read(old->input) == -1) {
                         auth_client_connection_destroy(old);
 			old = NULL;
@@ -185,167 +94,54 @@
 		return FALSE;
 	}
 
+	/* handshake complete, we can now actually start serving requests */
+        conn->refcount++;
+	if (!AUTH_MASTER_IS_DUMMY(conn->master)) {
+		conn->request_handler =
+			auth_request_handler_create(conn->auth,
+				conn->connect_uid, pid, auth_callback, conn,
+				auth_master_request_callback, conn->master);
+	} else {
+		conn->request_handler =
+			auth_request_handler_create(conn->auth,
+						    conn->connect_uid, pid,
+						    auth_callback, conn,
+						    NULL, NULL);
+	}
 	conn->pid = pid;
 	return TRUE;
 }
 
-static int
-auth_client_input_auth(struct auth_client_connection *conn, const char *args)
+static int auth_client_output(void *context)
 {
-	struct mech_module *mech;
-	struct auth_request *request;
-	const char *const *list, *name, *arg, *initial_resp;
-	const void *initial_resp_data;
-	size_t initial_resp_len;
-	unsigned int id;
-	buffer_t *buf;
-	int valid_client_cert;
-
-	if (conn->pid == 0) {
-		i_error("BUG: Authentication client %u didn't send handshake",
-			conn->pid);
-		return FALSE;
-	}
-
-	/* <id> <mechanism> [...] */
-	list = t_strsplit(args, "\t");
-	if (list[0] == NULL || list[1] == NULL) {
-		i_error("BUG: Authentication client %u "
-			"sent broken AUTH request", conn->pid);
-		return FALSE;
-	}
-
-	id = (unsigned int)strtoul(list[0], NULL, 10);
-
-	mech = mech_module_find(list[1]);
-	if (mech == NULL) {
-		/* unsupported mechanism */
-		i_error("BUG: Authentication client %u requested unsupported "
-			"authentication mechanism %s", conn->pid,
-			str_sanitize(list[1], MAX_MECH_NAME_LEN));
-		return FALSE;
-	}
-
-	request = auth_request_new(conn->auth, mech, auth_callback);
-	hash_insert(conn->auth_requests, POINTER_CAST(id), request);
-
-	request->conn = conn;
-	request->id = id;
-
-	/* parse optional parameters */
-	initial_resp = NULL;
-	valid_client_cert = FALSE;
-	for (list += 2; *list != NULL; list++) {
-		arg = strchr(*list, '=');
-		if (arg == NULL) {
-			name = *list;
-			arg = "";
-		} else {
-			name = t_strdup_until(*list, arg);
-			arg++;
-		}
-
-		if (strcmp(name, "lip") == 0)
-			(void)net_addr2ip(arg, &request->local_ip);
-		else if (strcmp(name, "rip") == 0)
-			(void)net_addr2ip(arg, &request->remote_ip);
-		else if (strcmp(name, "service") == 0)
-			request->service = p_strdup(request->pool, arg);
-		else if (strcmp(name, "resp") == 0)
-			initial_resp = arg;
-		else if (strcmp(name, "valid-client-cert") == 0)
-			valid_client_cert = TRUE;
-	}
-
-	if (request->service == NULL) {
-		i_error("BUG: Authentication client %u "
-			"didn't specify service in request", conn->pid);
-		auth_request_destroy(request);
-		return FALSE;
-	}
+	struct auth_client_connection *conn = context;
 
-	if (request->auth->ssl_require_client_cert && !valid_client_cert) {
-		/* we fail without valid certificate */
-		auth_request_log_info(request, "ssl-cert-check",
-			"Client didn't present valid SSL certificate");
-		auth_request_destroy(request);
-		auth_client_send(conn, "FAIL\t%u", id);
-		return TRUE;
+	if (o_stream_flush(conn->output) < 0) {
+		auth_client_connection_destroy(conn);
+		return 1;
 	}
 
-	if (initial_resp == NULL) {
-		initial_resp_data = NULL;
-		initial_resp_len = 0;
-	} else {
-		size_t len = strlen(initial_resp);
-		buf = buffer_create_dynamic(pool_datastack_create(),
-					    MAX_BASE64_DECODED_SIZE(len));
-		if (base64_decode(initial_resp, len, NULL, buf) < 0) {
-			auth_request_log_info(request, mech->mech_name,
-				"Invalid base64 data in initial response");
-			auth_request_destroy(request);
-			auth_client_send(conn, "FAIL\t%u\t"
-				"reason=Invalid base64 data in initial "
-				"response", id);
-			return TRUE;
-		}
-		initial_resp_data = buf->data;
-		initial_resp_len = buf->used;
+	if (o_stream_get_buffer_used_size(conn->output) <=
+	    OUTBUF_THROTTLE_SIZE/3 && conn->io == NULL) {
+		/* allow input again */
+		conn->io = io_add(conn->fd, IO_READ, auth_client_input, conn);
 	}
-
-	/* connection is referenced only until auth_callback is called. */
-	conn->refcount++;
-	auth_request_initial(request, initial_resp_data, initial_resp_len);
-	return TRUE;
+	return 1;
 }
 
 static int
-auth_client_input_cont(struct auth_client_connection *conn, const char *args)
+auth_client_handle_line(struct auth_client_connection *conn, const char *line)
 {
-	struct auth_request *request;
-	const char *data;
-	size_t data_len;
-	buffer_t *buf;
-	unsigned int id;
-
-	data = strchr(args, '\t');
-	if (data++ == NULL) {
-		i_error("BUG: Authentication client %u "
-			"sent broken CONT request", conn->pid);
-		return FALSE;
-	}
-
-	id = (unsigned int)strtoul(args, NULL, 10);
-
-	request = hash_lookup(conn->auth_requests, POINTER_CAST(id));
-	if (request == NULL) {
-		/* timeouted */
-		auth_client_send(conn, "FAIL\t%u\treason=Timeouted", id);
-		return TRUE;
-	}
-
-	if (!request->accept_input) {
-		auth_client_send(conn, "FAIL\t%u"
-				 "\treason=Unexpected continuation", id);
-		auth_request_destroy(request);
-		return TRUE;
+	if (strncmp(line, "AUTH\t", 5) == 0) {
+		return auth_request_handler_auth_begin(conn->request_handler,
+						       line + 5);
 	}
-        request->accept_input = FALSE;
-
-	data_len = strlen(data);
-	buf = buffer_create_dynamic(pool_datastack_create(),
-				    MAX_BASE64_DECODED_SIZE(data_len));
-	if (base64_decode(data, data_len, NULL, buf) < 0) {
-                auth_request_log_info(request, request->mech->mech_name,
-			"Invalid base64 data in continued response");
-		auth_client_send(conn, "FAIL\t%u\treason=Invalid base64 data "
-				 "in continued response", id);
-		auth_request_destroy(request);
-		return TRUE;
+	if (strncmp(line, "CONT\t", 5) == 0) {
+		return auth_request_handler_auth_continue(conn->request_handler,
+							  line + 5);
 	}
 
-	conn->refcount++;
-	auth_request_continue(request, buf->data, buf->used);
+	/* ignore unknown command */
 	return TRUE;
 }
 
@@ -366,46 +162,48 @@
 		/* buffer full */
 		i_error("BUG: Auth client %u sent us more than %d bytes",
 			conn->pid, (int)AUTH_CLIENT_MAX_LINE_LENGTH);
-		auth_client_connection_destroy_wait(conn);
+		auth_client_connection_destroy(conn);
 		return;
 	}
 
-	if (!conn->version_received) {
+	while (conn->request_handler == NULL) {
+		/* still handshaking */
 		line = i_stream_next_line(conn->input);
 		if (line == NULL)
 			return;
 
-		/* make sure the major version matches */
-		if (strncmp(line, "VERSION\t", 8) != 0 ||
-		    atoi(t_strcut(line + 8, '\t')) !=
-		    AUTH_CLIENT_PROTOCOL_MAJOR_VERSION) {
-			i_error("Authentication client %u "
-				"not compatible with this server "
-				"(mixed old and new binaries?)", conn->pid);
-			auth_client_connection_destroy_wait(conn);
-			return;
+		if (!conn->version_received) {
+			/* make sure the major version matches */
+			if (strncmp(line, "VERSION\t", 8) != 0 ||
+			    atoi(t_strcut(line + 8, '\t')) !=
+			    AUTH_CLIENT_PROTOCOL_MAJOR_VERSION) {
+				i_error("Authentication client "
+					"not compatible with this server "
+					"(mixed old and new binaries?)");
+				auth_client_connection_destroy(conn);
+				return;
+			}
+			conn->version_received = TRUE;
+			continue;
+		}
+
+		if (strncmp(line, "CPID\t", 5) == 0) {
+			if (!auth_client_input_cpid(conn, line + 5)) {
+				auth_client_connection_destroy(conn);
+				return;
+			}
 		}
-		conn->version_received = TRUE;
 	}
 
-	conn->refcount++;
+        conn->refcount++;
 	while ((line = i_stream_next_line(conn->input)) != NULL) {
 		t_push();
-		if (strncmp(line, "AUTH\t", 5) == 0)
-			ret = auth_client_input_auth(conn, line + 5);
-		else if (strncmp(line, "CONT\t", 5) == 0)
-			ret = auth_client_input_cont(conn, line + 5);
-		else if (strncmp(line, "CPID\t", 5) == 0)
-			ret = auth_client_input_cpid(conn, line + 5);
-		else {
-			/* ignore unknown command */
-			ret = TRUE;
-		}
+		ret = auth_client_handle_line(conn, line);
 		safe_memset(line, 0, strlen(line));
 		t_pop();
 
 		if (!ret) {
-			auth_client_connection_destroy_wait(conn);
+			auth_client_connection_destroy(conn);
 			break;
 		}
 	}
@@ -420,27 +218,21 @@
 	struct const_iovec iov[2];
 	string_t *str;
 
-	pool_t pool;
-
-	pool = pool_alloconly_create("Auth client", 4096);
-	conn = p_new(pool, struct auth_client_connection, 1);
-	conn->pool = pool;
+	conn = i_new(struct auth_client_connection, 1);
 	conn->auth = master->auth;
 	conn->master = master;
 	conn->refcount = 1;
 	conn->connect_uid = ++connect_uid_counter;
 
 	conn->fd = fd;
-	conn->input = i_stream_create_file(fd, default_pool,
-					   AUTH_CLIENT_MAX_LINE_LENGTH,
-					   FALSE);
-	conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
-					    FALSE);
+	conn->input =
+		i_stream_create_file(fd, default_pool,
+				     AUTH_CLIENT_MAX_LINE_LENGTH, FALSE);
+	conn->output =
+		o_stream_create_file(fd, default_pool, (size_t)-1, FALSE);
+	o_stream_set_flush_callback(conn->output, auth_client_output, conn);
 	conn->io = io_add(fd, IO_READ, auth_client_input, conn);
 
-	conn->auth_requests = hash_create(default_pool, conn->pool,
-					  0, NULL, NULL);
-
 	conn->next = master->clients;
 	master->clients = conn;
 
@@ -488,86 +280,46 @@
 	net_disconnect(conn->fd);
 	conn->fd = -1;
 
+	if (conn->request_handler != NULL)
+		auth_request_handler_unref(conn->request_handler);
+
 	conn->master = NULL;
         auth_client_connection_unref(conn);
 }
 
-static void
-auth_client_connection_destroy_wait(struct auth_client_connection *conn)
-{
-        conn->delayed_destroy = TRUE;
-
-	if (conn->io != NULL) {
-		io_remove(conn->io);
-		conn->io = NULL;
-	}
-}
-
 static void auth_client_connection_unref(struct auth_client_connection *conn)
 {
-	struct hash_iterate_context *iter;
-	void *key, *value;
-
 	if (--conn->refcount > 0)
 		return;
 
-	iter = hash_iterate_init(conn->auth_requests);
-	while (hash_iterate(iter, &key, &value)) {
-		struct auth_request *auth_request = value;
-
-		auth_request->conn = NULL;
-		auth_request_unref(auth_request);
-	}
-	hash_iterate_deinit(iter);
-	hash_destroy(conn->auth_requests);
-
 	i_stream_unref(conn->input);
 	o_stream_unref(conn->output);
-
-	pool_unref(conn->pool);
+	i_free(conn);
 }
 
-static void
-auth_client_connection_check_timeouts(struct auth_client_connection *conn)
+struct auth_client_connection *
+auth_client_connection_lookup(struct auth_master_connection *master,
+			      unsigned int pid)
 {
-	struct hash_iterate_context *iter;
-	void *key, *value;
-	unsigned int secs;
-	int destroy = FALSE;
-
-	if (conn->delayed_destroy) {
-		auth_client_connection_destroy(conn);
-		return;
-	}
-
-	iter = hash_iterate_init(conn->auth_requests);
-	while (hash_iterate(iter, &key, &value)) {
-		struct auth_request *auth_request = value;
-
-		if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time) {
-			secs = (unsigned int) (ioloop_time -
-					       auth_request->created);
-			i_warning("Login process has too old (%us) requests, "
-				  "killing it.", secs);
+	struct auth_client_connection *conn;
 
-			destroy = TRUE;
-			break;
-		}
+	for (conn = master->clients; conn != NULL; conn = conn->next) {
+		if (conn->pid == pid)
+			return conn;
 	}
-	hash_iterate_deinit(iter);
 
-	if (destroy)
-		auth_client_connection_destroy(conn);
+	return NULL;
 }
 
 static void request_timeout(void *context __attr_unused__)
 {
         struct auth_master_connection *master = context;
-	struct auth_client_connection *conn, *next;
+	struct auth_client_connection *conn;
 
-	for (conn = master->clients; conn != NULL; conn = next) {
-		next = conn->next;
-		auth_client_connection_check_timeouts(conn);
+	for (conn = master->clients; conn != NULL; conn = conn->next) {
+		if (conn->request_handler == NULL)
+			continue;
+		auth_request_handler_check_timeouts(conn->request_handler);
 	}
 }
 

Index: auth-client-connection.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-connection.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- auth-client-connection.h	8 Jan 2005 19:01:34 -0000	1.8
+++ auth-client-connection.h	9 Jan 2005 00:49:18 -0000	1.9
@@ -13,14 +13,11 @@
 	struct istream *input;
 	struct ostream *output;
 
-	pool_t pool;
-	struct hash_table *auth_requests;
-
 	unsigned int pid;
 	unsigned int connect_uid;
+	struct auth_request_handler *request_handler;
 
 	unsigned int version_received:1;
-	unsigned int delayed_destroy:1;
 };
 
 struct auth_client_connection *

Index: auth-master-connection.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-master-connection.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- auth-master-connection.c	8 Jan 2005 16:56:04 -0000	1.24
+++ auth-master-connection.c	9 Jan 2005 00:49:18 -0000	1.25
@@ -9,7 +9,7 @@
 #include "ostream.h"
 #include "network.h"
 #include "userdb.h"
-#include "auth-request.h"
+#include "auth-request-handler.h"
 #include "auth-master-interface.h"
 #include "auth-client-connection.h"
 #include "auth-master-connection.h"
@@ -38,81 +38,23 @@
 static void auth_master_connection_close(struct auth_master_connection *conn);
 static int auth_master_connection_unref(struct auth_master_connection *conn);
 
-static void master_send(struct auth_master_connection *conn,
-			const char *fmt, ...) __attr_format__(2, 3);
-static void master_send(struct auth_master_connection *conn,
-			const char *fmt, ...)
-{
-	va_list args;
-	string_t *str;
-
-	t_push();
-	va_start(args, fmt);
-	str = t_str_new(256);
-	str_vprintfa(str, fmt, args);
-	str_append_c(str, '\n');
-	(void)o_stream_send(conn->output, str_data(str), str_len(str));
-	va_end(args);
-	t_pop();
-}
-
-static void append_user_reply(string_t *str, const struct user_data *user)
-{
-	const char *p;
-
-	str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user,
-		    dec2str(user->uid), dec2str(user->gid));
-
-	if (user->system_user != NULL)
-		str_printfa(str, "\tsystem_user=%s", user->system_user);
-	if (user->mail != NULL)
-		str_printfa(str, "\tmail=%s", user->mail);
-
-	p = user->home != NULL ? strstr(user->home, "/./") : NULL;
-	if (p == NULL) {
-		if (user->home != NULL)
-			str_printfa(str, "\thome=%s", user->home);
-	} else {
-		/* wu-ftpd like <chroot>/./<home> */
-		str_printfa(str, "\thome=%s\tchroot=%s",
-			    p + 3, t_strdup_until(user->home, p));
-	}
-}
-
-static void userdb_callback(const struct user_data *user, void *context)
+void auth_master_request_callback(const char *reply, void *context)
 {
-	struct master_userdb_request *master_request = context;
-	string_t *str;
+	struct auth_master_connection *conn = context;
+	struct const_iovec iov[2];
 
-	if (user != NULL) {
-		auth_request_log_debug(master_request->auth_request, "userdb",
-				       "uid=%s gid=%s home=%s mail=%s",
-				       dec2str(user->uid), dec2str(user->gid),
-				       user->home != NULL ? user->home : "",
-				       user->mail != NULL ? user->mail : "");
-	}
+	iov[0].iov_base = reply;
+	iov[0].iov_len = strlen(reply);
+	iov[1].iov_base = "\n";
+	iov[1].iov_len = 1;
 
-	if (auth_master_connection_unref(master_request->conn)) {
-		if (user == NULL) {
-			master_send(master_request->conn, "NOTFOUND\t%u",
-				    master_request->id);
-		} else {
-			str = t_str_new(256);
-			str_printfa(str, "USER\t%u\t", master_request->id);
-			append_user_reply(str,  user);
-			master_send(master_request->conn, "%s", str_c(str));
-		}
-	}
-	auth_request_destroy(master_request->auth_request);
-	i_free(master_request);
+	(void)o_stream_sendv(conn->output, iov, 2);
 }
 
 static int
 master_input_request(struct auth_master_connection *conn, const char *args)
 {
 	struct auth_client_connection *client_conn;
-	struct master_userdb_request *master_request;
-	struct auth_request *request;
 	const char *const *list;
 	unsigned int id, client_pid, client_id;
 
@@ -128,27 +70,14 @@
 	client_id = (unsigned int)strtoul(list[2], NULL, 10);
 
 	client_conn = auth_client_connection_lookup(conn, client_pid);
-	request = client_conn == NULL ? NULL :
-		hash_lookup(client_conn->auth_requests,
-			    POINTER_CAST(client_id));
-
-	if (request == NULL) {
-		i_error("Master request %u.%u not found",
-			client_pid, client_id);
-		master_send(conn, "NOTFOUND\t%u", id);
-	} else if (!request->successful) {
-		i_error("Master requested unfinished authentication request "
-			"%u.%u", client_pid, client_id);
-		master_send(conn, "NOTFOUND\t%u", id);
+	if (client_conn == NULL) {
+		i_error("Master requested auth for nonexisting client %u",
+			client_pid);
+		(void)o_stream_send_str(conn->output,
+					t_strdup_printf("NOTFOUND\t%u\n", id));
 	} else {
-		master_request = i_new(struct master_userdb_request, 1);
-		master_request->conn = conn;
-		master_request->id = id;
-		master_request->auth_request = request;
-
-		conn->refcount++;
-		auth_request_lookup_user(request, userdb_callback,
-					 master_request);
+		auth_request_handler_master_request(
+			client_conn->request_handler, id, client_id);
 	}
 	return TRUE;
 }
@@ -255,14 +184,14 @@
 }
 
 struct auth_master_connection *
-auth_master_connection_create(struct auth *auth, int fd, unsigned int pid)
+auth_master_connection_create(struct auth *auth, int fd)
 {
 	struct auth_master_connection *conn;
 
 	conn = i_new(struct auth_master_connection, 1);
 	conn->auth = auth;
 	conn->refcount = 1;
-	conn->pid = pid;
+	conn->pid = (unsigned int)getpid();
 	conn->fd = fd;
 	conn->listeners_buf = buffer_create_dynamic(default_pool, 64);
 	if (fd != -1)
@@ -272,11 +201,15 @@
 
 void auth_master_connection_send_handshake(struct auth_master_connection *conn)
 {
-	if (conn->output != NULL) {
-		master_send(conn, "VERSION\t%u\t%u\nSPID\t%u\n",
-			    AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
-                            AUTH_MASTER_PROTOCOL_MINOR_VERSION, conn->pid);
-	}
+	const char *line;
+
+	if (conn->output == NULL)
+		return;
+
+	line = t_strdup_printf("VERSION\t%u\t%u\nSPID\t%u\n",
+			       AUTH_MASTER_PROTOCOL_MAJOR_VERSION,
+			       AUTH_MASTER_PROTOCOL_MINOR_VERSION, conn->pid);
+	(void)o_stream_send_str(conn->output, line);
 }
 
 static void auth_master_connection_close(struct auth_master_connection *conn)

Index: auth-master-connection.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-master-connection.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- auth-master-connection.h	7 Jan 2005 19:55:49 -0000	1.7
+++ auth-master-connection.h	9 Jan 2005 00:49:18 -0000	1.8
@@ -23,10 +23,12 @@
 #define AUTH_MASTER_IS_DUMMY(master) (master->fd == -1)
 
 struct auth_master_connection *
-auth_master_connection_create(struct auth *auth, int fd, unsigned int pid);
+auth_master_connection_create(struct auth *auth, int fd);
 void auth_master_connection_send_handshake(struct auth_master_connection *conn);
 void auth_master_connection_destroy(struct auth_master_connection *conn);
 
+void auth_master_request_callback(const char *reply, void *context);
+
 void auth_master_connection_add_listener(struct auth_master_connection *conn,
 					 int fd, const char *path, int client);
 

--- NEW FILE: auth-request-handler.c ---
/* Copyright (C) 2005 Timo Sirainen */

#include "common.h"
#include "ioloop.h"
#include "buffer.h"
#include "base64.h"
#include "hash.h"
#include "str.h"
#include "str-sanitize.h"
#include "auth-request.h"
#include "auth-request-handler.h"

#include <stdlib.h>

/* Used only for string sanitization. */
#define MAX_MECH_NAME_LEN 64

struct auth_request_handler {
	int refcount;
	pool_t pool;
	struct hash_table *requests;

        struct auth *auth;
        unsigned int connect_uid, client_pid;

	auth_request_callback_t *callback;
	void *context;

	auth_request_callback_t *master_callback;
	void *master_context;
};

static buffer_t *auth_failures_buf;
static struct timeout *to_auth_failures;

struct auth_request_handler *
auth_request_handler_create(struct auth *auth,
			    unsigned int connect_uid, unsigned int client_pid,
			    auth_request_callback_t *callback, void *context,
			    auth_request_callback_t *master_callback,
			    void *master_context)
{
	struct auth_request_handler *handler;
	pool_t pool;

	pool = pool_alloconly_create("auth request handler", 4096);

	handler = p_new(pool, struct auth_request_handler, 1);
	handler->refcount = 1;
	handler->pool = pool;
	handler->requests = hash_create(default_pool, pool, 0, NULL, NULL);
	handler->auth = auth;
	handler->connect_uid = connect_uid;
	handler->client_pid = client_pid;
	handler->callback = callback;
	handler->context = context;
	handler->master_callback = master_callback;
	handler->master_context = master_context;
	return handler;
}

void auth_request_handler_unref(struct auth_request_handler *handler)
{
	struct hash_iterate_context *iter;
	void *key, *value;

	i_assert(handler->refcount > 0);
	if (--handler->refcount > 0)
		return;

	iter = hash_iterate_init(handler->requests);
	while (hash_iterate(iter, &key, &value))
		auth_request_unref(value);
	hash_iterate_deinit(iter);

	/* notify parent that we're done with all requests */
	handler->callback(NULL, handler->context);

	hash_destroy(handler->requests);
	pool_unref(handler->pool);
}

void auth_request_handler_check_timeouts(struct auth_request_handler *handler)
{
	struct hash_iterate_context *iter;
	void *key, *value;

	iter = hash_iterate_init(handler->requests);
	while (hash_iterate(iter, &key, &value)) {
		struct auth_request *auth_request = value;

		if (auth_request->created + AUTH_REQUEST_TIMEOUT < ioloop_time)
			hash_remove(handler->requests, key);
	}
	hash_iterate_deinit(iter);
}

static void auth_request_handler_remove(struct auth_request_handler *handler,
					struct auth_request *request)
{
	hash_remove(handler->requests, POINTER_CAST(request->id));
	auth_request_unref(request);
}

static const char *get_client_extra_fields(struct auth_request *request)
{
	const char **fields;
	unsigned int src, dest;

	if (request->extra_fields == NULL)
		return NULL;

	/* we only wish to remove all fields prefixed with "userdb_" */
	if (strstr(request->extra_fields, "userdb_") == NULL)
		return request->extra_fields;

	fields = t_strsplit(request->extra_fields, "\t");
	for (src = dest = 0; fields[src] != NULL; src++) {
		if (strncmp(fields[src], "userdb_", 7) == 0)
			fields[dest++] = fields[src];
	}
	fields[dest] = NULL;
	return t_strarray_join(fields, "\t");
}

static void auth_callback(struct auth_request *request,
			  enum auth_client_result result,
			  const void *reply, size_t reply_size)
{
        struct auth_request_handler *handler = request->context;
	string_t *str = NULL;
	const char *fields;

	t_push();

	switch (result) {
	case AUTH_CLIENT_RESULT_CONTINUE:
		str = t_str_new(32 + MAX_BASE64_ENCODED_SIZE(reply_size));
		str_printfa(str, "CONT\t%u\t", request->id);
		base64_encode(reply, reply_size, str);
                request->accept_input = TRUE;
		handler->callback(str_c(str), handler->context);
		break;
	case AUTH_CLIENT_RESULT_SUCCESS:
		str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size));
		str_printfa(str, "OK\t%u\tuser=%s", request->id, request->user);
		if (reply_size > 0) {
			str_append(str, "\tresp=");
			base64_encode(reply, reply_size, str);
		}
		fields = get_client_extra_fields(request);
		if (fields != NULL) {
			str_append_c(str, '\t');
			str_append(str, fields);
		}

		if (request->no_login || handler->master_callback == NULL) {
			/* this request doesn't have to wait for master
			   process to pick it up. delete it */
			auth_request_handler_remove(handler, request);
		}
		handler->callback(str_c(str), handler->context);
		break;
	case AUTH_CLIENT_RESULT_FAILURE:
		str = t_str_new(128);
		str_printfa(str, "FAIL\t%u", request->id);
		if (request->user != NULL)
			str_printfa(str, "\tuser=%s", request->user);
		if (request->internal_failure)
			str_append(str, "\ttemp");
		fields = get_client_extra_fields(request);
		if (fields != NULL) {
			str_append_c(str, '\t');
			str_append(str, fields);
		}

		if (request->delayed_failure) {
			/* we came here from flush_failures() */
			handler->callback(str_c(str), handler->context);
			break;
		}

		/* remove the request from requests-list */
		auth_request_ref(request);
		auth_request_handler_remove(handler, request);

		if (request->no_failure_delay) {
			/* passdb specifically requested not to delay the
			   reply. */
			handler->callback(str_c(str), handler->context);
		} else {
			/* failure. don't announce it immediately to avoid
			   a) timing attacks, b) flooding */
			request->delayed_failure = TRUE;
			handler->refcount++;
			buffer_append(auth_failures_buf,
				      &request, sizeof(request));
		}
		break;
	}
	/* NOTE: request may be destroyed now */

        auth_request_handler_unref(handler);

	t_pop();
}

static void auth_request_handler_auth_fail(struct auth_request_handler *handler,
					   struct auth_request *request,
					   const char *reason)
{
	const char *reply;

	auth_request_log_info(request, request->mech->mech_name, "%s", reason);

	reply = t_strdup_printf("FAIL\t%u\treason=%s", request->id, reason);
	handler->callback(reply, handler->context);
	auth_request_handler_remove(handler, request);
}

int auth_request_handler_auth_begin(struct auth_request_handler *handler,
				    const char *args)
{
	struct mech_module *mech;
	struct auth_request *request;
	const char *const *list, *name, *arg, *initial_resp;
	const void *initial_resp_data;
	size_t initial_resp_len;
	unsigned int id;
	buffer_t *buf;
	int valid_client_cert;

	/* <id> <mechanism> [...] */
	list = t_strsplit(args, "\t");
	if (list[0] == NULL || list[1] == NULL) {
		i_error("BUG: Authentication client %u "
			"sent broken AUTH request", handler->client_pid);
		return FALSE;
	}

	id = (unsigned int)strtoul(list[0], NULL, 10);

	mech = mech_module_find(list[1]);
	if (mech == NULL) {
		/* unsupported mechanism */
		i_error("BUG: Authentication client %u requested unsupported "
			"authentication mechanism %s", handler->client_pid,
			str_sanitize(list[1], MAX_MECH_NAME_LEN));
		return FALSE;
	}

	request = auth_request_new(handler->auth, mech, auth_callback, handler);
	request->connect_uid = handler->connect_uid;
	request->client_pid = handler->client_pid;
	request->id = id;

	/* parse optional parameters */
	initial_resp = NULL;
	valid_client_cert = FALSE;
	for (list += 2; *list != NULL; list++) {
		arg = strchr(*list, '=');
		if (arg == NULL) {
			name = *list;
			arg = "";
		} else {
			name = t_strdup_until(*list, arg);
			arg++;
		}

		if (strcmp(name, "lip") == 0)
			(void)net_addr2ip(arg, &request->local_ip);
		else if (strcmp(name, "rip") == 0)
			(void)net_addr2ip(arg, &request->remote_ip);
		else if (strcmp(name, "service") == 0)
			request->service = p_strdup(request->pool, arg);
		else if (strcmp(name, "resp") == 0)
			initial_resp = arg;
		else if (strcmp(name, "valid-client-cert") == 0)
			valid_client_cert = TRUE;
	}

	if (request->service == NULL) {
		i_error("BUG: Authentication client %u "
			"didn't specify service in request",
			handler->client_pid);
		auth_request_unref(request);
		return FALSE;
	}

	hash_insert(handler->requests, POINTER_CAST(id), request);

	if (request->auth->ssl_require_client_cert && !valid_client_cert) {
		/* we fail without valid certificate */
                auth_request_handler_auth_fail(handler, request,
			"Client didn't present valid SSL certificate");
		return TRUE;
	}

	if (initial_resp == NULL) {
		initial_resp_data = NULL;
		initial_resp_len = 0;
	} else {
		size_t len = strlen(initial_resp);
		buf = buffer_create_dynamic(pool_datastack_create(),
					    MAX_BASE64_DECODED_SIZE(len));
		if (base64_decode(initial_resp, len, NULL, buf) < 0) {
                        auth_request_handler_auth_fail(handler, request,
				"Invalid base64 data in initial response");
			return TRUE;
		}
		initial_resp_data = buf->data;
		initial_resp_len = buf->used;
	}

	/* handler is referenced until auth_callback is called. */
	handler->refcount++;
	auth_request_initial(request, initial_resp_data, initial_resp_len);
	return TRUE;
}

int auth_request_handler_auth_continue(struct auth_request_handler *handler,
				       const char *args)
{
	struct auth_request *request;
	const char *data;
	size_t data_len;
	buffer_t *buf;
	unsigned int id;

	data = strchr(args, '\t');
	if (data++ == NULL) {
		i_error("BUG: Authentication client sent broken CONT request");
		return FALSE;
	}

	id = (unsigned int)strtoul(args, NULL, 10);

	request = hash_lookup(handler->requests, POINTER_CAST(id));
	if (request == NULL) {
		data = t_strdup_printf("FAIL\t%u\treason=Timeouted", id);
		handler->callback(data, handler->context);
		return TRUE;
	}

	/* accept input only once after mechanism has sent a CONT reply */
	if (!request->accept_input) {
		auth_request_handler_auth_fail(handler, request,
					       "Unexpected continuation");
		return TRUE;
	}
	request->accept_input = FALSE;

	data_len = strlen(data);
	buf = buffer_create_dynamic(pool_datastack_create(),
				    MAX_BASE64_DECODED_SIZE(data_len));
	if (base64_decode(data, data_len, NULL, buf) < 0) {
		auth_request_handler_auth_fail(handler, request,
			"Invalid base64 data in continued response");
		return TRUE;
	}

	/* handler is referenced until auth_callback is called. */
	handler->refcount++;
	auth_request_continue(request, buf->data, buf->used);
	return TRUE;
}

static void append_user_reply(string_t *str, const struct user_data *user)
{
	const char *p;

	str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user,
		    dec2str(user->uid), dec2str(user->gid));

	if (user->system_user != NULL)
		str_printfa(str, "\tsystem_user=%s", user->system_user);
	if (user->mail != NULL)
		str_printfa(str, "\tmail=%s", user->mail);

	p = user->home != NULL ? strstr(user->home, "/./") : NULL;
	if (p == NULL) {
		if (user->home != NULL)
			str_printfa(str, "\thome=%s", user->home);
	} else {
		/* wu-ftpd like <chroot>/./<home> */
		str_printfa(str, "\thome=%s\tchroot=%s",
			    p + 3, t_strdup_until(user->home, p));
	}
}

static void userdb_callback(const struct user_data *user, void *context)
{
        struct auth_request *request = context;
        struct auth_request_handler *handler = request->context;
	string_t *reply;

	if (user != NULL) {
		auth_request_log_debug(request, "userdb",
				       "uid=%s gid=%s home=%s mail=%s",
				       dec2str(user->uid), dec2str(user->gid),
				       user->home != NULL ? user->home : "",
				       user->mail != NULL ? user->mail : "");
	}

	reply = t_str_new(256);
	if (user == NULL)
		str_printfa(reply, "NOTFOUND\t%u", request->id);
	else {
		str_printfa(reply, "USER\t%u\t", request->id);
		append_user_reply(reply, user);
	}
	handler->master_callback(str_c(reply), handler->master_context);

	auth_request_unref(request);
        auth_request_handler_unref(handler);
}

void auth_request_handler_master_request(struct auth_request_handler *handler,
					 unsigned int id,
					 unsigned int client_id)
{
	struct auth_request *request;
	const char *reply;

	request = hash_lookup(handler->requests, POINTER_CAST(client_id));
	if (request == NULL) {
		i_error("Master request %u.%u not found",
			handler->client_pid, client_id);
		reply = t_strdup_printf("NOTFOUND\t%u", id);
		handler->master_callback(reply, handler->master_context);
		return;
	}

	auth_request_ref(request);
	auth_request_handler_remove(handler, request);

	if (!request->successful) {
		i_error("Master requested unfinished authentication request "
			"%u.%u", handler->client_pid, client_id);
		reply = t_strdup_printf("NOTFOUND\t%u", id);
		handler->master_callback(reply, handler->master_context);
	} else {
		/* the request isn't being referenced anywhere anymore,
		   so we can do a bit of kludging.. replace the request's
		   old client_id with master's id. */
		request->id = id;
		request->context = handler;

		/* handler is referenced until userdb_callback is called. */
		handler->refcount++;
		auth_request_lookup_user(request, userdb_callback, request);
	}
}

void auth_request_handlers_flush_failures(void)
{
	struct auth_request **auth_request;
	size_t i, size;

	auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
	size /= sizeof(*auth_request);

	for (i = 0; i < size; i++) {
		auth_request[i]->callback(auth_request[i],
					  AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
		auth_request_unref(auth_request[i]);
	}
	buffer_set_used_size(auth_failures_buf, 0);
}

static void auth_failure_timeout(void *context __attr_unused__)
{
	auth_request_handlers_flush_failures();
}

void auth_request_handlers_init(void)
{
	auth_failures_buf = buffer_create_dynamic(default_pool, 1024);
        to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL);
}

void auth_request_handlers_deinit(void)
{
	buffer_free(auth_failures_buf);
	timeout_remove(to_auth_failures);
}

--- NEW FILE: auth-request-handler.h ---
#ifndef __AUTH_REQUEST_HANDLER_H
#define __AUTH_REQUEST_HANDLER_H

typedef void auth_request_callback_t(const char *reply, void *context);

struct auth_request_handler *
auth_request_handler_create(struct auth *auth,
			    unsigned int connect_uid, unsigned int client_pid,
			    auth_request_callback_t *callback, void *context,
			    auth_request_callback_t *master_callback,
			    void *master_context);
void auth_request_handler_unref(struct auth_request_handler *handler);

void auth_request_handler_check_timeouts(struct auth_request_handler *handler);

int auth_request_handler_auth_begin(struct auth_request_handler *handler,
				    const char *args);
int auth_request_handler_auth_continue(struct auth_request_handler *handler,
				       const char *args);
void auth_request_handler_master_request(struct auth_request_handler *handler,
					 unsigned int id,
					 unsigned int client_id);

void auth_request_handlers_flush_failures(void);

void auth_request_handlers_init(void);
void auth_request_handlers_deinit(void);

#endif

Index: auth-request.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- auth-request.c	8 Jan 2005 21:37:32 -0000	1.6
+++ auth-request.c	9 Jan 2005 00:49:18 -0000	1.7
@@ -20,81 +20,41 @@
 	char *user_password, *password;
 };
 
-static buffer_t *auth_failures_buf;
-static struct timeout *to_auth_failures;
-
 struct auth_request *
 auth_request_new(struct auth *auth, struct mech_module *mech,
-		 mech_callback_t *callback)
+		 mech_callback_t *callback, void *context)
 {
 	struct auth_request *request;
 
 	request = mech->auth_new();
 
 	request->refcount = 1;
+	request->created = ioloop_time;
+
 	request->auth = auth;
 	request->mech = mech;
 	request->callback = callback;
-	request->created = ioloop_time;
+	request->context = context;
 	return request;
 }
 
-void auth_request_destroy(struct auth_request *request)
-{
-	i_assert(request->refcount > 0);
-
-	if (request->destroyed)
-		return;
-	request->destroyed = TRUE;
-
-	if (request->conn != NULL) {
-		hash_remove(request->conn->auth_requests,
-			    POINTER_CAST(request->id));
-	}
-	auth_request_unref(request);
-}
-
 void auth_request_success(struct auth_request *request,
 			  const void *data, size_t data_size)
 {
-	request->successful = TRUE;
-	if (request->conn != NULL) {
-		request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
-				  data, data_size);
-	}
+	i_assert(!request->finished);
+	request->finished = TRUE;
 
-	if (request->no_login || request->conn == NULL ||
-	    AUTH_MASTER_IS_DUMMY(request->conn->master)) {
-		/* we don't have master process, the request is no longer
-		   needed */
-		auth_request_destroy(request);
-	}
+	request->successful = TRUE;
+	request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
+			  data, data_size);
 }
 
 void auth_request_fail(struct auth_request *request)
 {
-	if (request->no_failure_delay) {
-		/* passdb specifically requested to to delay the reply. */
-		request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
-		auth_request_destroy(request);
-		return;
-	}
-
-	/* failure. don't announce it immediately to avoid
-	   a) timing attacks, b) flooding */
-	if (auth_failures_buf->used > 0) {
-		const struct auth_request *const *requests;
-
-		requests = auth_failures_buf->data;
-		requests += auth_failures_buf->used/sizeof(*requests)-1;
-		i_assert(*requests != request);
-	}
-
-	buffer_append(auth_failures_buf, &request, sizeof(request));
+	i_assert(!request->finished);
+	request->finished = TRUE;
 
-	/* make sure the request isn't found anymore */
-	auth_request_ref(request);
-	auth_request_destroy(request);
+	request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
 }
 
 void auth_request_internal_failure(struct auth_request *request)
@@ -320,7 +280,7 @@
 		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);
+	tab[7].value = dec2str(auth_request->client_pid);
 	return tab;
 }
 
@@ -397,39 +357,3 @@
 	t_pop();
 	va_end(va);
 }
-
-void auth_failure_buf_flush(void)
-{
-	struct auth_request **auth_request;
-	size_t i, size;
-
-	auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
-	size /= sizeof(*auth_request);
-
-	for (i = 0; i < size; i++) {
-		if (auth_request[i]->conn != NULL) {
-			auth_request[i]->callback(auth_request[i],
-						  AUTH_CLIENT_RESULT_FAILURE,
-						  NULL, 0);
-		}
-		auth_request_destroy(auth_request[i]);
-	}
-	buffer_set_used_size(auth_failures_buf, 0);
-}
-
-static void auth_failure_timeout(void *context __attr_unused__)
-{
-	auth_failure_buf_flush();
-}
-
-void auth_requests_init(void)
-{
-	auth_failures_buf = buffer_create_dynamic(default_pool, 1024);
-        to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL);
-}
-
-void auth_requests_deinit(void)
-{
-	buffer_free(auth_failures_buf);
-	timeout_remove(to_auth_failures);
-}

Index: auth-request.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-request.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- auth-request.h	8 Jan 2005 21:37:32 -0000	1.6
+++ auth-request.h	9 Jan 2005 00:49:18 -0000	1.7
@@ -17,37 +17,40 @@
 
 	struct mech_module *mech;
 	struct auth *auth;
-	struct auth_client_connection *conn;
 
+	unsigned int connect_uid;
+	unsigned int client_pid;
 	unsigned int id;
 	time_t created;
 
 	const char *service;
 	struct ip_addr local_ip, remote_ip;
+
 	mech_callback_t *callback;
+	void *context;
 
 	unsigned int successful:1;
 	unsigned int internal_failure:1;
+	unsigned int finished:1;
+	unsigned int delayed_failure:1;
 	unsigned int accept_input:1;
 	unsigned int no_failure_delay:1;
 	unsigned int no_login:1;
 	unsigned int proxy:1;
-	unsigned int destroyed:1;
 	/* ... mechanism specific data ... */
 };
 
-void auth_request_success(struct auth_request *request,
-			  const void *data, size_t data_size);
-void auth_request_fail(struct auth_request *request);
-void auth_request_internal_failure(struct auth_request *request);
-
 struct auth_request *
 auth_request_new(struct auth *auth, struct mech_module *mech,
-		 mech_callback_t *callback);
-void auth_request_destroy(struct auth_request *request);
+		 mech_callback_t *callback, void *context);
 void auth_request_ref(struct auth_request *request);
 int auth_request_unref(struct auth_request *request);
 
+void auth_request_success(struct auth_request *request,
+			  const void *data, size_t data_size);
+void auth_request_fail(struct auth_request *request);
+void auth_request_internal_failure(struct auth_request *request);
+
 void auth_request_initial(struct auth_request *request,
 			  const unsigned char *data, size_t data_size);
 void auth_request_continue(struct auth_request *request,
@@ -86,9 +89,4 @@
 			    const char *subsystem,
 			    const char *format, ...) __attr_format__(3, 4);
 
-void auth_failure_buf_flush(void);
-
-void auth_requests_init(void);
-void auth_requests_deinit(void);
-
 #endif

Index: main.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/main.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -d -r1.36 -r1.37
--- main.c	9 Jan 2005 00:48:03 -0000	1.36
+++ main.c	9 Jan 2005 00:49:18 -0000	1.37
@@ -11,7 +11,7 @@
 #include "password-scheme.h"
 #include "mech.h"
 #include "auth.h"
-#include "auth-request.h"
+#include "auth-request-handler.h"
 #include "auth-master-connection.h"
 #include "auth-client-connection.h"
 
@@ -153,7 +153,7 @@
 		str = t_strdup_printf("AUTH_%u_MASTER", i);
 		master_fd = create_unix_listener(str);
 
-		master = auth_master_connection_create(auth, -1, getpid());
+		master = auth_master_connection_create(auth, -1);
 		if (master_fd != -1) {
 			auth_master_connection_add_listener(master, master_fd,
 							    master_path, FALSE);
@@ -191,19 +191,18 @@
 {
 	struct auth_master_connection *master, **master_p;
 	size_t i, size;
-	const char *env;
-	unsigned int pid;
+
+	process_start_time = ioloop_time;
 
 	process_start_time = ioloop_time;
 
 	mech_init();
 	auth_init(auth);
-	auth_requests_init();
+	auth_request_handlers_init();
 
 	lib_init_signals(sig_quit);
 
-	env = getenv("AUTH_PROCESS");
-	standalone = env == NULL;
+	standalone = getenv("DOVECOT_MASTER") == NULL;
 	if (standalone) {
 		/* starting standalone */
 		if (getenv("AUTH_1") == NULL) {
@@ -230,12 +229,7 @@
 				i_fatal("chdir(/) failed: %m");
 		}
        } else {
-		pid = atoi(env);
-		if (pid == 0)
-			i_fatal("AUTH_PROCESS can't be 0");
-
-		master = auth_master_connection_create(auth, MASTER_SOCKET_FD,
-						       pid);
+		master = auth_master_connection_create(auth, MASTER_SOCKET_FD);
 		auth_master_connection_add_listener(master, LOGIN_LISTEN_FD,
 						    NULL, TRUE);
 		auth_client_connections_init(master);
@@ -257,7 +251,7 @@
         if (lib_signal_kill != 0)
 		i_warning("Killed with signal %d", lib_signal_kill);
 
-	auth_failure_buf_flush();
+	auth_request_handlers_flush_failures();
 
 	master = buffer_get_modifyable_data(masters_buf, &size);
 	size /= sizeof(*master);
@@ -265,7 +259,7 @@
 		auth_master_connection_destroy(master[i]);
 
         password_schemes_deinit();
-	auth_requests_deinit();
+	auth_request_handlers_deinit();
 	auth_deinit(auth);
 	mech_deinit();
 

Index: mech-apop.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-apop.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- mech-apop.c	9 Jan 2005 00:48:03 -0000	1.14
+++ mech-apop.c	9 Jan 2005 00:49:18 -0000	1.15
@@ -101,7 +101,7 @@
 
 	if (sscanf((const char *)data, "<%lx.%lx.%lx.",
 		   &pid, &connect_uid, &timestamp) != 3 ||
-	    connect_uid != auth_request->conn->connect_uid ||
+	    connect_uid != auth_request->connect_uid ||
             pid != (unsigned long)getpid() ||
 	    (time_t)timestamp < process_start_time) {
 		auth_request_log_info(auth_request, "apop",



More information about the dovecot-cvs mailing list