[dovecot-cvs] dovecot/src/auth Makefile.am, 1.34, 1.35 auth-client-connection.c, 1.12, 1.13 auth-client-connection.h, 1.2, 1.3 auth-client-interface.h, 1.8, 1.9 auth-master-connection.c, 1.11, 1.12 auth-master-connection.h, 1.4, 1.5 auth-master-interface.h, 1.5, NONE mech-anonymous.c, 1.5, 1.6 mech-apop.c, 1.5, 1.6 mech-cram-md5.c, 1.12, 1.13 mech-digest-md5.c, 1.25, 1.26 mech-login.c, 1.3, 1.4 mech-ntlm.c, 1.6, 1.7 mech-plain.c, 1.21, 1.22 mech-rpa.c, 1.5, 1.6 mech.c, 1.41, 1.42 mech.h, 1.22, 1.23 userdb.h, 1.10, 1.11

cras at dovecot.org cras at dovecot.org
Wed Oct 13 19:38:35 EEST 2004


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

Modified Files:
	Makefile.am auth-client-connection.c auth-client-connection.h 
	auth-client-interface.h auth-master-connection.c 
	auth-master-connection.h mech-anonymous.c mech-apop.c 
	mech-cram-md5.c mech-digest-md5.c mech-login.c mech-ntlm.c 
	mech-plain.c mech-rpa.c mech.c mech.h userdb.h 
Removed Files:
	auth-master-interface.h 
Log Message:
Changed dovecot-auth protocol to ASCII based. Should be easier now to write
replacement server if needed by someone. Also cleaned up/made more
consistent auth code. The new code could still use some cleaning though..



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/Makefile.am,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- Makefile.am	10 Oct 2004 13:55:12 -0000	1.34
+++ Makefile.am	13 Oct 2004 16:38:32 -0000	1.35
@@ -71,7 +71,6 @@
 	auth-client-connection.h \
 	auth-client-interface.h \
 	auth-master-connection.h \
-	auth-master-interface.h \
 	auth-module.h \
 	db-ldap.h \
 	db-mysql.h \

Index: auth-client-connection.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-connection.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- auth-client-connection.c	10 Oct 2004 14:21:07 -0000	1.12
+++ auth-client-connection.c	13 Oct 2004 16:38:32 -0000	1.13
@@ -5,48 +5,99 @@
 #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 "mech.h"
 #include "auth-client-connection.h"
 #include "auth-master-connection.h"
 
 #include <stdlib.h>
-#include <syslog.h>
 
-#define MAX_INBUF_SIZE \
-	(sizeof(struct auth_client_request_continue) + \
-	 AUTH_CLIENT_MAX_REQUEST_DATA_SIZE)
+/* Used only for string sanitization. */
+#define MAX_MECH_NAME_LEN 64
+
 #define MAX_OUTBUF_SIZE (1024*50)
 
 static void auth_client_connection_unref(struct auth_client_connection *conn);
 
-static void request_callback(struct auth_client_request_reply *reply,
-			     const void *data,
-			     struct auth_client_connection *conn)
+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, ...)
 {
-	struct const_iovec iov[2];
+	va_list args;
+	string_t *str;
 	ssize_t ret;
 
-	iov[0].iov_base = reply;
-	iov[0].iov_len = sizeof(*reply);
-	iov[1].iov_base = data;
-	iov[1].iov_len = reply->data_size;
+	i_assert(conn->refcount > 1);
 
-	ret = o_stream_sendv(conn->output, iov, 2);
-	if (ret == (ssize_t)(iov[0].iov_len + iov[1].iov_len)) {
-		/* all sent */
-		auth_client_connection_unref(conn);
-		return;
+	t_push();
+	va_start(args, fmt);
+	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(conn);
 	}
+	va_end(args);
+	t_pop();
+}
 
-	if (ret >= 0) {
-		i_warning("Auth client %u: Transmit buffer full, killing it",
-			  conn->pid);
+static void auth_callback(struct auth_request *request,
+			  enum auth_client_result result,
+			  const void *reply, size_t reply_size)
+{
+	string_t *str = NULL;
+	ssize_t ret;
+
+	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;
+		break;
+	case AUTH_CLIENT_RESULT_SUCCESS:
+		str = t_str_new(128 + MAX_BASE64_ENCODED_SIZE(reply_size));
+		str_printfa(str, "OK\t%u\t%s", request->id, request->user);
+		if (reply_size > 0) {
+			str_append(str, "\tresp=");
+			base64_encode(reply, reply_size, str);
+		}
+		break;
+	case AUTH_CLIENT_RESULT_FAILURE:
+		str = t_str_new(128);
+		str_printfa(str, "FAIL\t%u", request->id);
+		if (reply != NULL) {
+			str_append_c(str, '\t');
+			str_append(str, reply);
+		}
+		break;
 	}
 
-	auth_client_connection_destroy(conn);
-	auth_client_connection_unref(conn);
+	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(request->conn);
+	}
+	t_pop();
+
+	auth_client_connection_unref(request->conn);
 }
 
 struct auth_client_connection *
@@ -63,106 +114,229 @@
 	return NULL;
 }
 
-static int auth_client_input_handshake(struct auth_client_connection *conn)
+static int
+auth_client_input_proto(struct auth_client_connection *conn, const char *args)
 {
-        struct auth_client_handshake_request rec;
-        unsigned char *data;
-	size_t size;
+	if (conn->default_protocol == NULL)
+		conn->default_protocol = p_strdup(conn->pool, args);
+	return TRUE;
+}
 
-	data = i_stream_get_modifyable_data(conn->input, &size);
-	if (size < sizeof(rec))
-		return FALSE;
+static int
+auth_client_input_cpid(struct auth_client_connection *conn, const char *args)
+{
+        struct auth_client_connection *old;
+	unsigned int pid;
 
-	/* Don't just cast because of alignment issues. */
-	memcpy(&rec, data, sizeof(rec));
-	i_stream_skip(conn->input, sizeof(rec));
+	if (conn->pid != 0) {
+		i_error("BUG: Authentication client re-handshaking");
+		return FALSE;
+	}
 
-	if (rec.client_pid == 0) {
-		i_error("BUG: Auth client said it's PID 0");
-		auth_client_connection_destroy(conn);
+	pid = (unsigned int)strtoul(args, NULL, 10);
+	if (pid == 0) {
+		i_error("BUG: Authentication client said it's PID 0");
 		return FALSE;
 	}
 
-	if (auth_client_connection_lookup(conn->master,
-					  rec.client_pid) != NULL) {
-		/* well, it might have just reconnected very fast .. although
-		   there's not much reason for it. */
-		i_error("BUG: Auth client gave a PID %u of existing connection",
-			rec.client_pid);
-		auth_client_connection_destroy(conn);
+	old = auth_client_connection_lookup(conn->master, pid);
+	if (old != NULL) {
+		/* already exists. it's possible that it just reconnected,
+		   see if the old connection is still there. */
+		if (i_stream_read(old->input) == -1) {
+                        auth_client_connection_destroy(old);
+			old = NULL;
+		}
+	}
+
+	if (old != NULL) {
+		i_error("BUG: Authentication client gave a PID "
+			"%u of existing connection", pid);
 		return FALSE;
 	}
 
-	conn->pid = rec.client_pid;
+	conn->pid = pid;
 	return TRUE;
 }
 
-static int auth_client_input_request(struct auth_client_connection *conn)
+static int
+auth_client_input_auth(struct auth_client_connection *conn, const char *args)
 {
-        enum auth_client_request_type type;
-        unsigned char *data;
-	size_t size;
+	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;
 
-	data = i_stream_get_modifyable_data(conn->input, &size);
-	if (size < sizeof(type))
+	if (conn->pid == 0) {
+		i_error("BUG: Authentication client %u didn't send handshake",
+			conn->pid);
 		return FALSE;
+	}
 
-	/* note that we can't directly cast the received data pointer into
-	   structures, as it may not be aligned properly. */
-	memcpy(&type, data, sizeof(type));
+	/* <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;
+	}
 
-	conn->refcount++;
-	switch (type) {
-	case AUTH_CLIENT_REQUEST_NEW: {
-		struct auth_client_request_new request;
+	id = (unsigned int)strtoul(list[0], NULL, 10);
 
-		if (size < sizeof(request))
-			return FALSE;
+	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;
+	}
 
-		memcpy(&request, data, sizeof(request));
-		if (size < sizeof(request) + request.data_size)
-			return FALSE;
+	request = auth_request_new(mech);
+	if (request == NULL)
+		return TRUE;
 
-		/* we have a full init request */
-		conn->refcount++;
-		mech_request_new(conn, &request, data + sizeof(request),
-				 request_callback);
-		i_stream_skip(conn->input, sizeof(request) + request.data_size);
-		break;
+	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, "proto") == 0)
+			request->protocol = 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;
 	}
-	case AUTH_CLIENT_REQUEST_CONTINUE: {
-                struct auth_client_request_continue request;
 
-		if (size < sizeof(request))
-			return FALSE;
+	if (request->protocol == NULL)
+		request->protocol = conn->default_protocol;
+	if (request->protocol == NULL) {
+		i_error("BUG: Authentication client %u "
+			"didn't specify protocol in request", conn->pid);
+		auth_request_destroy(request);
+		return FALSE;
+	}
 
-		memcpy(&request, data, sizeof(request));
-		if (size < sizeof(request) + request.data_size)
-			return FALSE;
+	if (ssl_require_client_cert && !valid_client_cert) {
+		/* we fail without valid certificate */
+		if (verbose) {
+			i_info("ssl-cert-check(%s): "
+			       "Client didn't present valid SSL certificate",
+			       get_log_prefix(request));
+		}
+		auth_request_destroy(request);
+		auth_client_send(conn, "FAIL\t%u", id);
+		return TRUE;
+	}
 
-		/* we have a full continued request */
-		conn->refcount++;
-		mech_request_continue(conn, &request, data + sizeof(request),
-				      request_callback);
+	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) {
+			if (verbose) {
+				i_info("%s(%s): Invalid base64 data in "
+				       "initial response", mech->mech_name,
+				       get_log_prefix(request));
+			}
+			auth_request_destroy(request);
+			auth_client_send(conn, "FAIL\t%u\t"
+				"Invalid base64 data in initial response", id);
+			return TRUE;
+		}
+		initial_resp_data = buf->data;
+		initial_resp_len = buf->used;
+	}
+	hash_insert(conn->auth_requests, POINTER_CAST(id), request);
 
-		/* clear any sensitive data from memory */
-		safe_memset(data + sizeof(request), 0, request.data_size);
-		i_stream_skip(conn->input, sizeof(request) + request.data_size);
-		break;
+	/* connection is referenced only until auth_callback is called. */
+	conn->refcount++;
+	mech->auth_initial(request, initial_resp_data, initial_resp_len,
+			   auth_callback);
+	return TRUE;
+}
+
+static int
+auth_client_input_cont(struct auth_client_connection *conn, 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 %u "
+			"sent broken CONT request", conn->pid);
+		return FALSE;
 	}
-	default:
-		/* unknown request */
-		i_error("BUG: Auth client %u sent us unknown request type %u",
-			conn->pid, type);
-		auth_client_connection_destroy(conn);
+
+	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\tTimeouted", id);
+		return TRUE;
 	}
-	auth_client_connection_unref(conn);
+
+	if (!request->accept_input) {
+		auth_client_send(conn, "FAIL\t%u\tUnexpected continuation", id);
+		auth_request_destroy(request);
+		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) {
+		if (verbose) {
+			i_info("%s(%s): Invalid base64 data in "
+			       "continued response", request->mech->mech_name,
+			       get_log_prefix(request));
+		}
+		auth_client_send(conn, "FAIL\t%u\tInvalid base64 data in "
+				 "continued response", id);
+		auth_request_destroy(request);
+		return TRUE;
+	}
+
+	conn->refcount++;
+	request->mech->auth_continue(request, buf->data, buf->used,
+				     auth_callback);
 	return TRUE;
 }
 
 static void auth_client_input(void *context)
 {
-	struct auth_client_connection *conn  = context;
+	struct auth_client_connection *conn = context;
+	char *line;
+	int ret;
 
 	switch (i_stream_read(conn->input)) {
 	case 0:
@@ -174,18 +348,35 @@
 	case -2:
 		/* buffer full */
 		i_error("BUG: Auth client %u sent us more than %d bytes",
-			conn->pid, (int)MAX_INBUF_SIZE);
+			conn->pid, (int)AUTH_CLIENT_MAX_LINE_LENGTH);
 		auth_client_connection_destroy(conn);
 		return;
 	}
 
-	if (conn->pid == 0) {
-		if (!auth_client_input_handshake(conn))
-			return;
-	}
+	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 if (strncmp(line, "PROTO\t", 6) == 0)
+			ret = auth_client_input_proto(conn, line + 6);
+		else {
+			/* ignore unknown command */
+			ret = TRUE;
+		}
+		safe_memset(line, 0, strlen(line));
+		t_pop();
 
-	while (auth_client_input_request(conn))
-		;
+		if (!ret) {
+			auth_client_connection_destroy(conn);
+			break;
+		}
+	}
+	auth_client_connection_unref(conn);
 }
 
 struct auth_client_connection *
@@ -193,8 +384,8 @@
 {
 	static unsigned int connect_uid_counter = 0;
 	struct auth_client_connection *conn;
-	struct auth_client_handshake_reply handshake_reply;
 	struct const_iovec iov[2];
+	string_t *str;
 
 	pool_t pool;
 
@@ -206,7 +397,8 @@
 	conn->connect_uid = ++connect_uid_counter;
 
 	conn->fd = fd;
-	conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
+	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);
@@ -218,13 +410,14 @@
 	conn->next = master->clients;
 	master->clients = conn;
 
-	handshake_reply = *master->handshake_reply;
-	handshake_reply.connect_uid = conn->connect_uid;
+	str = t_str_new(128);
+	str_printfa(str, "SPID\t%u\nCUID\t%u\nDONE\n",
+		    master->pid, conn->connect_uid);
 
-	iov[0].iov_base = &handshake_reply;
-	iov[0].iov_len = sizeof(handshake_reply);
-	iov[1].iov_base = master->handshake_reply + 1;
-	iov[1].iov_len = handshake_reply.data_size;
+	iov[0].iov_base = str_data(mech_handshake);
+	iov[0].iov_len = str_len(mech_handshake);
+	iov[1].iov_base = str_data(str);
+	iov[1].iov_len = str_len(str);
 
 	if (o_stream_sendv(conn->output, iov, 2) < 0) {
 		auth_client_connection_destroy(conn);

Index: auth-client-connection.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-connection.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- auth-client-connection.h	2 Jul 2004 22:03:37 -0000	1.2
+++ auth-client-connection.h	13 Oct 2004 16:38:32 -0000	1.3
@@ -1,8 +1,6 @@
 #ifndef __AUTH_CLIENT_CONNECTION_H
 #define __AUTH_CLIENT_CONNECTION_H
 
-#include "auth-client-interface.h"
-
 struct auth_client_connection {
 	struct auth_client_connection *next;
 
@@ -16,6 +14,7 @@
 
 	pool_t pool;
 	struct hash_table *auth_requests;
+	char *default_protocol;
 
 	unsigned int pid;
 	unsigned int connect_uid;

Index: auth-client-interface.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-client-interface.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- auth-client-interface.h	2 Sep 2004 19:18:14 -0000	1.8
+++ auth-client-interface.h	13 Oct 2004 16:38:32 -0000	1.9
@@ -1,91 +1,24 @@
 #ifndef __AUTH_CLIENT_INTERFACE_H
 #define __AUTH_CLIENT_INTERFACE_H
 
-/* max. size for auth_client_request_continue.data[] */
-#define AUTH_CLIENT_MAX_REQUEST_DATA_SIZE 4096
-
-/* Client process must finish with single authentication requests in this time,
-   or the whole connection will be killed. */
+#define AUTH_CLIENT_MAX_LINE_LENGTH 8192
 #define AUTH_REQUEST_TIMEOUT 120
 
-enum auth_client_request_new_flags {
-	AUTH_CLIENT_FLAG_SSL_ENABLED		= 0x01,
-	AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT	= 0x02
-};
-
-enum auth_client_request_type {
-	AUTH_CLIENT_REQUEST_NEW = 1,
-        AUTH_CLIENT_REQUEST_CONTINUE
-};
-
-enum auth_client_result {
-	AUTH_CLIENT_RESULT_CONTINUE = 1,
-	AUTH_CLIENT_RESULT_SUCCESS,
-	AUTH_CLIENT_RESULT_FAILURE
-};
-
-/* Client -> Server */
-struct auth_client_handshake_request {
-	unsigned int client_pid; /* unique identifier for client process */
-};
-
-struct auth_client_handshake_mech_desc {
-	uint32_t name_idx;
-	unsigned int plaintext:1;
-	unsigned int advertise:1;
-};
-
-/* Server -> Client */
-struct auth_client_handshake_reply {
-	unsigned int server_pid; /* unique auth process identifier */
-	unsigned int connect_uid; /* unique connection identifier */
-
-	uint32_t mech_count;
-	uint32_t data_size;
-	/* struct auth_client_handshake_mech_desc mech_desc[auth_mech_count]; */
-};
-
-/* New authentication request */
-struct auth_client_request_new {
-	enum auth_client_request_type type; /* AUTH_CLIENT_REQUEST_NEW */
-	unsigned int id; /* unique ID for the request */
-
-	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;
-
-	uint32_t data_size;
-	/* unsigned char data[]; */
-};
-#define AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request) \
-        ((request)->initial_resp_idx != (request)->data_size)
-
-/* Continue authentication request */
-struct auth_client_request_continue {
-	enum auth_client_request_type type; /* AUTH_CLIENT_REQUEST_CONTINUE */
-	unsigned int id;
-
-	uint32_t data_size;
-	/* unsigned char data[]; */
-};
-
-/* Reply to authentication */
-struct auth_client_request_reply {
-	unsigned int id;
-
-	enum auth_client_result result;
-
-	/* variable width data, indexes into data[].
-	   Ignore if it points outside data_size. */
-	uint32_t username_idx; /* NUL-terminated */
-	uint32_t reply_idx; /* last, non-NUL terminated */
-
-	uint32_t data_size;
-	/* unsigned char data[]; */
+enum mech_security_flags {
+	/* Don't advertise this as available SASL mechanism (eg. APOP) */
+	MECH_SEC_PRIVATE		= 0x0001,
+	/* Anonymous authentication */
+	MECH_SEC_ANONYMOUS		= 0x0002,
+	/* Transfers plaintext passwords */
+	MECH_SEC_PLAINTEXT		= 0x0004,
+	/* Subject to passive (dictionary) attack */
+	MECH_SEC_DICTIONARY		= 0x0008,
+	/* Subject to active (non-dictionary) attack */
+	MECH_SEC_ACTIVE			= 0x0010,
+	/* Provides forward secrecy between sessions */
+	MECH_SEC_FORWARD_SECRECY	= 0x0020,
+	/* Provides mutual authentication */
+	MECH_SEC_MUTUAL_AUTH		= 0x0040,
 };
 
 #endif

Index: auth-master-connection.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-master-connection.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- auth-master-connection.c	8 Oct 2004 17:51:47 -0000	1.11
+++ auth-master-connection.c	13 Oct 2004 16:38:32 -0000	1.12
@@ -3,7 +3,9 @@
 #include "common.h"
 #include "buffer.h"
 #include "hash.h"
+#include "str.h"
 #include "ioloop.h"
+#include "istream.h"
 #include "ostream.h"
 #include "network.h"
 #include "mech.h"
@@ -12,12 +14,11 @@
 #include "auth-master-connection.h"
 
 #include <unistd.h>
+#include <stdlib.h>
 
+#define MAX_INBUF_SIZE 1024
 #define MAX_OUTBUF_SIZE (1024*50)
 
-static struct auth_master_reply failure_reply =
-{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
 struct auth_listener {
 	struct auth_master_connection *master;
 	int client_listener;
@@ -28,164 +29,162 @@
 
 struct master_userdb_request {
 	struct auth_master_connection *conn;
-	unsigned int tag;
+	unsigned int id;
 };
 
 static void master_output(void *context);
 static void auth_master_connection_close(struct auth_master_connection *conn);
 static int auth_master_connection_unref(struct auth_master_connection *conn);
 
-static size_t reply_add(buffer_t *buf, const char *str)
+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, ...)
 {
-	size_t index;
-
-	if (str == NULL || *str == '\0')
-		return (size_t)-1;
+	va_list args;
+	string_t *str;
 
-	index = buffer_get_used_size(buf) - sizeof(struct auth_master_reply);
-	buffer_append(buf, str, strlen(str)+1);
-	return index;
+	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 struct auth_master_reply *
-fill_reply(const struct user_data *user, size_t *reply_size)
+static void append_user_reply(string_t *str, const struct user_data *user)
 {
-	struct auth_master_reply reply, *reply_p;
-	buffer_t *buf;
-	char *p;
-
-	buf = buffer_create_dynamic(pool_datastack_create(),
-				    sizeof(reply) + 256);
-	memset(&reply, 0, sizeof(reply));
-	buffer_append(buf, &reply, sizeof(reply));
-
-	reply.success = TRUE;
+	const char *p;
 
-	reply.uid = user->uid;
-	reply.gid = user->gid;
+	str_append(str, user->virtual_user);
+	str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user,
+		    dec2str(user->uid), dec2str(user->gid));
 
-	reply.system_user_idx = reply_add(buf, user->system_user);
-	reply.virtual_user_idx = reply_add(buf, user->virtual_user);
-	reply.mail_idx = reply_add(buf, user->mail);
+	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) {
-		reply.home_idx = reply_add(buf, user->home);
-		reply.chroot_idx = reply_add(buf, NULL);
+		if (user->home != NULL)
+			str_printfa(str, "\thome=%s", user->home);
 	} else {
 		/* wu-ftpd like <chroot>/./<home> */
-		reply.chroot_idx =
-			reply_add(buf, t_strdup_until(user->home, p));
-		reply.home_idx = reply_add(buf, p + 3);
-	}
-
-	*reply_size = buffer_get_used_size(buf);
-	reply.data_size = *reply_size - sizeof(reply);
-
-	reply_p = buffer_get_space_unsafe(buf, 0, sizeof(reply));
-	*reply_p = reply;
-
-	return reply_p;
-}
-
-static void master_send_reply(struct auth_master_connection *conn,
-			      struct auth_master_reply *reply,
-			      size_t reply_size, unsigned int tag)
-{
-	ssize_t ret;
-
-	reply->tag = tag;
-
-	ret = o_stream_send(conn->output, reply, reply_size);
-	if (ret < 0) {
-		/* master died, kill ourself too */
-		auth_master_connection_close(conn);
-		return;
-	}
-	i_assert((size_t)ret == reply_size);
-
-	if (o_stream_get_buffer_used_size(conn->output) >= MAX_OUTBUF_SIZE) {
-		/* buffer full, stop accepting more input */
-		if (conn->io != NULL) {
-			io_remove(conn->io);
-			conn->io = NULL;
-		}
+		str_printfa(str, "\thome=%s\tchroot=%s",
+			    p + 3, t_strdup_until(user->home, p));
 	}
 }
 
-static void userdb_callback(struct user_data *user, void *context)
+static void userdb_callback(const struct user_data *user, void *context)
 {
 	struct master_userdb_request *master_request = context;
-	struct auth_master_reply *reply;
-	size_t reply_size;
+	string_t *str;
 
 	if (auth_master_connection_unref(master_request->conn)) {
 		if (user == NULL) {
-			master_send_reply(master_request->conn, &failure_reply,
-					  sizeof(failure_reply),
-					  master_request->tag);
+			master_send(master_request->conn, "NOTFOUND\t%u",
+				    master_request->id);
 		} else {
-			reply = fill_reply(user, &reply_size);
-			master_send_reply(master_request->conn, reply,
-					  reply_size, master_request->tag);
+			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));
 		}
 	}
 	i_free(master_request);
 }
 
-static void master_handle_request(struct auth_master_connection *conn,
-				  struct auth_master_request *request)
+static int
+master_input_request(struct auth_master_connection *conn, const char *args)
 {
 	struct auth_client_connection *client_conn;
-	struct auth_request *auth_request;
 	struct master_userdb_request *master_request;
+	struct auth_request *request;
+	const char *const *list;
+	unsigned int id, client_pid, client_id;
 
-	client_conn = auth_client_connection_lookup(conn, request->client_pid);
-	auth_request = client_conn == NULL ? NULL :
+	/* <id> <client-pid> <client-id> */
+	list = t_strsplit(args, "\t");
+	if (list[0] == NULL || list[1] == NULL || list[2] == NULL) {
+		i_error("BUG: Master sent broken REQUEST");
+		return FALSE;
+	}
+
+	id = (unsigned int)strtoul(list[0], NULL, 10);
+	client_pid = (unsigned int)strtoul(list[1], NULL, 10);
+	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(request->id));
+			    POINTER_CAST(client_id));
 
-	if (auth_request == NULL) {
+	if (request == NULL) {
 		if (verbose) {
 			i_info("Master request %u.%u not found",
-			       request->client_pid, request->id);
+			       client_pid, client_id);
 		}
-		master_send_reply(conn, &failure_reply, sizeof(failure_reply),
-				  request->tag);
+		master_send(conn, "NOTFOUND\t%u", id);
 	} else {
 		master_request = i_new(struct master_userdb_request, 1);
 		master_request->conn = conn;
-		master_request->tag = request->tag;
+		master_request->id = id;
 
 		conn->refcount++;
-		userdb->lookup(auth_request, userdb_callback,
-			       master_request);
+		userdb->lookup(request, userdb_callback, master_request);
 
 		/* the auth request is finished, we don't need it anymore */
-		mech_request_free(auth_request, request->id);
+		auth_request_destroy(request);
 	}
+	return TRUE;
+}
+
+static int
+master_input_die(struct auth_master_connection *conn)
+{
+	return TRUE;
 }
 
 static void master_input(void *context)
 {
 	struct auth_master_connection *conn = context;
+ 	char *line;
 	int ret;
 
-	ret = net_receive(conn->fd,
-			  conn->request_buf + conn->request_pos,
-			  sizeof(conn->request_buf) - conn->request_pos);
-	if (ret < 0) {
-		/* master died, kill ourself too */
+	switch (i_stream_read(conn->input)) {
+	case 0:
+		return;
+	case -1:
+		/* disconnected */
+                auth_master_connection_close(conn);
+		return;
+	case -2:
+		/* buffer full */
+		i_error("BUG: Master sent us more than %d bytes",
+			(int)MAX_INBUF_SIZE);
                 auth_master_connection_close(conn);
 		return;
 	}
 
-	conn->request_pos += ret;
-	if (conn->request_pos >= sizeof(conn->request_buf)) {
-		/* reply is now read */
-		master_handle_request(conn, (struct auth_master_request *)
-				      conn->request_buf);
-		conn->request_pos = 0;
+	while ((line = i_stream_next_line(conn->input)) != NULL) {
+		t_push();
+		if (strncmp(line, "REQUEST\t", 8) == 0)
+			ret = master_input_request(conn, line + 8);
+		else if (strcmp(line, "DIE") == 0)
+			ret = master_input_die(conn);
+		else {
+			/* ignore unknown command */
+			ret = TRUE;
+		}
+		t_pop();
+
+		if (!ret) {
+			auth_master_connection_close(conn);
+			return;
+		}
 	}
 }
 
@@ -206,56 +205,18 @@
 	}
 }
 
-static void master_get_handshake_reply(struct auth_master_connection *master)
-{
-	struct mech_module_list *list;
-	buffer_t *buf;
-	struct auth_client_handshake_reply reply;
-	struct auth_client_handshake_mech_desc mech_desc;
-	uint32_t mech_desc_offset;
-
-	memset(&reply, 0, sizeof(reply));
-	memset(&mech_desc, 0, sizeof(mech_desc));
-
-	reply.server_pid = master->pid;
-
-	buf = buffer_create_dynamic(default_pool, 128);
-
-	for (list = mech_modules; list != NULL; list = list->next)
-		reply.mech_count++;
-	buffer_set_used_size(buf, sizeof(reply) +
-			     sizeof(mech_desc) * reply.mech_count);
-
-	mech_desc_offset = sizeof(reply);
-	for (list = mech_modules; list != NULL; list = list->next) {
-		mech_desc.name_idx = buffer_get_used_size(buf) - sizeof(reply);
-		mech_desc.plaintext = list->module.plaintext;
-		mech_desc.advertise = list->module.advertise;
-
-		memcpy(buffer_get_space_unsafe(buf, mech_desc_offset,
-					       sizeof(mech_desc)),
-		       &mech_desc, sizeof(mech_desc));
-		buffer_append(buf, list->module.mech_name,
-			      strlen(list->module.mech_name) + 1);
-
-		mech_desc_offset += sizeof(mech_desc);
-	}
-
-	reply.data_size = buffer_get_used_size(buf) - sizeof(reply);
-	memcpy(buffer_get_space_unsafe(buf, 0, sizeof(reply)),
-	       &reply, sizeof(reply));
-
-	master->handshake_reply = buffer_free_without_data(buf);
-}
-
 static void
 auth_master_connection_set_fd(struct auth_master_connection *conn, int fd)
 {
+	if (conn->input != NULL)
+		i_stream_unref(conn->input);
 	if (conn->output != NULL)
 		o_stream_unref(conn->output);
 	if (conn->io != NULL)
 		io_remove(conn->io);
 
+	conn->input = i_stream_create_file(fd, default_pool,
+					   MAX_INBUF_SIZE, FALSE);
 	conn->output = o_stream_create_file(fd, default_pool,
 					    (size_t)-1, FALSE);
 	o_stream_set_flush_callback(conn->output, master_output, conn);
@@ -276,22 +237,15 @@
 	conn->listeners_buf = buffer_create_dynamic(default_pool, 64);
 	if (fd != -1)
                 auth_master_connection_set_fd(conn, fd);
-	master_get_handshake_reply(conn);
 	return conn;
 }
 
 void auth_master_connection_send_handshake(struct auth_master_connection *conn)
 {
-	struct auth_master_handshake_reply reply;
-
 	/* just a note to master that we're ok. if we die before, it means
 	   we're broken and a simple restart most likely won't help. */
-	if (conn->output != NULL) {
-		memset(&reply, 0, sizeof(reply));
-		reply.server_pid = conn->pid;
-		if (o_stream_send(conn->output, &reply, sizeof(reply)) < 0)
-                        auth_master_connection_close(conn);
-	}
+	if (conn->output != NULL)
+		master_send(conn, "SPID\t%u", conn->pid);
 }
 
 static void auth_master_connection_close(struct auth_master_connection *conn)
@@ -350,7 +304,6 @@
 
 	if (conn->output != NULL)
 		o_stream_unref(conn->output);
-	i_free(conn->handshake_reply);
 	i_free(conn);
 	return FALSE;
 }

Index: auth-master-connection.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/auth-master-connection.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- auth-master-connection.h	23 Jun 2004 17:50:44 -0000	1.4
+++ auth-master-connection.h	13 Oct 2004 16:38:32 -0000	1.5
@@ -1,21 +1,16 @@
 #ifndef __AUTH_MASTER_CONNECTION_H
 #define __AUTH_MASTER_CONNECTION_H
 
-#include "auth-master-interface.h"
-
 struct auth_master_connection {
 	unsigned int pid;
 	int refcount;
 
 	int fd;
+	struct istream *input;
 	struct ostream *output;
 	struct io *io;
 	buffer_t *listeners_buf;
 
-	unsigned int request_pos;
-	unsigned char request_buf[sizeof(struct auth_master_request)];
-
-	struct auth_client_handshake_reply *handshake_reply;
 	struct auth_client_connection *clients;
 	struct timeout *to_clients;
 

--- auth-master-interface.h DELETED ---

Index: mech-anonymous.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-anonymous.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mech-anonymous.c	31 May 2004 18:57:25 -0000	1.5
+++ mech-anonymous.c	13 Oct 2004 16:38:32 -0000	1.6
@@ -1,85 +1,72 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2004 Timo Sirainen */
 
 #include "common.h"
 #include "mech.h"
 
-static int
-mech_anonymous_auth_continue(struct auth_request *auth_request,
+static void
+mech_anonymous_auth_continue(struct auth_request *request,
 			     const unsigned char *data, size_t data_size,
 			     mech_callback_t *callback)
 {
 	i_assert(anonymous_username != NULL);
 
 	if (verbose) {
-		auth_request->user =
+		/* temporarily set the user to the one that was given,
+		   so that the log message goes right */
+		request->user =
 			p_strndup(pool_datastack_create(), data, data_size);
 		i_info("anonymous(%s): login",
-		       get_log_prefix(auth_request));
+		       get_log_prefix(request));
 	}
 
-	auth_request->callback = callback;
-	auth_request->user = p_strdup(auth_request->pool, anonymous_username);
+	request->callback = callback;
+	request->user = p_strdup(request->pool, anonymous_username);
 
-	mech_auth_finish(auth_request, NULL, 0, TRUE);
-	return TRUE;
+	mech_auth_finish(request, NULL, 0, TRUE);
 }
 
-static int
-mech_anonymous_auth_initial(struct auth_request *auth_request,
-			    struct auth_client_request_new *request,
-			    const unsigned char *data,
+static void
+mech_anonymous_auth_initial(struct auth_request *request,
+			    const unsigned char *data, size_t data_size,
 			    mech_callback_t *callback)
 {
-	struct auth_client_request_reply reply;
-	size_t data_size;
-
-	if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
-		data += request->initial_resp_idx;
-		data_size = request->data_size - request->initial_resp_idx;
-
-		return auth_request->auth_continue(auth_request, data,
-						   data_size, callback);
+	if (data_size == 0)
+		callback(request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
+	else {
+		mech_anonymous_auth_continue(request, data, data_size,
+					     callback);
 	}
-
-	/* initialize reply */
-	memset(&reply, 0, sizeof(reply));
-	reply.id = auth_request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	callback(&reply, NULL, auth_request->conn);
-	return TRUE;
 }
 
 static void
-mech_anonymous_auth_free(struct auth_request *auth_request)
+mech_anonymous_auth_free(struct auth_request *request)
 {
-	pool_unref(auth_request->pool);
+	pool_unref(request->pool);
 }
 
 static struct auth_request *mech_anonymous_auth_new(void)
 {
-        struct auth_request *auth_request;
+        struct auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("anonymous_auth_request", 256);
-	auth_request = p_new(pool, struct auth_request, 1);
-	auth_request->refcount = 1;
-	auth_request->pool = pool;
-	auth_request->auth_initial = mech_anonymous_auth_initial;
-	auth_request->auth_continue = mech_anonymous_auth_continue;
-        auth_request->auth_free = mech_anonymous_auth_free;
+	request = p_new(pool, struct auth_request, 1);
+	request->refcount = 1;
+	request->pool = pool;
 
-	return auth_request;
+	return request;
 }
 
 struct mech_module mech_anonymous = {
 	"ANONYMOUS",
 
-	MEMBER(plaintext) FALSE,
-	MEMBER(advertise) TRUE,
+	MEMBER(flags) MECH_SEC_ANONYMOUS,
 
 	MEMBER(passdb_need_plain) FALSE,
 	MEMBER(passdb_need_credentials) FALSE,
 
-	mech_anonymous_auth_new
+	mech_anonymous_auth_new,
+	mech_anonymous_auth_initial,
+	mech_anonymous_auth_continue,
+        mech_anonymous_auth_free
 };

Index: mech-apop.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-apop.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mech-apop.c	15 Sep 2004 13:20:16 -0000	1.5
+++ mech-apop.c	13 Oct 2004 16:38:32 -0000	1.6
@@ -35,7 +35,7 @@
 apop_credentials_callback(const char *credentials,
 			  struct auth_request *auth_request)
 {
-	struct apop_auth_request *auth =
+	struct apop_auth_request *request =
 		(struct apop_auth_request *)auth_request;
 	unsigned char digest[16];
 	struct md5_context ctx;
@@ -43,41 +43,41 @@
 
 	if (credentials != NULL) {
 		md5_init(&ctx);
-		md5_update(&ctx, auth->challenge, strlen(auth->challenge));
+		md5_update(&ctx, request->challenge,
+			   strlen(request->challenge));
 		md5_update(&ctx, credentials, strlen(credentials));
 		md5_final(&ctx, digest);
 
-		ret = memcmp(digest, auth->digest, 16) == 0;
+		ret = memcmp(digest, request->digest, 16) == 0;
 	}
 
 	mech_auth_finish(auth_request, NULL, 0, ret);
 }
 
-static int
+static void
 mech_apop_auth_initial(struct auth_request *auth_request,
-		       struct auth_client_request_new *request,
-		       const unsigned char *data,
+		       const unsigned char *data, size_t data_size,
 		       mech_callback_t *callback)
 {
-	struct apop_auth_request *auth =
+	struct apop_auth_request *request =
 		(struct apop_auth_request *)auth_request;
 	const unsigned char *tmp, *end, *username = NULL;
 	const char *str, *error;
 
 	auth_request->callback = callback;
 
-	if (!AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
+	if (data_size == 0) {
 		/* Should never happen */
 		if (verbose) {
 			i_info("apop(%s): no initial respone",
 			       get_log_prefix(auth_request));
 		}
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 
-	tmp = data = data + request->initial_resp_idx;
-	end = data + request->data_size - request->initial_resp_idx;
+	tmp = data;
+	end = data + data_size;
 
 	while (tmp != end && *tmp != '\0')
 		tmp++;
@@ -93,9 +93,9 @@
 			       get_log_prefix(auth_request));
 		}
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
-	auth->challenge = p_strdup(auth->pool, (const char *)data);
+	request->challenge = p_strdup(request->pool, (const char *)data);
 
 	if (tmp != end) {
 		username = ++tmp;
@@ -110,58 +110,55 @@
 			       get_log_prefix(auth_request));
 		}
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 	tmp++;
 
-	auth_request->user = p_strdup(auth->pool, (const char *)username);
+	auth_request->user = p_strdup(request->pool, (const char *)username);
 	if (!mech_fix_username(auth_request->user, &error)) {
 		if (verbose) {
 			i_info("apop(%s): %s",
 			       get_log_prefix(auth_request), error);
 		}
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 
-	memcpy(auth->digest, tmp, sizeof(auth->digest));
+	memcpy(request->digest, tmp, sizeof(request->digest));
 
 	passdb->lookup_credentials(auth_request, PASSDB_CREDENTIALS_PLAINTEXT,
 				   apop_credentials_callback);
-	return TRUE;
 }
 
-static void mech_apop_auth_free(struct auth_request *auth_request)
+static void mech_apop_auth_free(struct auth_request *request)
 {
-	pool_unref(auth_request->pool);
+	pool_unref(request->pool);
 }
 
 static struct auth_request *mech_apop_auth_new(void)
 {
-	struct apop_auth_request *auth;
+	struct apop_auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("apop_auth_request", 256);
-	auth = p_new(pool, struct apop_auth_request, 1);
-	auth->pool = pool;
-
-	auth->auth_request.refcount = 1;
-	auth->auth_request.pool = pool;
-	auth->auth_request.auth_initial = mech_apop_auth_initial;
-	auth->auth_request.auth_continue = NULL;
-	auth->auth_request.auth_free = mech_apop_auth_free;
+	request = p_new(pool, struct apop_auth_request, 1);
+	request->pool = pool;
 
-	return &auth->auth_request;
+	request->auth_request.refcount = 1;
+	request->auth_request.pool = pool;
+	return &request->auth_request;
 }
 
 const struct mech_module mech_apop = {
 	"APOP",
 
-	MEMBER(plaintext) FALSE,
-	MEMBER(advertise) FALSE,
+	MEMBER(flags) MECH_SEC_PRIVATE | MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
 
 	MEMBER(passdb_need_plain) FALSE,
 	MEMBER(passdb_need_credentials) TRUE,
 
 	mech_apop_auth_new,
+	mech_apop_auth_initial,
+	NULL,
+        mech_apop_auth_free
 };

Index: mech-cram-md5.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-cram-md5.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- mech-cram-md5.c	8 Oct 2004 17:51:47 -0000	1.12
+++ mech-cram-md5.c	13 Oct 2004 16:38:32 -0000	1.13
@@ -42,11 +42,11 @@
 		buf[i] = (buf[i] % 10) + '0';
 	buf[sizeof(buf)-1] = '\0';
 
-	return t_strdup_printf("<%s.%s@%s>", (const char *) buf,
+	return t_strdup_printf("<%s.%s@%s>", (const char *)buf,
 			       dec2str(ioloop_time), my_hostname);
 }
 
-static int verify_credentials(struct cram_auth_request *auth,
+static int verify_credentials(struct cram_auth_request *request,
 			      const char *credentials)
 {
 	
@@ -66,15 +66,15 @@
 		return FALSE;
 
 	hmac_md5_set_cram_context(&ctx, context_digest);
-	hmac_md5_update(&ctx, auth->challenge, strlen(auth->challenge));
+	hmac_md5_update(&ctx, request->challenge, strlen(request->challenge));
 	hmac_md5_final(&ctx, digest);
 
 	response_hex = binary_to_hex(digest, 16);
 
-	if (memcmp(response_hex, auth->response, 32) != 0) {
+	if (memcmp(response_hex, request->response, 32) != 0) {
 		if (verbose) {
 			i_info("cram-md5(%s): password mismatch",
-			       get_log_prefix(&auth->auth_request));
+			       get_log_prefix(&request->auth_request));
 		}
 		return FALSE;
 	}
@@ -82,7 +82,7 @@
 	return TRUE;
 }
 
-static int parse_cram_response(struct cram_auth_request *auth,
+static int parse_cram_response(struct cram_auth_request *request,
 			       const unsigned char *data, size_t size,
 			       const char **error_r)
 {
@@ -102,126 +102,106 @@
 		return FALSE;
 	}
 
-	auth->username = p_strndup(auth->pool, data, space);
+	request->username = p_strndup(request->pool, data, space);
 	space++;
-	auth->response = p_strndup(auth->pool, data + space, size - space);
+	request->response =
+		p_strndup(request->pool, data + space, size - space);
 	return TRUE;
 }
 
 static void credentials_callback(const char *result,
-				 struct auth_request *request)
+				 struct auth_request *auth_request)
 {
-	struct cram_auth_request *auth =
-		(struct cram_auth_request *) request;
+	struct cram_auth_request *request =
+		(struct cram_auth_request *)auth_request;
 
-	if (verify_credentials(auth, result))
-		mech_auth_finish(request, NULL, 0, TRUE);
+	if (verify_credentials(request, result))
+		mech_auth_finish(auth_request, NULL, 0, TRUE);
 	else {
 		if (verbose) {
 			i_info("cram-md5(%s): authentication failed",
-			       get_log_prefix(&auth->auth_request));
+			       get_log_prefix(auth_request));
 		}
-		mech_auth_finish(request, NULL, 0, FALSE);
+		mech_auth_finish(auth_request, NULL, 0, FALSE);
 	}
 }
 
-static int
+static void
 mech_cram_md5_auth_continue(struct auth_request *auth_request,
 			    const unsigned char *data, size_t data_size,
 			    mech_callback_t *callback)
 {
-	struct cram_auth_request *auth =
+	struct cram_auth_request *request =
 		(struct cram_auth_request *)auth_request;
 	const char *error;
 
-	if (parse_cram_response(auth, data, data_size, &error)) {
+	if (parse_cram_response(request, data, data_size, &error)) {
 		auth_request->callback = callback;
 
 		auth_request->user =
-			p_strdup(auth_request->pool, auth->username);
+			p_strdup(auth_request->pool, request->username);
 
 		if (mech_fix_username(auth_request->user, &error)) {
-			passdb->lookup_credentials(&auth->auth_request,
+			passdb->lookup_credentials(auth_request,
 						   PASSDB_CREDENTIALS_CRAM_MD5,
 						   credentials_callback);
-			return TRUE;
+			return;
 		}
 	}
 
 	if (error == NULL)
 		error = "authentication failed";
 
-	if (verbose) {
-		i_info("cram-md5(%s): %s",
-                       get_log_prefix(&auth->auth_request), error);
-	}
+	if (verbose)
+		i_info("cram-md5(%s): %s", get_log_prefix(auth_request), error);
 
 	/* failed */
 	mech_auth_finish(auth_request, NULL, 0, FALSE);
-	return FALSE;
 }
 
-static int
+static void
 mech_cram_md5_auth_initial(struct auth_request *auth_request,
-			   struct auth_client_request_new *request,
 			   const unsigned char *data __attr_unused__,
+			   size_t data_size __attr_unused__,
 			   mech_callback_t *callback)
 {
-	struct cram_auth_request *auth =
+	struct cram_auth_request *request =
 		(struct cram_auth_request *)auth_request;
 
-	struct auth_client_request_reply reply;
-
-	if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
-		/* No initial response in CRAM-MD5 */
-		return FALSE;
-	}
-
-	auth->challenge = p_strdup(auth->pool, get_cram_challenge());
-
-	/* initialize reply */
-	mech_init_auth_client_reply(&reply);
-	reply.id = request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	/* send the initial challenge */
-	reply.reply_idx = 0;
-	reply.data_size = strlen(auth->challenge);
-	callback(&reply, auth->challenge, auth_request->conn);
-	return TRUE;
+	request->challenge = p_strdup(request->pool, get_cram_challenge());
+	callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+		 request->challenge, strlen(request->challenge));
 }
 
-static void mech_cram_md5_auth_free(struct auth_request *auth_request)
+static void mech_cram_md5_auth_free(struct auth_request *request)
 {
-	pool_unref(auth_request->pool);
+	pool_unref(request->pool);
 }
 
 static struct auth_request *mech_cram_md5_auth_new(void)
 {
-	struct cram_auth_request *auth;
+	struct cram_auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("cram_md5_auth_request", 2048);
-	auth = p_new(pool, struct cram_auth_request, 1);
-	auth->pool = pool;
-
-	auth->auth_request.refcount = 1;
-	auth->auth_request.pool = pool;
-	auth->auth_request.auth_initial = mech_cram_md5_auth_initial;
-	auth->auth_request.auth_continue = mech_cram_md5_auth_continue;
-	auth->auth_request.auth_free = mech_cram_md5_auth_free;
+	request = p_new(pool, struct cram_auth_request, 1);
+	request->pool = pool;
 
-	return &auth->auth_request;
+	request->auth_request.refcount = 1;
+	request->auth_request.pool = pool;
+	return &request->auth_request;
 }
 
 struct mech_module mech_cram_md5 = {
 	"CRAM-MD5",
 
-	MEMBER(plaintext) FALSE,
-	MEMBER(advertise) TRUE,
+	MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
 
 	MEMBER(passdb_need_plain) FALSE,
 	MEMBER(passdb_need_credentials) TRUE,
 
-	mech_cram_md5_auth_new
+	mech_cram_md5_auth_new,
+	mech_cram_md5_auth_initial,
+	mech_cram_md5_auth_continue,
+        mech_cram_md5_auth_free
 };

Index: mech-digest-md5.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-digest-md5.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- mech-digest-md5.c	8 Oct 2004 17:51:47 -0000	1.25
+++ mech-digest-md5.c	13 Oct 2004 16:38:32 -0000	1.26
@@ -52,7 +52,7 @@
 	char *rspauth;
 };
 
-static string_t *get_digest_challenge(struct digest_auth_request *auth)
+static string_t *get_digest_challenge(struct digest_auth_request *request)
 {
 	buffer_t *buf;
 	string_t *str;
@@ -79,7 +79,7 @@
 
 	base64_encode(nonce, sizeof(nonce), buf);
 	buffer_append_c(buf, '\0');
-	auth->nonce = p_strdup(auth->pool, buffer_get_data(buf, NULL));
+	request->nonce = p_strdup(request->pool, buffer_get_data(buf, NULL));
 	t_pop();
 
 	str = t_str_new(256);
@@ -89,11 +89,11 @@
 		str_append_c(str, ',');
 	}
 
-	str_printfa(str, "nonce=\"%s\",", auth->nonce);
+	str_printfa(str, "nonce=\"%s\",", request->nonce);
 
 	str_append(str, "qop=\""); first_qop = TRUE;
 	for (i = 0; i < QOP_COUNT; i++) {
-		if (auth->qop & (1 << i)) {
+		if (request->qop & (1 << i)) {
 			if (first_qop)
 				first_qop = FALSE;
 			else
@@ -108,7 +108,7 @@
 	return str;
 }
 
-static int verify_credentials(struct digest_auth_request *auth,
+static int verify_credentials(struct digest_auth_request *request,
 			      const char *credentials)
 {
 	struct md5_context ctx;
@@ -151,9 +151,9 @@
 	md5_init(&ctx);
 	md5_update(&ctx, digest, 16);
 	md5_update(&ctx, ":", 1);
-	md5_update(&ctx, auth->nonce, strlen(auth->nonce));
+	md5_update(&ctx, request->nonce, strlen(request->nonce));
 	md5_update(&ctx, ":", 1);
-	md5_update(&ctx, auth->cnonce, strlen(auth->cnonce));
+	md5_update(&ctx, request->cnonce, strlen(request->cnonce));
 	md5_final(&ctx, digest);
 	a1_hex = binary_to_hex(digest, 16);
 
@@ -167,11 +167,12 @@
 		else
 			md5_update(&ctx, ":", 1);
 
-		if (auth->digest_uri != NULL) {
-			md5_update(&ctx, auth->digest_uri,
-				   strlen(auth->digest_uri));
+		if (request->digest_uri != NULL) {
+			md5_update(&ctx, request->digest_uri,
+				   strlen(request->digest_uri));
 		}
-		if (auth->qop == QOP_AUTH_INT || auth->qop == QOP_AUTH_CONF) {
+		if (request->qop == QOP_AUTH_INT ||
+		    request->qop == QOP_AUTH_CONF) {
 			md5_update(&ctx, ":00000000000000000000000000000000",
 				   33);
 		}
@@ -182,13 +183,15 @@
 		md5_init(&ctx);
 		md5_update(&ctx, a1_hex, 32);
 		md5_update(&ctx, ":", 1);
-		md5_update(&ctx, auth->nonce, strlen(auth->nonce));
+		md5_update(&ctx, request->nonce, strlen(request->nonce));
 		md5_update(&ctx, ":", 1);
-		md5_update(&ctx, auth->nonce_count, strlen(auth->nonce_count));
+		md5_update(&ctx, request->nonce_count,
+			   strlen(request->nonce_count));
 		md5_update(&ctx, ":", 1);
-		md5_update(&ctx, auth->cnonce, strlen(auth->cnonce));
+		md5_update(&ctx, request->cnonce, strlen(request->cnonce));
 		md5_update(&ctx, ":", 1);
-		md5_update(&ctx, auth->qop_value, strlen(auth->qop_value));
+		md5_update(&ctx, request->qop_value,
+			   strlen(request->qop_value));
 		md5_update(&ctx, ":", 1);
 		md5_update(&ctx, a2_hex, 32);
 		md5_final(&ctx, digest);
@@ -196,10 +199,10 @@
 
 		if (i == 0) {
 			/* verify response */
-			if (memcmp(response_hex, auth->response, 32) != 0) {
+			if (memcmp(response_hex, request->response, 32) != 0) {
 				if (verbose) {
 					struct auth_request *auth_request =
-						&auth->auth_request;
+						&request->auth_request;
 					i_info("digest-md5(%s): "
 					       "password mismatch",
 					       get_log_prefix(auth_request));
@@ -207,8 +210,9 @@
 				return FALSE;
 			}
 		} else {
-			auth->rspauth = p_strconcat(auth->pool, "rspauth=",
-						    response_hex, NULL);
+			request->rspauth =
+				p_strconcat(request->pool, "rspauth=",
+					    response_hex, NULL);
 		}
 	}
 
@@ -283,7 +287,7 @@
 	return TRUE;
 }
 
-static int auth_handle_response(struct digest_auth_request *auth,
+static int auth_handle_response(struct digest_auth_request *request,
 				char *key, char *value, const char **error)
 {
 	int i;
@@ -295,13 +299,13 @@
 			*error = "Invalid realm";
 			return FALSE;
 		}
-		if (auth->realm == NULL && *value != '\0')
-			auth->realm = p_strdup(auth->pool, value);
+		if (request->realm == NULL && *value != '\0')
+			request->realm = p_strdup(request->pool, value);
 		return TRUE;
 	}
 
 	if (strcmp(key, "username") == 0) {
-		if (auth->username != NULL) {
+		if (request->username != NULL) {
 			*error = "username must not exist more than once";
 			return FALSE;
 		}
@@ -311,23 +315,23 @@
 			return FALSE;
 		}
 
-		auth->username = p_strdup(auth->pool, value);
+		request->username = p_strdup(request->pool, value);
 		return TRUE;
 	}
 
 	if (strcmp(key, "nonce") == 0) {
 		/* nonce must be same */
-		if (strcmp(value, auth->nonce) != 0) {
+		if (strcmp(value, request->nonce) != 0) {
 			*error = "Invalid nonce";
 			return FALSE;
 		}
 
-		auth->nonce_found = TRUE;
+		request->nonce_found = TRUE;
 		return TRUE;
 	}
 
 	if (strcmp(key, "cnonce") == 0) {
-		if (auth->cnonce != NULL) {
+		if (request->cnonce != NULL) {
 			*error = "cnonce must not exist more than once";
 			return FALSE;
 		}
@@ -337,12 +341,12 @@
 			return FALSE;
 		}
 
-		auth->cnonce = p_strdup(auth->pool, value);
+		request->cnonce = p_strdup(request->pool, value);
 		return TRUE;
 	}
 
 	if (strcmp(key, "nonce-count") == 0) {
-		if (auth->nonce_count != NULL) {
+		if (request->nonce_count != NULL) {
 			*error = "nonce-count must not exist more than once";
 			return FALSE;
 		}
@@ -352,7 +356,7 @@
 			return FALSE;
 		}
 
-		auth->nonce_count = p_strdup(auth->pool, value);
+		request->nonce_count = p_strdup(request->pool, value);
 		return TRUE;
 	}
 
@@ -367,13 +371,13 @@
 			return FALSE;
 		}
 
-		auth->qop &= (1 << i);
-		if (auth->qop == 0) {
+		request->qop &= (1 << i);
+		if (request->qop == 0) {
 			*error = "Nonallowed QoP requested";
 			return FALSE;
 		} 
 
-		auth->qop_value = p_strdup(auth->pool, value);
+		request->qop_value = p_strdup(request->pool, value);
 		return TRUE;
 	}
 
@@ -390,18 +394,18 @@
 		   But isn't the realm enough already? That'd be just extra
 		   configuration.. Maybe optionally list valid hosts in
 		   config file? */
-		auth->digest_uri = p_strdup(auth->pool, value);
+		request->digest_uri = p_strdup(request->pool, value);
 		return TRUE;
 	}
 
 	if (strcmp(key, "maxbuf") == 0) {
-		if (auth->maxbuf != 0) {
+		if (request->maxbuf != 0) {
 			*error = "maxbuf must not exist more than once";
 			return FALSE;
 		}
 
-		auth->maxbuf = strtoul(value, NULL, 10);
-		if (auth->maxbuf == 0) {
+		request->maxbuf = strtoul(value, NULL, 10);
+		if (request->maxbuf == 0) {
 			*error = "Invalid maxbuf value";
 			return FALSE;
 		}
@@ -423,7 +427,7 @@
 			return FALSE;
 		}
 
-		memcpy(auth->response, value, 32);
+		memcpy(request->response, value, 32);
 		return TRUE;
 	}
 
@@ -441,7 +445,7 @@
 	return TRUE;
 }
 
-static int parse_digest_response(struct digest_auth_request *auth,
+static int parse_digest_response(struct digest_auth_request *request,
 				 const unsigned char *data, size_t size,
 				 const char **error)
 {
@@ -471,7 +475,7 @@
 	copy = t_strdup_noconst(t_strndup(data, size));
 	while (*copy != '\0') {
 		if (parse_next(&copy, &key, &value)) {
-			if (!auth_handle_response(auth, key, value, error)) {
+			if (!auth_handle_response(request, key, value, error)) {
 				failed = TRUE;
 				break;
 			}
@@ -482,22 +486,22 @@
 	}
 
 	if (!failed) {
-		if (!auth->nonce_found) {
+		if (!request->nonce_found) {
 			*error = "Missing nonce parameter";
 			failed = TRUE;
-		} else if (auth->cnonce == NULL) {
+		} else if (request->cnonce == NULL) {
 			*error = "Missing cnonce parameter";
 			failed = TRUE;
-		} else if (auth->username == NULL) {
+		} else if (request->username == NULL) {
 			*error = "Missing username parameter";
 			failed = TRUE;
 		}
 	}
 
-	if (auth->nonce_count == NULL)
-		auth->nonce_count = p_strdup(auth->pool, "00000001");
-	if (auth->qop_value == NULL)
-		auth->qop_value = p_strdup(auth->pool, "auth");
+	if (request->nonce_count == NULL)
+		request->nonce_count = p_strdup(request->pool, "00000001");
+	if (request->qop_value == NULL)
+		request->qop_value = p_strdup(request->pool, "auth");
 
 	t_pop();
 
@@ -505,148 +509,118 @@
 }
 
 static void credentials_callback(const char *result,
-				 struct auth_request *request)
+				 struct auth_request *auth_request)
 {
-	struct digest_auth_request *auth =
-		(struct digest_auth_request *) request;
-	struct auth_client_request_reply reply;
+	struct digest_auth_request *request =
+		(struct digest_auth_request *)auth_request;
 
-	if (!verify_credentials(auth, result)) {
-		mech_auth_finish(request, NULL, 0, FALSE);
+	if (!verify_credentials(request, result)) {
+		mech_auth_finish(auth_request, NULL, 0, FALSE);
 		return;
 	}
 
-	mech_init_auth_client_reply(&reply);
-	reply.id = request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-	reply.data_size = strlen(auth->rspauth);
-	auth->authenticated = TRUE;
-
-	request->callback(&reply, auth->rspauth, request->conn);
+	auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+			       request->rspauth, strlen(request->rspauth));
 }
 
-static int
+static void
 mech_digest_md5_auth_continue(struct auth_request *auth_request,
 			      const unsigned char *data, size_t data_size,
 			      mech_callback_t *callback)
 {
-	struct digest_auth_request *auth =
+	struct digest_auth_request *request =
 		(struct digest_auth_request *)auth_request;
-	struct auth_client_request_reply reply;
 	const char *error, *realm;
 
-	/* initialize reply */
-	mech_init_auth_client_reply(&reply);
-	reply.id = auth_request->id;
-
-	if (auth->authenticated) {
+	if (request->authenticated) {
 		/* authentication is done, we were just waiting the last
 		   word from client */
 		mech_auth_finish(auth_request, NULL, 0, TRUE);
-		return TRUE;
+		return;
 	}
 
-	if (parse_digest_response(auth, data, data_size, &error)) {
+	if (parse_digest_response(request, data, data_size, &error)) {
 		auth_request->callback = callback;
 
-		realm = auth->realm != NULL ? auth->realm : default_realm;
+		realm = request->realm != NULL ? request->realm : default_realm;
 		if (realm == NULL) {
 			auth_request->user = p_strdup(auth_request->pool,
-						      auth->username);
+						      request->username);
 		} else {
 			auth_request->user = p_strconcat(auth_request->pool,
-							 auth->username, "@",
+							 request->username, "@",
 							 realm, NULL);
 		}
 
 		if (mech_fix_username(auth_request->user, &error)) {
-			passdb->lookup_credentials(&auth->auth_request,
+			passdb->lookup_credentials(auth_request,
 						PASSDB_CREDENTIALS_DIGEST_MD5,
 						credentials_callback);
-			return TRUE;
+			return;
 		}
 	}
 
-	if (error == NULL)
-                error = "Authentication failed";
-	else if (verbose) {
+	if (verbose && error != NULL) {
 		i_info("digest-md5(%s): %s",
 		       get_log_prefix(auth_request), error);
 	}
 
-	/* failed */
-	reply.result = AUTH_CLIENT_RESULT_FAILURE;
-	reply.data_size = strlen(error)+1;
-	callback(&reply, error, auth_request->conn);
-	return FALSE;
+	mech_auth_finish(auth_request, NULL, 0, FALSE);
 }
 
-static int
+static void
 mech_digest_md5_auth_initial(struct auth_request *auth_request,
-			     struct auth_client_request_new *request,
-			     const unsigned char *data __attr_unused__,
+			     const unsigned char *data, size_t data_size,
 			     mech_callback_t *callback)
 {
-	struct digest_auth_request *auth =
+	struct digest_auth_request *request =
 		(struct digest_auth_request *)auth_request;
-	struct auth_client_request_reply reply;
 	string_t *challenge;
-	size_t data_size;
 
-	if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
+	if (data_size > 0) {
 		/* FIXME: support subsequent authentication? */
-		data += request->initial_resp_idx;
-		data_size = request->data_size - request->initial_resp_idx;
-
-		return auth_request->auth_continue(auth_request, data,
-						   data_size, callback);
+		mech_digest_md5_auth_continue(auth_request, data, data_size,
+					      callback);
+		return;
 	}
 
-	/* initialize reply */
-	mech_init_auth_client_reply(&reply);
-	reply.id = request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	/* send the initial challenge */
-	reply.reply_idx = 0;
-	challenge = get_digest_challenge(auth);
-	reply.data_size = str_len(challenge);
-	callback(&reply, str_data(challenge), auth_request->conn);
-	return TRUE;
+	challenge = get_digest_challenge(request);
+	callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+		 str_data(challenge), str_len(challenge));
 }
 
-static void mech_digest_md5_auth_free(struct auth_request *auth_request)
+static void mech_digest_md5_auth_free(struct auth_request *request)
 {
-	pool_unref(auth_request->pool);
+	pool_unref(request->pool);
 }
 
 static struct auth_request *
 mech_digest_md5_auth_new(void)
 {
-	struct digest_auth_request *auth;
+	struct digest_auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("digest_md5_auth_request", 2048);
-	auth = p_new(pool, struct digest_auth_request, 1);
-	auth->pool = pool;
+	request = p_new(pool, struct digest_auth_request, 1);
+	request->pool = pool;
 
-	auth->auth_request.refcount = 1;
-	auth->auth_request.pool = pool;
-	auth->auth_request.auth_initial = mech_digest_md5_auth_initial;
-	auth->auth_request.auth_continue = mech_digest_md5_auth_continue;
-	auth->auth_request.auth_free = mech_digest_md5_auth_free;
-	auth->qop = QOP_AUTH;
-	return &auth->auth_request;
+	request->auth_request.refcount = 1;
+	request->auth_request.pool = pool;
+	request->qop = QOP_AUTH;
+	return &request->auth_request;
 }
 
 struct mech_module mech_digest_md5 = {
 	"DIGEST-MD5",
 
-	MEMBER(plaintext) FALSE,
-	MEMBER(advertise) TRUE,
+	MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE |
+		MECH_SEC_MUTUAL_AUTH,
 
 	MEMBER(passdb_need_plain) FALSE,
 	MEMBER(passdb_need_credentials) TRUE,
 
-	mech_digest_md5_auth_new
+	mech_digest_md5_auth_new,
+	mech_digest_md5_auth_initial,
+	mech_digest_md5_auth_continue,
+        mech_digest_md5_auth_free
 };

Index: mech-login.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-login.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- mech-login.c	31 Aug 2004 09:31:18 -0000	1.3
+++ mech-login.c	13 Oct 2004 16:38:32 -0000	1.4
@@ -20,98 +20,77 @@
 	mech_auth_finish(request, NULL, 0, result == PASSDB_RESULT_OK);
 }
 
-static int
-mech_login_auth_continue(struct auth_request *auth_request,
+static void
+mech_login_auth_continue(struct auth_request *request,
 			 const unsigned char *data, size_t data_size,
 			 mech_callback_t *callback)
 {
-	struct auth_client_request_reply reply;
 	static const char prompt2[] = "Password:";
 	const char *error;
 
-	auth_request->callback = callback;
+	request->callback = callback;
 
-	if (!auth_request->user) {
-		auth_request->user =
-			p_strndup(auth_request->pool, data, data_size);
+	if (request->user == NULL) {
+		request->user = p_strndup(request->pool, data, data_size);
 
-		if (!mech_fix_username(auth_request->user, &error)) {
+		if (!mech_fix_username(request->user, &error)) {
 			if (verbose) {
 				i_info("login(%s): %s",
-				       get_log_prefix(auth_request), error);
+				       get_log_prefix(request), error);
 			}
-			mech_auth_finish(auth_request, NULL, 0, FALSE);
-			return TRUE;
+			mech_auth_finish(request, NULL, 0, FALSE);
+			return;
 		}
 
-		mech_init_auth_client_reply(&reply);
-		reply.id = auth_request->id;
-		reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-		reply.reply_idx = 0;
-		reply.data_size = strlen(prompt2);
-		callback(&reply, prompt2, auth_request->conn);
+		callback(request, AUTH_CLIENT_RESULT_CONTINUE,
+			 prompt2, strlen(prompt2));
 	} else {
 		char *pass = p_strndup(unsafe_data_stack_pool, data, data_size);
-
-		passdb->verify_plain(auth_request, pass, verify_callback);
-
+		passdb->verify_plain(request, pass, verify_callback);
 		safe_memset(pass, 0, strlen(pass));
 	}
-
-	return TRUE;
 }
 
-static int
-mech_login_auth_initial(struct auth_request *auth_request,
-		       struct auth_client_request_new *request,
-		       const unsigned char *data __attr_unused__,
-		       mech_callback_t *callback)
+static void
+mech_login_auth_initial(struct auth_request *request,
+			const unsigned char *data __attr_unused__,
+			size_t data_size __attr_unused__,
+			mech_callback_t *callback)
 {
-	struct auth_client_request_reply reply;
 	static const char prompt1[] = "Username:";
 
-	mech_init_auth_client_reply(&reply);
-	reply.id = request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	reply.reply_idx = 0;
-	reply.data_size = strlen(prompt1);
-	callback(&reply, prompt1, auth_request->conn);
-
-	return TRUE;
+	callback(request, AUTH_CLIENT_RESULT_CONTINUE,
+		 prompt1, strlen(prompt1));
 }
 
-static void mech_login_auth_free(struct auth_request *auth_request)
+static void mech_login_auth_free(struct auth_request *request)
 {
-	pool_unref(auth_request->pool);
+	pool_unref(request->pool);
 }
 
 static struct auth_request *mech_login_auth_new(void)
 {
-	struct auth_request *auth;
+	struct auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("login_auth_request", 256);
-	auth = p_new(pool, struct auth_request, 1);
-
-	auth->refcount = 1;
-	auth->pool = pool;
-	auth->auth_initial = mech_login_auth_initial;
-	auth->auth_continue = mech_login_auth_continue;
-	auth->auth_free = mech_login_auth_free;
+	request = p_new(pool, struct auth_request, 1);
 
-	return auth;
+	request->refcount = 1;
+	request->pool = pool;
+	return request;
 }
 
 const struct mech_module mech_login = {
 	"LOGIN",
 
-	MEMBER(plaintext) TRUE,
-	MEMBER(advertise) TRUE,
+	MEMBER(flags) MECH_SEC_PLAINTEXT,
 
 	MEMBER(passdb_need_plain) TRUE,
 	MEMBER(passdb_need_credentials) FALSE,
 
 	mech_login_auth_new,
+	mech_login_auth_initial,
+	mech_login_auth_continue,
+        mech_login_auth_free
 };

Index: mech-ntlm.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-ntlm.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- mech-ntlm.c	7 Oct 2004 19:37:27 -0000	1.6
+++ mech-ntlm.c	13 Oct 2004 16:38:32 -0000	1.7
@@ -36,7 +36,7 @@
 lm_credentials_callback(const char *credentials,
 			struct auth_request *auth_request)
 {
-	struct ntlm_auth_request *auth =
+	struct ntlm_auth_request *request =
 		(struct ntlm_auth_request *)auth_request;
 	const unsigned char *client_response;
 	unsigned char lm_response[LM_RESPONSE_SIZE];
@@ -53,9 +53,9 @@
 					 hash, sizeof(hash));
 	hex_to_binary(credentials, hash_buffer);
 
-	client_response = ntlmssp_buffer_data(auth->response, lm_response);
+	client_response = ntlmssp_buffer_data(request->response, lm_response);
 
-	ntlmssp_v1_response(hash, auth->challenge, lm_response);
+	ntlmssp_v1_response(hash, request->challenge, lm_response);
 
 	ret = memcmp(lm_response, client_response, LM_RESPONSE_SIZE) == 0;
 
@@ -66,7 +66,7 @@
 ntlm_credentials_callback(const char *credentials,
 			  struct auth_request *auth_request)
 {
-	struct ntlm_auth_request *auth =
+	struct ntlm_auth_request *request =
 		(struct ntlm_auth_request *)auth_request;
 	const unsigned char *client_response;
 	unsigned char hash[NTLMSSP_HASH_SIZE];
@@ -74,7 +74,7 @@
 	buffer_t *hash_buffer;
 	int ret;
 
-	if (credentials == NULL && !auth->ntlm2_negotiated) {
+	if (credentials == NULL && !request->ntlm2_negotiated) {
 		passdb->lookup_credentials(auth_request,
 					   PASSDB_CREDENTIALS_LANMAN,
 					   lm_credentials_callback);
@@ -85,8 +85,9 @@
 					 hash, sizeof(hash));
 	hex_to_binary(credentials, hash_buffer);
 
-	response_length = ntlmssp_buffer_length(auth->response, ntlm_response);
-	client_response = ntlmssp_buffer_data(auth->response, ntlm_response);
+	response_length =
+		ntlmssp_buffer_length(request->response, ntlm_response);
+	client_response = ntlmssp_buffer_data(request->response, ntlm_response);
 
 	if (response_length > NTLMSSP_RESPONSE_SIZE) {
 		unsigned char ntlm_v2_response[NTLMSSP_V2_RESPONSE_SIZE];
@@ -98,7 +99,7 @@
 		 * as a standalone server, not as NT domain member.
 		 */
 		ntlmssp_v2_response(auth_request->user, NULL,
-				    hash, auth->challenge, blob,
+				    hash, request->challenge, blob,
 				    response_length - NTLMSSP_V2_RESPONSE_SIZE,
 				    ntlm_v2_response);
 
@@ -107,14 +108,14 @@
 	} else {
 		unsigned char ntlm_response[NTLMSSP_RESPONSE_SIZE];
 		const unsigned char *client_lm_response =
-			ntlmssp_buffer_data(auth->response, lm_response);
+			ntlmssp_buffer_data(request->response, lm_response);
 
-		if (auth->ntlm2_negotiated)
-			ntlmssp2_response(hash, auth->challenge,
+		if (request->ntlm2_negotiated)
+			ntlmssp2_response(hash, request->challenge,
 					  client_lm_response,
 					  ntlm_response);
 		else 
-			ntlmssp_v1_response(hash, auth->challenge,
+			ntlmssp_v1_response(hash, request->challenge,
 					    ntlm_response);
 
 		ret = memcmp(ntlm_response, client_response,
@@ -124,47 +125,42 @@
 	mech_auth_finish(auth_request, NULL, 0, ret);
 }
 
-static int
+static void
 mech_ntlm_auth_continue(struct auth_request *auth_request,
 			const unsigned char *data, size_t data_size,
 			mech_callback_t *callback)
 {
-	struct ntlm_auth_request *auth =
+	struct ntlm_auth_request *request =
 		(struct ntlm_auth_request *)auth_request;
-	struct auth_client_request_reply reply;
 	const char *error;
 
 	auth_request->callback = callback;
 
-	if (!auth->challenge) {
-		const struct ntlmssp_request *request =
+	if (!request->challenge) {
+		const struct ntlmssp_request *ntlm_request =
 			(struct ntlmssp_request *)data;
 		const struct ntlmssp_challenge *message;
 		size_t message_size;
 
-		if (!ntlmssp_check_request(request, data_size, &error)) {
+		if (!ntlmssp_check_request(ntlm_request, data_size, &error)) {
 			if (verbose) {
 				i_info("ntlm(%s): invalid NTLM request, %s",
 				       get_log_prefix(auth_request),
 				       error);
 			}
 			mech_auth_finish(auth_request, NULL, 0, FALSE);
-			return TRUE;
+			return;
 		}
 
-		message = ntlmssp_create_challenge(auth->pool, request,
+		message = ntlmssp_create_challenge(request->pool, ntlm_request,
 						   &message_size);
-		auth->ntlm2_negotiated =
+		request->ntlm2_negotiated =
 			read_le32(&message->flags) & NTLMSSP_NEGOTIATE_NTLM2;
-		auth->challenge = message->challenge;
-
-		mech_init_auth_client_reply(&reply);
-		reply.id = auth_request->id;
-		reply.result = AUTH_CLIENT_RESULT_CONTINUE;
+		request->challenge = message->challenge;
 
-		reply.reply_idx = 0;
-		reply.data_size = message_size;
-		callback(&reply, message, auth_request->conn);
+		auth_request->callback(auth_request,
+				       AUTH_CLIENT_RESULT_CONTINUE,
+				       message, message_size);
 	} else {
 		const struct ntlmssp_response *response =
 			(struct ntlmssp_response *)data;
@@ -177,14 +173,14 @@
 				       error);
 			}
 			mech_auth_finish(auth_request, NULL, 0, FALSE);
-			return TRUE;
+			return;
 		}
 
-		auth->response = p_malloc(auth->pool, data_size);
-		memcpy(auth->response, response, data_size);
+		request->response = p_malloc(request->pool, data_size);
+		memcpy(request->response, response, data_size);
 
 		username = p_strdup(auth_request->pool,
-				    ntlmssp_t_str(auth->response, user));
+				    ntlmssp_t_str(request->response, user));
 
 		if (!mech_fix_username(username, &error)) {
 			if (verbose) {
@@ -192,70 +188,55 @@
 				       get_log_prefix(auth_request), error);
 			}
 			mech_auth_finish(auth_request, NULL, 0, FALSE);
-			return TRUE;
+			return;
 		}
 
 		auth_request->user = username;
-
 		passdb->lookup_credentials(auth_request,
 					   PASSDB_CREDENTIALS_NTLM,
 					   ntlm_credentials_callback);
 	}
-
-	return TRUE;
 }
 
-static int
+static void
 mech_ntlm_auth_initial(struct auth_request *auth_request,
-		       struct auth_client_request_new *request,
 		       const unsigned char *data __attr_unused__,
+		       size_t data_size __attr_unused__,
 		       mech_callback_t *callback)
 {
-	struct auth_client_request_reply reply;
-
-	mech_init_auth_client_reply(&reply);
-	reply.id = request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	reply.reply_idx = 0;
-	reply.data_size = 0;
-	callback(&reply, "", auth_request->conn);
-
-	return TRUE;
+	callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
 }
 
 static void
-mech_ntlm_auth_free(struct auth_request *auth_request)
+mech_ntlm_auth_free(struct auth_request *request)
 {
-	pool_unref(auth_request->pool);
+	pool_unref(request->pool);
 }
 
 static struct auth_request *mech_ntlm_auth_new(void)
 {
-	struct ntlm_auth_request *auth;
+	struct ntlm_auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("ntlm_auth_request", 256);
-	auth = p_new(pool, struct ntlm_auth_request, 1);
-	auth->pool = pool;
-
-	auth->auth_request.refcount = 1;
-	auth->auth_request.pool = pool;
-	auth->auth_request.auth_initial = mech_ntlm_auth_initial;
-	auth->auth_request.auth_continue = mech_ntlm_auth_continue;
-	auth->auth_request.auth_free = mech_ntlm_auth_free;
+	request = p_new(pool, struct ntlm_auth_request, 1);
+	request->pool = pool;
 
-	return &auth->auth_request;
+	request->auth_request.refcount = 1;
+	request->auth_request.pool = pool;
+	return &request->auth_request;
 }
 
 const struct mech_module mech_ntlm = {
 	"NTLM",
 
-	MEMBER(plaintext) FALSE,
-	MEMBER(advertise) TRUE,
+	MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
 
 	MEMBER(passdb_need_plain) FALSE,
 	MEMBER(passdb_need_credentials) TRUE,
 
 	mech_ntlm_auth_new,
+	mech_ntlm_auth_initial,
+	mech_ntlm_auth_continue,
+	mech_ntlm_auth_free
 };

Index: mech-plain.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-plain.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- mech-plain.c	31 Aug 2004 09:31:18 -0000	1.21
+++ mech-plain.c	13 Oct 2004 16:38:32 -0000	1.22
@@ -11,8 +11,8 @@
 	mech_auth_finish(request, NULL, 0, result == PASSDB_RESULT_OK);
 }
 
-static int
-mech_plain_auth_continue(struct auth_request *auth_request,
+static void
+mech_plain_auth_continue(struct auth_request *request,
 			 const unsigned char *data, size_t data_size,
 			 mech_callback_t *callback)
 {
@@ -20,7 +20,7 @@
 	char *pass;
 	size_t i, count, len;
 
-	auth_request->callback = callback;
+	request->callback = callback;
 
 	/* authorization ID \0 authentication ID \0 pass.
 	   we'll ignore authorization ID for now. */
@@ -46,93 +46,74 @@
 		/* invalid input */
 		if (verbose) {
 			i_info("plain(%s): invalid input",
-			       get_log_prefix(auth_request));
+			       get_log_prefix(request));
 		}
-		mech_auth_finish(auth_request, NULL, 0, FALSE);
+		mech_auth_finish(request, NULL, 0, FALSE);
 	} else {
 		/* split and save user/realm */
 		if (strchr(authenid, '@') == NULL && default_realm != NULL) {
-			auth_request->user = p_strconcat(auth_request->pool,
-							 authenid, "@",
-							 default_realm, NULL);
+			request->user = p_strconcat(request->pool,
+						    authenid, "@",
+						    default_realm, NULL);
 		} else {
-			auth_request->user = p_strdup(auth_request->pool,
-						      authenid);
+			request->user = p_strdup(request->pool, authenid);
 		}
 
-		if (!mech_fix_username(auth_request->user, &error)) {
+		if (!mech_fix_username(request->user, &error)) {
 			/* invalid username */
 			if (verbose) {
 				i_info("plain(%s): %s",
-				       get_log_prefix(auth_request), error);
+				       get_log_prefix(request), error);
 			}
-			mech_auth_finish(auth_request, NULL, 0, FALSE);
+			mech_auth_finish(request, NULL, 0, FALSE);
 		} else {
-			passdb->verify_plain(auth_request, pass,
-					     verify_callback);
+			passdb->verify_plain(request, pass, verify_callback);
 		}
 
 		/* make sure it's cleared */
 		safe_memset(pass, 0, strlen(pass));
 	}
-	return TRUE;
 }
 
-static int
-mech_plain_auth_initial(struct auth_request *auth_request,
-			struct auth_client_request_new *request,
-			const unsigned char *data,
+static void
+mech_plain_auth_initial(struct auth_request *request,
+			const unsigned char *data, size_t data_size,
 			mech_callback_t *callback)
 {
-	struct auth_client_request_reply reply;
-	size_t data_size;
-
-	if (AUTH_CLIENT_REQUEST_HAVE_INITIAL_RESPONSE(request)) {
-		data += request->initial_resp_idx;
-		data_size = request->data_size - request->initial_resp_idx;
-
-		return auth_request->auth_continue(auth_request, data,
-						   data_size, callback);
-	}
-
-	/* initialize reply */
-	memset(&reply, 0, sizeof(reply));
-	reply.id = request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	callback(&reply, NULL, auth_request->conn);
-	return TRUE;
+	if (data_size == 0)
+		callback(request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
+	else
+		mech_plain_auth_continue(request, data, data_size, callback);
 }
 
 static void
-mech_plain_auth_free(struct auth_request *auth_request)
+mech_plain_auth_free(struct auth_request *request)
 {
-	pool_unref(auth_request->pool);
+	pool_unref(request->pool);
 }
 
 static struct auth_request *mech_plain_auth_new(void)
 {
-        struct auth_request *auth_request;
+        struct auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("plain_auth_request", 256);
-	auth_request = p_new(pool, struct auth_request, 1);
-	auth_request->refcount = 1;
-	auth_request->pool = pool;
-	auth_request->auth_initial = mech_plain_auth_initial;
-	auth_request->auth_continue = mech_plain_auth_continue;
-        auth_request->auth_free = mech_plain_auth_free;
-	return auth_request;
+	request = p_new(pool, struct auth_request, 1);
+	request->refcount = 1;
+	request->pool = pool;
+	return request;
 }
 
 struct mech_module mech_plain = {
 	"PLAIN",
 
-	MEMBER(plaintext) TRUE,
-	MEMBER(advertise) FALSE,
+	MEMBER(flags) MECH_SEC_PLAINTEXT,
 
 	MEMBER(passdb_need_plain) TRUE,
 	MEMBER(passdb_need_credentials) FALSE,
 
-	mech_plain_auth_new
+	mech_plain_auth_new,
+	mech_plain_auth_initial,
+	mech_plain_auth_continue,
+        mech_plain_auth_free
 };

Index: mech-rpa.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech-rpa.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mech-rpa.c	8 Oct 2004 17:51:47 -0000	1.5
+++ mech-rpa.c	13 Oct 2004 16:38:32 -0000	1.6
@@ -64,7 +64,7 @@
 /*
  * Compute client -> server authentication response.
  */
-static void rpa_user_response(struct rpa_auth_request *auth,
+static void rpa_user_response(struct rpa_auth_request *request,
 			      unsigned char *digest)
 {
 	struct md5_context ctx;
@@ -73,22 +73,22 @@
 	memset(z, 0, sizeof(z));
 
 	md5_init(&ctx);
-	md5_update(&ctx, auth->pwd_md5, 16);
+	md5_update(&ctx, request->pwd_md5, 16);
 	md5_update(&ctx, z, sizeof(z));
-	md5_update(&ctx, auth->username_ucs2be, auth->username_len);
-	md5_update(&ctx, auth->service_ucs2be, auth->service_len);
-	md5_update(&ctx, auth->realm_ucs2be, auth->realm_len);
-	md5_update(&ctx, auth->user_challenge, auth->user_challenge_len);
-	md5_update(&ctx, auth->service_challenge, RPA_SCHALLENGE_LEN);
-	md5_update(&ctx, auth->service_timestamp, RPA_TIMESTAMP_LEN);
-	md5_update(&ctx, auth->pwd_md5, 16);
+	md5_update(&ctx, request->username_ucs2be, request->username_len);
+	md5_update(&ctx, request->service_ucs2be, request->service_len);
+	md5_update(&ctx, request->realm_ucs2be, request->realm_len);
+	md5_update(&ctx, request->user_challenge, request->user_challenge_len);
+	md5_update(&ctx, request->service_challenge, RPA_SCHALLENGE_LEN);
+	md5_update(&ctx, request->service_timestamp, RPA_TIMESTAMP_LEN);
+	md5_update(&ctx, request->pwd_md5, 16);
 	md5_final(&ctx, digest);
 }
 
 /*
  * Compute server -> client authentication response.
  */
-static void rpa_server_response(struct rpa_auth_request *auth,
+static void rpa_server_response(struct rpa_auth_request *request,
 				unsigned char *digest)
 {
 	struct md5_context ctx;
@@ -99,32 +99,32 @@
 	memset(z, 0, sizeof(z));
 
 	md5_init(&ctx);
-	md5_update(&ctx, auth->pwd_md5, 16);
+	md5_update(&ctx, request->pwd_md5, 16);
 	md5_update(&ctx, z, sizeof(z));
-	md5_update(&ctx, auth->service_ucs2be, auth->service_len);
-	md5_update(&ctx, auth->username_ucs2be, auth->username_len);
-	md5_update(&ctx, auth->realm_ucs2be, auth->realm_len);
-	md5_update(&ctx, auth->service_challenge, RPA_SCHALLENGE_LEN);
-	md5_update(&ctx, auth->user_challenge, auth->user_challenge_len);
-	md5_update(&ctx, auth->service_timestamp, RPA_TIMESTAMP_LEN);
-	md5_update(&ctx, auth->pwd_md5, 16);
+	md5_update(&ctx, request->service_ucs2be, request->service_len);
+	md5_update(&ctx, request->username_ucs2be, request->username_len);
+	md5_update(&ctx, request->realm_ucs2be, request->realm_len);
+	md5_update(&ctx, request->service_challenge, RPA_SCHALLENGE_LEN);
+	md5_update(&ctx, request->user_challenge, request->user_challenge_len);
+	md5_update(&ctx, request->service_timestamp, RPA_TIMESTAMP_LEN);
+	md5_update(&ctx, request->pwd_md5, 16);
 	md5_final(&ctx, tmp);
 
 	for (i = 0; i < 16; i++)
-		tmp[i] = auth->session_key[i] ^ tmp[i];
+		tmp[i] = request->session_key[i] ^ tmp[i];
 
 	md5_init(&ctx);
-	md5_update(&ctx, auth->pwd_md5, 16);
+	md5_update(&ctx, request->pwd_md5, 16);
 	md5_update(&ctx, z, sizeof(z));
-	md5_update(&ctx, auth->service_ucs2be, auth->service_len);
-	md5_update(&ctx, auth->username_ucs2be, auth->username_len);
-	md5_update(&ctx, auth->realm_ucs2be, auth->realm_len);
-	md5_update(&ctx, auth->session_key, 16);
-	md5_update(&ctx, auth->service_challenge, RPA_SCHALLENGE_LEN);
-	md5_update(&ctx, auth->user_challenge, auth->user_challenge_len);
-	md5_update(&ctx, auth->service_timestamp, RPA_TIMESTAMP_LEN);
+	md5_update(&ctx, request->service_ucs2be, request->service_len);
+	md5_update(&ctx, request->username_ucs2be, request->username_len);
+	md5_update(&ctx, request->realm_ucs2be, request->realm_len);
+	md5_update(&ctx, request->session_key, 16);
+	md5_update(&ctx, request->service_challenge, RPA_SCHALLENGE_LEN);
+	md5_update(&ctx, request->user_challenge, request->user_challenge_len);
+	md5_update(&ctx, request->service_timestamp, RPA_TIMESTAMP_LEN);
 	md5_update(&ctx, tmp, 16);
-	md5_update(&ctx, auth->pwd_md5, 16);
+	md5_update(&ctx, request->pwd_md5, 16);
 	md5_final(&ctx, digest);
 }
 
@@ -248,10 +248,10 @@
 }
 
 static int
-rpa_parse_token3(struct rpa_auth_request *auth, const void *data,
+rpa_parse_token3(struct rpa_auth_request *request, const void *data,
 		 size_t data_size, const char **error)
 {
-	struct auth_request *auth_request = (struct auth_request *)auth;
+	struct auth_request *auth_request = &request->auth_request;
 	const unsigned char *end = ((unsigned char *)data) + data_size;
 	const unsigned char *p;
 	unsigned int len;
@@ -277,21 +277,21 @@
 	user = t_strndup(p, len);
 	p += len;
 
-	auth_request->user = rpa_parse_username(auth->pool, user);
+	auth_request->user = rpa_parse_username(request->pool, user);
 
-	auth->username_ucs2be = ucs2be_str(auth->pool, auth_request->user,
-					   &auth->username_len);
+	request->username_ucs2be = ucs2be_str(request->pool, auth_request->user,
+					      &request->username_len);
 
 	/* Read user challenge */
-	auth->user_challenge_len = rpa_read_buffer(auth->pool, &p, end,
-						   &auth->user_challenge);
-	if (auth->user_challenge_len == 0) {
+	request->user_challenge_len = rpa_read_buffer(request->pool, &p, end,
+						      &request->user_challenge);
+	if (request->user_challenge_len == 0) {
 		*error = "invalid user challenge";
 		return FALSE;
 	}
 
 	/* Read user response */
-	len = rpa_read_buffer(auth->pool, &p, end, &auth->user_response);
+	len = rpa_read_buffer(request->pool, &p, end, &request->user_response);
 	if (len != RPA_UCHALLENGE_LEN) {
 		*error = "invalid user response";
 		return FALSE;
@@ -321,7 +321,7 @@
 }
 
 static const unsigned char *
-mech_rpa_build_token2(struct rpa_auth_request *auth,
+mech_rpa_build_token2(struct rpa_auth_request *request,
 		      const char *realms, size_t *size)
 {
 	unsigned int realms_len;
@@ -333,7 +333,7 @@
         length = sizeof(rpa_oid) + 3 + RPA_SCHALLENGE_LEN +
 		RPA_TIMESTAMP_LEN + 2 + realms_len;
 
-	buf = buffer_create_dynamic(auth->pool, length + 4);
+	buf = buffer_create_dynamic(request->pool, length + 4);
 
 	buffer_append_c(buf, ASN1_APPLICATION);
 	buffer_append_asn1_length(buf, length);
@@ -344,18 +344,19 @@
 	buffer_append_c(buf, 0);
 
 	/* Service challenge */
-	auth->service_challenge = p_malloc(auth->pool, RPA_SCHALLENGE_LEN);
-	random_fill(auth->service_challenge, RPA_SCHALLENGE_LEN);
+	request->service_challenge =
+		p_malloc(request->pool, RPA_SCHALLENGE_LEN);
+	random_fill(request->service_challenge, RPA_SCHALLENGE_LEN);
 	buffer_append_c(buf, RPA_SCHALLENGE_LEN);
-	buffer_append(buf, auth->service_challenge, RPA_SCHALLENGE_LEN);
+	buffer_append(buf, request->service_challenge, RPA_SCHALLENGE_LEN);
 
 	/* Timestamp, looks like clients accept anything we send */
 	random_fill(timestamp, sizeof(timestamp));
-	auth->service_timestamp = p_malloc(auth->pool, RPA_TIMESTAMP_LEN);
-	memcpy(auth->service_timestamp,
+	request->service_timestamp = p_malloc(request->pool, RPA_TIMESTAMP_LEN);
+	memcpy(request->service_timestamp,
 	       binary_to_hex(timestamp, sizeof(timestamp)),
 	       RPA_TIMESTAMP_LEN);
-	buffer_append(buf, auth->service_timestamp, RPA_TIMESTAMP_LEN);
+	buffer_append(buf, request->service_timestamp, RPA_TIMESTAMP_LEN);
 
 	/* Realm list */
 	buffer_append_c(buf, realms_len >> 8);
@@ -367,29 +368,29 @@
 }
 
 static const unsigned char *
-mech_rpa_build_token4(struct rpa_auth_request *auth, size_t *size)
+mech_rpa_build_token4(struct rpa_auth_request *request, size_t *size)
 {
 	unsigned int length = sizeof(rpa_oid) + 17 + 17 + 1;
 	buffer_t *buf;
 	unsigned char server_response[16];
 
-	buf = buffer_create_dynamic(auth->pool, length + 4);
+	buf = buffer_create_dynamic(request->pool, length + 4);
 
 	buffer_append_c(buf, ASN1_APPLICATION);
 	buffer_append_asn1_length(buf, length);
 	buffer_append(buf, rpa_oid, sizeof(rpa_oid));
 
 	/* Generate random session key */
-	auth->session_key = p_malloc(auth->pool, 16);
-	random_fill(auth->session_key, 16);
+	request->session_key = p_malloc(request->pool, 16);
+	random_fill(request->session_key, 16);
 
 	/* Server authentication response */
-	rpa_server_response(auth, server_response);
+	rpa_server_response(request, server_response);
 	buffer_append_c(buf, 16);
 	buffer_append(buf, server_response, 16);
 
 	buffer_append_c(buf, 16);
-	buffer_append(buf, auth->session_key, 16);
+	buffer_append(buf, request->session_key, 16);
 
 	/* Status, 0 - success */
 	buffer_append_c(buf, 0);
@@ -402,28 +403,24 @@
 rpa_credentials_callback(const char *credentials,
 			 struct auth_request *auth_request)
 {
-	struct rpa_auth_request *auth =
+	struct rpa_auth_request *request =
 		(struct rpa_auth_request *)auth_request;
 	buffer_t *hash_buffer;
 
 	if (credentials == NULL)
 		return;
 
-	auth->pwd_md5 = p_malloc(auth->pool, 16);
-
-	hash_buffer = buffer_create_data(auth->pool, auth->pwd_md5, 16);
-
+	request->pwd_md5 = p_malloc(request->pool, 16);
+	hash_buffer = buffer_create_data(request->pool, request->pwd_md5, 16);
 	hex_to_binary(credentials, hash_buffer);
 }
 
-static int
+static void
 mech_rpa_auth_phase1(struct auth_request *auth_request,
-		     const unsigned char *data, size_t data_size,
-		     mech_callback_t *callback)
+		     const unsigned char *data, size_t data_size)
 {
-	struct rpa_auth_request *auth =
+	struct rpa_auth_request *request =
 		(struct rpa_auth_request *)auth_request;
-	struct auth_client_request_reply reply;
 	const unsigned char *token2;
 	size_t token2_size;
 	const char *service, *error;
@@ -434,52 +431,42 @@
 			       get_log_prefix(auth_request), error);
 		}
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 
 	service = t_str_lcase(auth_request->protocol);
 
-	token2 = mech_rpa_build_token2(auth, t_strconcat(service, "@",
+	token2 = mech_rpa_build_token2(request, t_strconcat(service, "@",
 				       my_hostname, NULL), &token2_size);
 
-	auth->service_ucs2be = ucs2be_str(auth->pool, service,
-					  &auth->service_len);
-	auth->realm_ucs2be = ucs2be_str(auth->pool, my_hostname,
-					&auth->realm_len);
-
-	mech_init_auth_client_reply(&reply);
-	reply.id = auth_request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	reply.reply_idx = 0;
-	reply.data_size = token2_size;
-	callback(&reply, token2, auth_request->conn);
-
-	auth->phase = 1;
+	request->service_ucs2be = ucs2be_str(request->pool, service,
+					     &request->service_len);
+	request->realm_ucs2be = ucs2be_str(request->pool, my_hostname,
+					   &request->realm_len);
 
-	return TRUE;
+	auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+			       token2, token2_size);
+	request->phase = 1;
 }
 
-static int
+static void
 mech_rpa_auth_phase2(struct auth_request *auth_request,
-		     const unsigned char *data, size_t data_size,
-		     mech_callback_t *callback)
+		     const unsigned char *data, size_t data_size)
 {
-	struct rpa_auth_request *auth =
+	struct rpa_auth_request *request =
 		(struct rpa_auth_request *)auth_request;
-	struct auth_client_request_reply reply;
 	unsigned char response[16];
 	const unsigned char *token4;
 	const char *error;
 	size_t token4_size;
 
-	if (!rpa_parse_token3(auth, data, data_size, &error)) {
+	if (!rpa_parse_token3(request, data, data_size, &error)) {
 		if (verbose) {
 			i_info("rpa(%s): invalid token 3, %s",
 			       get_log_prefix(auth_request), error);
 		}
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 
 	if (!mech_fix_username(auth_request->user, &error)) {
@@ -488,41 +475,31 @@
 			       get_log_prefix(auth_request), error);
 		}
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 
 	passdb->lookup_credentials(auth_request, PASSDB_CREDENTIALS_RPA,
 				   rpa_credentials_callback);
-	if (auth->pwd_md5 == NULL) {
+	if (request->pwd_md5 == NULL) {
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 
-	rpa_user_response(auth, response);
-	if (memcmp(response, auth->user_response, 16) != 0) {
+	rpa_user_response(request, response);
+	if (memcmp(response, request->user_response, 16) != 0) {
 		mech_auth_finish(auth_request, NULL, 0, FALSE);
-		return TRUE;
+		return;
 	}
 
-	token4 = mech_rpa_build_token4(auth, &token4_size);
-
-	mech_init_auth_client_reply(&reply);
-	reply.id = auth_request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	reply.reply_idx = 0;
-	reply.data_size = token4_size;
-	callback(&reply, token4, auth_request->conn);
-
-	auth->phase = 2;
-
-	return TRUE;
+	token4 = mech_rpa_build_token4(request, &token4_size);
+	auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
+			       token4, token4_size);
+	request->phase = 2;
 }
 
-static int
+static void
 mech_rpa_auth_phase3(struct auth_request *auth_request,
-		     const unsigned char *data, size_t data_size,
-		     mech_callback_t *callback __attr_unused__)
+		     const unsigned char *data, size_t data_size)
 {
 	static const unsigned char client_ack[3] = { 0x60, 0x01, 0x00 };
 	int ret = TRUE;
@@ -537,90 +514,80 @@
 	}
 
 	mech_auth_finish(auth_request, NULL, 0, ret);
-	return TRUE;
 }
 
-static int
+static void
 mech_rpa_auth_continue(struct auth_request *auth_request,
-			const unsigned char *data, size_t data_size,
-			mech_callback_t *callback)
+		       const unsigned char *data, size_t data_size,
+		       mech_callback_t *callback)
 {
-	struct rpa_auth_request *auth =
+	struct rpa_auth_request *request =
 		(struct rpa_auth_request *)auth_request;
 
 	auth_request->callback = callback;
 
-	switch (auth->phase) {
-		case 0:	return mech_rpa_auth_phase1(auth_request, data,
-						    data_size, callback);
-		case 1:	return mech_rpa_auth_phase2(auth_request, data,
-						    data_size, callback);
-		case 2:	return mech_rpa_auth_phase3(auth_request, data,
-						    data_size, callback);
+	switch (request->phase) {
+	case 0:
+		mech_rpa_auth_phase1(auth_request, data, data_size);
+		break;
+	case 1:
+		mech_rpa_auth_phase2(auth_request, data, data_size);
+		break;
+	case 2:
+		mech_rpa_auth_phase3(auth_request, data, data_size);
+		break;
+	default:
+		mech_auth_finish(auth_request, NULL, 0, FALSE);
+		break;
 	}
-
-	mech_auth_finish(auth_request, NULL, 0, FALSE);
-	return TRUE;
 }
 
-static int
+static void
 mech_rpa_auth_initial(struct auth_request *auth_request,
-		      struct auth_client_request_new *request,
 		      const unsigned char *data __attr_unused__,
+		      size_t data_size __attr_unused__,
 		      mech_callback_t *callback)
 {
-	struct auth_client_request_reply reply;
-
-	mech_init_auth_client_reply(&reply);
-	reply.id = request->id;
-	reply.result = AUTH_CLIENT_RESULT_CONTINUE;
-
-	reply.reply_idx = 0;
-	reply.data_size = 0;
-	callback(&reply, "", auth_request->conn);
-
-	return TRUE;
+	callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE, NULL, 0);
 }
 
 static void
 mech_rpa_auth_free(struct auth_request *auth_request)
 {
-	struct rpa_auth_request *auth =
+	struct rpa_auth_request *request =
 		(struct rpa_auth_request *)auth_request;
 
-	if (auth->pwd_md5 != NULL)
-		safe_memset(auth->pwd_md5, 0, 16);
+	if (request->pwd_md5 != NULL)
+		safe_memset(request->pwd_md5, 0, 16);
 
 	pool_unref(auth_request->pool);
 }
 
 static struct auth_request *mech_rpa_auth_new(void)
 {
-	struct rpa_auth_request *auth;
+	struct rpa_auth_request *request;
 	pool_t pool;
 
 	pool = pool_alloconly_create("rpa_auth_request", 256);
-	auth = p_new(pool, struct rpa_auth_request, 1);
-	auth->pool = pool;
-	auth->phase = 0;
-
-	auth->auth_request.refcount = 1;
-	auth->auth_request.pool = pool;
-	auth->auth_request.auth_initial = mech_rpa_auth_initial;
-	auth->auth_request.auth_continue = mech_rpa_auth_continue;
-	auth->auth_request.auth_free = mech_rpa_auth_free;
+	request = p_new(pool, struct rpa_auth_request, 1);
+	request->pool = pool;
+	request->phase = 0;
 
-	return &auth->auth_request;
+	request->auth_request.refcount = 1;
+	request->auth_request.pool = pool;
+	return &request->auth_request;
 }
 
 const struct mech_module mech_rpa = {
 	"RPA",
 
-	MEMBER(plaintext) FALSE,
-	MEMBER(advertise) TRUE,
+	MEMBER(flags) MECH_SEC_DICTIONARY | MECH_SEC_ACTIVE,
 
 	MEMBER(passdb_need_plain) FALSE,
 	MEMBER(passdb_need_credentials) TRUE,
 
 	mech_rpa_auth_new,
+	mech_rpa_auth_initial,
+	mech_rpa_auth_continue,
+	mech_rpa_auth_free
 };

Index: mech.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech.c,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -d -r1.41 -r1.42
--- mech.c	10 Oct 2004 14:32:32 -0000	1.41
+++ mech.c	13 Oct 2004 16:38:32 -0000	1.42
@@ -14,14 +14,14 @@
 #include <stdlib.h>
 
 struct mech_module_list *mech_modules;
+buffer_t *mech_handshake;
+
 const char *const *auth_realms;
 const char *default_realm;
 const char *anonymous_username;
 char username_chars[256], username_translation[256];
 int ssl_require_client_cert;
 
-static struct auth_client_request_reply failure_reply;
-
 static buffer_t *auth_failures_buf;
 static struct timeout *to_auth_failures;
 
@@ -32,6 +32,23 @@
 	list = i_new(struct mech_module_list, 1);
 	list->module = *module;
 
+	str_printfa(mech_handshake, "MECH\t%s", module->mech_name);
+	if ((module->flags & MECH_SEC_PRIVATE) != 0)
+		str_append(mech_handshake, "\tprivate");
+	if ((module->flags & MECH_SEC_ANONYMOUS) != 0)
+		str_append(mech_handshake, "\tanonymous");
+	if ((module->flags & MECH_SEC_PLAINTEXT) != 0)
+		str_append(mech_handshake, "\tplaintext");
+	if ((module->flags & MECH_SEC_DICTIONARY) != 0)
+		str_append(mech_handshake, "\tdictionary");
+	if ((module->flags & MECH_SEC_ACTIVE) != 0)
+		str_append(mech_handshake, "\tactive");
+	if ((module->flags & MECH_SEC_FORWARD_SECRECY) != 0)
+		str_append(mech_handshake, "\tforward-secrecy");
+	if ((module->flags & MECH_SEC_MUTUAL_AUTH) != 0)
+		str_append(mech_handshake, "\tmutual-auth");
+	str_append_c(mech_handshake, '\n');
+
 	list->next = mech_modules;
 	mech_modules = list;
 }
@@ -62,7 +79,7 @@
 	return str;
 }
 
-static struct mech_module *mech_module_find(const char *name)
+struct mech_module *mech_module_find(const char *name)
 {
 	struct mech_module_list *list;
 
@@ -73,183 +90,48 @@
 	return NULL;
 }
 
-void mech_request_new(struct auth_client_connection *conn,
-		      struct auth_client_request_new *request,
-		      const unsigned char *data,
-		      mech_callback_t *callback)
-{
-        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 <= 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 ||
-	    data[request->initial_resp_idx-1] != '\0') {
-		i_error("BUG: Auth client %u sent corrupted request",
-			conn->pid);
-		failure_reply.id = request->id;
-		callback(&failure_reply, NULL, conn);
-		return;
-	}
-
-	mech = mech_module_find((const char *)data + request->mech_idx);
-	if (mech == NULL) {
-		/* unsupported mechanism */
-		i_error("BUG: Auth client %u requested unsupported "
-			"auth mechanism %s", conn->pid,
-			(const char *)data + request->mech_idx);
-		failure_reply.id = request->id;
-		callback(&failure_reply, NULL, conn);
-		return;
-	}
-
-	auth_request = mech->auth_new();
-	if (auth_request == NULL)
-		return;
-
-	auth_request->created = ioloop_time;
-	auth_request->conn = conn;
-	auth_request->id = request->id;
-	auth_request->protocol =
-		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.ip, data, ip_size);
-		memcpy(&auth_request->remote_ip.ip, data + ip_size, ip_size);
-	}
-
-	if (ssl_require_client_cert &&
-	    (request->flags & AUTH_CLIENT_FLAG_SSL_VALID_CLIENT_CERT) == 0) {
-		/* we fail without valid certificate */
-		if (verbose) {
-			i_info("ssl-cert-check(%s): "
-			       "Client didn't present valid SSL certificate",
-			       get_log_prefix(auth_request));
-		}
-		auth_request_unref(auth_request);
-
-		failure_reply.id = request->id;
-		callback(&failure_reply, NULL, conn);
-		return;
-	}
-
-	hash_insert(conn->auth_requests, POINTER_CAST(request->id),
-		    auth_request);
-
-	if (!auth_request->auth_initial(auth_request, request, data, callback))
-		mech_request_free(auth_request, request->id);
-}
-
-void mech_request_continue(struct auth_client_connection *conn,
-			   struct auth_client_request_continue *request,
-			   const unsigned char *data,
-			   mech_callback_t *callback)
-{
-	struct auth_request *auth_request;
-
-	auth_request = hash_lookup(conn->auth_requests,
-				   POINTER_CAST(request->id));
-	if (auth_request == NULL) {
-		/* timeouted */
-		failure_reply.id = request->id;
-		callback(&failure_reply, NULL, conn);
-	} else {
-		if (!auth_request->auth_continue(auth_request,
-						 data, request->data_size,
-						 callback))
-			mech_request_free(auth_request, request->id);
-	}
-}
-
-void mech_request_free(struct auth_request *auth_request, unsigned int id)
+struct auth_request *auth_request_new(struct mech_module *mech)
 {
-	if (auth_request->conn != NULL) {
-		hash_remove(auth_request->conn->auth_requests,
-			    POINTER_CAST(id));
-	}
-	auth_request_unref(auth_request);
-}
+	struct auth_request *request;
 
-void mech_init_auth_client_reply(struct auth_client_request_reply *reply)
-{
-	memset(reply, 0, sizeof(*reply));
+	request = mech->auth_new();
+	if (request == NULL)
+		return NULL;
 
-	reply->username_idx = (uint32_t)-1;
-	reply->reply_idx = (uint32_t)-1;
+	request->mech = mech;
+	request->created = ioloop_time;
+	return request;
 }
 
-void *mech_auth_success(struct auth_client_request_reply *reply,
-			struct auth_request *auth_request,
-			const void *data, size_t data_size)
+void auth_request_destroy(struct auth_request *request)
 {
-	buffer_t *buf;
-
-	buf = buffer_create_dynamic(pool_datastack_create(), 256);
-
-	reply->username_idx = 0;
-	buffer_append(buf, auth_request->user, strlen(auth_request->user)+1);
-
-	if (data_size == 0)
-		reply->reply_idx = (uint32_t)-1;
-	else {
-		reply->reply_idx = buffer_get_used_size(buf);
-		buffer_append(buf, data, data_size);
+	if (request->conn != NULL) {
+		hash_remove(request->conn->auth_requests,
+			    POINTER_CAST(request->id));
 	}
-
-	reply->result = AUTH_CLIENT_RESULT_SUCCESS;
-	reply->data_size = buffer_get_used_size(buf);
-	return buffer_get_modifyable_data(buf, NULL);
+	auth_request_unref(request);
 }
 
-void mech_auth_finish(struct auth_request *auth_request,
+void mech_auth_finish(struct auth_request *request,
 		      const void *data, size_t data_size, int success)
 {
-	struct auth_client_request_reply reply;
-	void *reply_data;
-	int free_request;
-
 	if (!success) {
 		/* failure. don't announce it immediately to avoid
 		   a) timing attacks, b) flooding */
-		buffer_append(auth_failures_buf,
-			      &auth_request, sizeof(auth_request));
+		buffer_append(auth_failures_buf, &request, sizeof(request));
 		return;
 	}
 
-	memset(&reply, 0, sizeof(reply));
-	reply.id = auth_request->id;
-	reply.result = AUTH_CLIENT_RESULT_SUCCESS;
-
-	if (auth_request->conn == NULL) {
-		/* client is already gone */
-		free_request = TRUE;
-	} else {
-		/* get this before callback because it can destroy connection */
-		free_request = AUTH_MASTER_IS_DUMMY(auth_request->conn->master);
-
-		reply_data = mech_auth_success(&reply, auth_request,
-					       data, data_size);
-		auth_request->callback(&reply, reply_data, auth_request->conn);
+	if (request->conn != NULL) {
+		request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
+				  data, data_size);
 	}
 
-	if (free_request) {
+	if (request->conn == NULL ||
+	    AUTH_MASTER_IS_DUMMY(request->conn->master)) {
 		/* we don't have master process, the request is no longer
 		   needed */
-		mech_request_free(auth_request, auth_request->id);
+		auth_request_destroy(request);
 	}
 }
 
@@ -285,7 +167,7 @@
 	if (--request->refcount > 0)
 		return TRUE;
 
-	request->auth_free(request);
+	request->mech->auth_free(request);
 	return FALSE;
 }
 
@@ -358,22 +240,18 @@
 void auth_failure_buf_flush(void)
 {
 	struct auth_request **auth_request;
-	struct auth_client_request_reply reply;
 	size_t i, size;
 
 	auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
 	size /= sizeof(*auth_request);
 
-	memset(&reply, 0, sizeof(reply));
-	reply.result = AUTH_CLIENT_RESULT_FAILURE;
-
 	for (i = 0; i < size; i++) {
-		reply.id = auth_request[i]->id;
 		if (auth_request[i]->conn != NULL) {
-			auth_request[i]->callback(&reply, NULL,
-						  auth_request[i]->conn);
+			auth_request[i]->callback(auth_request[i],
+						  AUTH_CLIENT_RESULT_FAILURE,
+						  NULL, 0);
 		}
-		mech_request_free(auth_request[i], reply.id);
+		auth_request_destroy(auth_request[i]);
 	}
 	buffer_set_used_size(auth_failures_buf, 0);
 }
@@ -397,10 +275,8 @@
 	const char *const *mechanisms;
 	const char *env;
 
-        mech_modules = NULL;
-
-	memset(&failure_reply, 0, sizeof(failure_reply));
-	failure_reply.result = AUTH_CLIENT_RESULT_FAILURE;
+	mech_modules = NULL;
+	mech_handshake = str_new(default_pool, 512);
 
 	anonymous_username = getenv("ANONYMOUS_USERNAME");
 	if (anonymous_username != NULL && *anonymous_username == '\0')
@@ -493,4 +369,6 @@
 	mech_unregister_module(&mech_ntlm);
 	mech_unregister_module(&mech_rpa);
 	mech_unregister_module(&mech_anonymous);
+
+	str_free(mech_handshake);
 }

Index: mech.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/mech.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- mech.h	10 Oct 2004 13:55:12 -0000	1.22
+++ mech.h	13 Oct 2004 16:38:32 -0000	1.23
@@ -4,11 +4,18 @@
 #include "network.h"
 #include "auth-client-interface.h"
 
+enum auth_client_result {
+	AUTH_CLIENT_RESULT_CONTINUE = 1,
+	AUTH_CLIENT_RESULT_SUCCESS,
+	AUTH_CLIENT_RESULT_FAILURE
+};
+
+struct auth_request;
 struct auth_client_connection;
 
-typedef void mech_callback_t(struct auth_client_request_reply *reply,
-			     const void *data,
-			     struct auth_client_connection *conn);
+typedef void mech_callback_t(struct auth_request *request,
+			     enum auth_client_result result,
+			     const void *reply, size_t reply_size);
 
 struct auth_request {
 	int refcount;
@@ -16,34 +23,35 @@
 	pool_t pool;
 	char *user;
 
+	struct mech_module *mech;
 	struct auth_client_connection *conn;
+
 	unsigned int id;
 	time_t created;
 
-	char *protocol;
+	const char *protocol;
 	struct ip_addr local_ip, remote_ip;
 	mech_callback_t *callback;
 
-	int (*auth_initial)(struct auth_request *auth_request,
-                            struct auth_client_request_new *request,
-			    const unsigned char *data,
-			    mech_callback_t *callback);
-	int (*auth_continue)(struct auth_request *auth_request,
-			     const unsigned char *data, size_t data_size,
-			     mech_callback_t *callback);
-	void (*auth_free)(struct auth_request *auth_request);
+	unsigned int accept_input:1;
 	/* ... mechanism specific data ... */
 };
 
 struct mech_module {
 	const char *mech_name;
 
-	unsigned int plaintext:1;
-	unsigned int advertise:1;
+        enum mech_security_flags flags;
 	unsigned int passdb_need_plain:1;
 	unsigned int passdb_need_credentials:1;
 
 	struct auth_request *(*auth_new)(void);
+	void (*auth_initial)(struct auth_request *request,
+			     const unsigned char *data, size_t data_size,
+			     mech_callback_t *callback);
+	void (*auth_continue)(struct auth_request *request,
+			      const unsigned char *data, size_t data_size,
+			      mech_callback_t *callback);
+	void (*auth_free)(struct auth_request *request);
 };
 
 struct mech_module_list {
@@ -53,6 +61,8 @@
 };
 
 extern struct mech_module_list *mech_modules;
+extern buffer_t *mech_handshake;
+
 extern const char *const *auth_realms;
 extern const char *default_realm;
 extern const char *anonymous_username;
@@ -61,28 +71,17 @@
 
 void mech_register_module(struct mech_module *module);
 void mech_unregister_module(struct mech_module *module);
+struct mech_module *mech_module_find(const char *name);
 
 const string_t *auth_mechanisms_get_list(void);
 
-void mech_request_new(struct auth_client_connection *conn,
-		      struct auth_client_request_new *request,
-		      const unsigned char *data,
-		      mech_callback_t *callback);
-void mech_request_continue(struct auth_client_connection *conn,
-			   struct auth_client_request_continue *request,
-			   const unsigned char *data,
-			   mech_callback_t *callback);
-void mech_request_free(struct auth_request *auth_request, unsigned int id);
-
-void mech_init_auth_client_reply(struct auth_client_request_reply *reply);
-void *mech_auth_success(struct auth_client_request_reply *reply,
-			struct auth_request *auth_request,
-			const void *data, size_t data_size);
-void mech_auth_finish(struct auth_request *auth_request,
+void mech_auth_finish(struct auth_request *request,
 		      const void *data, size_t data_size, int success);
 
 int mech_fix_username(char *username, const char **error_r);
 
+struct auth_request *auth_request_new(struct mech_module *mech);
+void auth_request_destroy(struct auth_request *request);
 void auth_request_ref(struct auth_request *request);
 int auth_request_unref(struct auth_request *request);
 

Index: userdb.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/auth/userdb.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- userdb.h	20 Sep 2004 21:47:31 -0000	1.10
+++ userdb.h	13 Oct 2004 16:38:32 -0000	1.11
@@ -13,7 +13,7 @@
 	gid_t gid;
 };
 
-typedef void userdb_callback_t(struct user_data *user, void *context);
+typedef void userdb_callback_t(const struct user_data *user, void *context);
 
 struct userdb_module {
 	void (*preinit)(const char *args);



More information about the dovecot-cvs mailing list