changeset 3064:2d33734b16d5 HEAD

Split auth_request* functions from mech.c to auth-request.c
author Timo Sirainen <tss@iki.fi>
date Fri, 07 Jan 2005 20:51:10 +0200
parents a0fbf92b41c3
children 29d83a8bb50d
files src/auth/Makefile.am src/auth/auth-cache.c src/auth/auth-client-connection.c src/auth/auth-master-connection.c src/auth/auth-request.c src/auth/auth-request.h src/auth/main.c src/auth/mech-anonymous.c src/auth/mech-apop.c src/auth/mech-cram-md5.c src/auth/mech-digest-md5.c src/auth/mech-login.c src/auth/mech-ntlm.c src/auth/mech-plain.c src/auth/mech-rpa.c src/auth/mech.c src/auth/mech.h src/auth/userdb.h
diffstat 18 files changed, 443 insertions(+), 410 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/Makefile.am	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/Makefile.am	Fri Jan 07 20:51:10 2005 +0200
@@ -36,6 +36,7 @@
 	auth-client-connection.c \
 	auth-master-connection.c \
 	auth-module.c \
+	auth-request.c \
 	db-ldap.c \
 	db-sql.c \
 	db-passwd-file.c \
@@ -76,6 +77,7 @@
 	auth-master-interface.h \
 	auth-master-connection.h \
 	auth-module.h \
+	auth-request.h \
 	db-ldap.h \
 	db-sql.h \
 	db-passwd-file.h \
--- a/src/auth/auth-cache.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/auth-cache.c	Fri Jan 07 20:51:10 2005 +0200
@@ -6,7 +6,7 @@
 #include "str.h"
 #include "strescape.h"
 #include "var-expand.h"
-#include "mech.h"
+#include "auth-request.h"
 #include "auth-cache.h"
 
 #include <time.h>
--- a/src/auth/auth-client-connection.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/auth-client-connection.c	Fri Jan 07 20:51:10 2005 +0200
@@ -11,7 +11,7 @@
 #include "str.h"
 #include "str-sanitize.h"
 #include "safe-memset.h"
-#include "mech.h"
+#include "auth-request.h"
 #include "auth-client-connection.h"
 #include "auth-master-connection.h"
 
--- a/src/auth/auth-master-connection.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/auth-master-connection.c	Fri Jan 07 20:51:10 2005 +0200
@@ -8,8 +8,8 @@
 #include "istream.h"
 #include "ostream.h"
 #include "network.h"
-#include "mech.h"
 #include "userdb.h"
+#include "auth-request.h"
 #include "auth-master-interface.h"
 #include "auth-client-connection.h"
 #include "auth-master-connection.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/auth-request.c	Fri Jan 07 20:51:10 2005 +0200
@@ -0,0 +1,317 @@
+/* Copyright (C) 2002-2005 Timo Sirainen */
+
+#include "common.h"
+#include "ioloop.h"
+#include "buffer.h"
+#include "hash.h"
+#include "str.h"
+#include "safe-memset.h"
+#include "str-sanitize.h"
+#include "var-expand.h"
+#include "auth-request.h"
+#include "auth-client-connection.h"
+#include "auth-master-connection.h"
+#include "passdb.h"
+#include "passdb-cache.h"
+
+struct auth_request_extra {
+	struct auth_request *request;
+	string_t *str;
+	char *user_password, *password;
+};
+
+static buffer_t *auth_failures_buf;
+static struct timeout *to_auth_failures;
+
+struct auth_request *auth_request_new(struct mech_module *mech)
+{
+	struct auth_request *request;
+
+	request = mech->auth_new();
+	if (request == NULL)
+		return NULL;
+
+	request->mech = mech;
+	request->created = ioloop_time;
+	return request;
+}
+
+void auth_request_destroy(struct auth_request *request)
+{
+	i_assert(request->refcount > 0);
+
+	if (request->destroyed)
+		return;
+	request->destroyed = TRUE;
+
+	if (request->conn != NULL) {
+		hash_remove(request->conn->auth_requests,
+			    POINTER_CAST(request->id));
+	}
+	auth_request_unref(request);
+}
+
+void auth_request_success(struct auth_request *request,
+			  const void *data, size_t data_size)
+{
+	request->successful = TRUE;
+	if (request->conn != NULL) {
+		request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
+				  data, data_size);
+	}
+
+	if (request->no_login || request->conn == NULL ||
+	    AUTH_MASTER_IS_DUMMY(request->conn->master)) {
+		/* we don't have master process, the request is no longer
+		   needed */
+		auth_request_destroy(request);
+	}
+}
+
+void auth_request_fail(struct auth_request *request)
+{
+	if (request->no_failure_delay) {
+		/* passdb specifically requested to to delay the reply. */
+		request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
+		auth_request_destroy(request);
+		return;
+	}
+
+	/* failure. don't announce it immediately to avoid
+	   a) timing attacks, b) flooding */
+	if (auth_failures_buf->used > 0) {
+		const struct auth_request *const *requests;
+
+		requests = auth_failures_buf->data;
+		requests += auth_failures_buf->used/sizeof(*requests)-1;
+		i_assert(*requests != request);
+	}
+
+	buffer_append(auth_failures_buf, &request, sizeof(request));
+
+	/* make sure the request isn't found anymore */
+	auth_request_ref(request);
+	auth_request_destroy(request);
+}
+
+void auth_request_internal_failure(struct auth_request *request)
+{
+	request->internal_failure = TRUE;
+	auth_request_fail(request);
+}
+
+void auth_request_ref(struct auth_request *request)
+{
+	request->refcount++;
+}
+
+int auth_request_unref(struct auth_request *request)
+{
+	i_assert(request->refcount > 0);
+	if (--request->refcount > 0)
+		return TRUE;
+
+	request->mech->auth_free(request);
+	return FALSE;
+}
+
+struct auth_request_extra *
+auth_request_extra_begin(struct auth_request *request,
+			 const char *user_password)
+{
+	struct auth_request_extra *extra;
+
+	extra = i_new(struct auth_request_extra, 1);
+	extra->request = request;
+	extra->user_password = i_strdup(user_password);
+	return extra;
+}
+
+void auth_request_extra_next(struct auth_request_extra *extra,
+			     const char *name, const char *value)
+{
+	string_t *str;
+
+	i_assert(value != NULL);
+
+	if (strcmp(name, "password") == 0) {
+		i_assert(extra->password == NULL);
+		extra->password = i_strdup(value);
+		return;
+	}
+
+	if (strcmp(name, "nodelay") == 0) {
+		/* don't delay replying to client of the failure */
+		extra->request->no_failure_delay = TRUE;
+		return;
+	}
+
+	str = extra->str;
+	if (str == NULL)
+		extra->str = str = str_new(extra->request->pool, 64);
+
+	if (strcmp(name, "nologin") == 0) {
+		/* user can't actually login - don't keep this
+		   reply for master */
+		extra->request->no_login = TRUE;
+		if (str_len(str) > 0)
+			str_append_c(str, '\t');
+		str_append(str, name);
+	} else if (strcmp(name, "proxy") == 0) {
+		/* we're proxying authentication for this user. send
+		   password back if using plaintext authentication. */
+		extra->request->proxy = TRUE;
+		if (str_len(str) > 0)
+			str_append_c(str, '\t');
+		str_append(str, name);
+	} else {
+		if (str_len(str) > 0)
+			str_append_c(str, '\t');
+		str_printfa(str, "%s=%s", name, value);
+	}
+}
+
+void auth_request_extra_finish(struct auth_request_extra *extra,
+			       const char *cache_key)
+{
+	string_t *str;
+
+	if (passdb_cache != NULL && cache_key != NULL) {
+		str = t_str_new(64);
+		if (extra->str != NULL)
+			str_append_str(str, extra->str);
+		if (extra->request->no_failure_delay) {
+			if (str_len(str) > 0)
+				str_append_c(str, '\t');
+			str_append(str, "nodelay");
+		}
+		auth_cache_insert(passdb_cache, extra->request, cache_key,
+				  t_strconcat(extra->password == NULL ? "" :
+					      extra->password,
+					      str_len(str) > 0 ? "\t" : "",
+					      str_c(str), NULL));
+	}
+
+	if (extra->user_password != NULL) {
+		if (extra->request->proxy) {
+			/* we're proxying - send back the password that was
+			   sent by user (not the password in passdb). */
+			str_printfa(extra->str, "\tpass=%s",
+				    extra->user_password);
+		}
+		safe_memset(extra->user_password, 0,
+			    strlen(extra->user_password));
+		i_free(extra->user_password);
+	}
+
+	if (extra->str != NULL)
+		extra->request->extra_fields = str_c(extra->str);
+
+	if (extra->password != NULL) {
+		safe_memset(extra->password, 0, strlen(extra->password));
+		i_free(extra->password);
+	}
+	i_free(extra);
+}
+
+static const char *escape_none(const char *str)
+{
+	return str;
+}
+
+const struct var_expand_table *
+auth_request_get_var_expand_table(const struct auth_request *auth_request,
+				  const char *(*escape_func)(const char *))
+{
+	static struct var_expand_table static_tab[] = {
+		{ 'u', NULL },
+		{ 'n', NULL },
+		{ 'd', NULL },
+		{ 's', NULL },
+		{ 'h', NULL },
+		{ 'l', NULL },
+		{ 'r', NULL },
+		{ 'p', NULL },
+		{ '\0', NULL }
+	};
+	struct var_expand_table *tab;
+
+	if (escape_func == NULL)
+		escape_func = escape_none;
+
+	tab = t_malloc(sizeof(static_tab));
+	memcpy(tab, static_tab, sizeof(static_tab));
+
+	tab[0].value = escape_func(auth_request->user);
+	tab[1].value = escape_func(t_strcut(auth_request->user, '@'));
+	tab[2].value = strchr(auth_request->user, '@');
+	if (tab[2].value != NULL)
+		tab[2].value = escape_func(tab[2].value+1);
+	tab[3].value = auth_request->service;
+	/* tab[4] = we have no home dir */
+	if (auth_request->local_ip.family != 0)
+		tab[5].value = net_ip2addr(&auth_request->local_ip);
+	if (auth_request->remote_ip.family != 0)
+		tab[6].value = net_ip2addr(&auth_request->remote_ip);
+	tab[7].value = dec2str(auth_request->conn->pid);
+	return tab;
+}
+
+const char *get_log_prefix(const struct auth_request *auth_request)
+{
+#define MAX_LOG_USERNAME_LEN 64
+	const char *ip;
+	string_t *str;
+
+	str = t_str_new(64);
+
+	if (auth_request->user == NULL)
+		str_append(str, "?");
+	else {
+		str_sanitize_append(str, auth_request->user,
+				    MAX_LOG_USERNAME_LEN);
+	}
+
+	ip = net_ip2addr(&auth_request->remote_ip);
+	if (ip != NULL) {
+		str_append_c(str, ',');
+		str_append(str, ip);
+	}
+	return str_c(str);
+}
+
+void auth_failure_buf_flush(void)
+{
+	struct auth_request **auth_request;
+	size_t i, size;
+
+	auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
+	size /= sizeof(*auth_request);
+
+	for (i = 0; i < size; i++) {
+		if (auth_request[i]->conn != NULL) {
+			auth_request[i]->callback(auth_request[i],
+						  AUTH_CLIENT_RESULT_FAILURE,
+						  NULL, 0);
+		}
+		auth_request_destroy(auth_request[i]);
+	}
+	buffer_set_used_size(auth_failures_buf, 0);
+}
+
+static void auth_failure_timeout(void *context __attr_unused__)
+{
+	auth_failure_buf_flush();
+}
+
+void auth_requests_init(void)
+{
+	auth_failures_buf = buffer_create_dynamic(default_pool, 1024);
+        to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL);
+}
+
+void auth_requests_deinit(void)
+{
+	buffer_free(auth_failures_buf);
+	timeout_remove(to_auth_failures);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/auth-request.h	Fri Jan 07 20:51:10 2005 +0200
@@ -0,0 +1,64 @@
+#ifndef __AUTH_REQUEST_H
+#define __AUTH_REQUEST_H
+
+#include "network.h"
+#include "mech.h"
+
+struct auth_client_connection;
+
+struct auth_request {
+	int refcount;
+
+	pool_t pool;
+	char *user;
+	const char *extra_fields;
+
+	struct mech_module *mech;
+	struct auth_client_connection *conn;
+
+	unsigned int id;
+	time_t created;
+
+	const char *service;
+	struct ip_addr local_ip, remote_ip;
+	mech_callback_t *callback;
+
+	unsigned int successful:1;
+	unsigned int internal_failure:1;
+	unsigned int accept_input:1;
+	unsigned int no_failure_delay:1;
+	unsigned int no_login:1;
+	unsigned int proxy:1;
+	unsigned int destroyed:1;
+	/* ... mechanism specific data ... */
+};
+
+void auth_request_success(struct auth_request *request,
+			  const void *data, size_t data_size);
+void auth_request_fail(struct auth_request *request);
+void auth_request_internal_failure(struct auth_request *request);
+
+struct auth_request *auth_request_new(struct 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);
+
+struct auth_request_extra *
+auth_request_extra_begin(struct auth_request *request, const char *password);
+void auth_request_extra_next(struct auth_request_extra *extra,
+			     const char *name, const char *value);
+void auth_request_extra_finish(struct auth_request_extra *extra,
+			       const char *cache_key);
+
+const struct var_expand_table *
+auth_request_get_var_expand_table(const struct auth_request *auth_request,
+				  const char *(*escape_func)(const char *));
+
+const char *get_log_prefix(const struct auth_request *auth_request);
+
+void auth_failure_buf_flush(void);
+
+void auth_requests_init(void);
+void auth_requests_deinit(void);
+
+#endif
--- a/src/auth/main.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/main.c	Fri Jan 07 20:51:10 2005 +0200
@@ -12,6 +12,7 @@
 #include "userdb.h"
 #include "passdb.h"
 #include "password-scheme.h"
+#include "auth-request.h"
 #include "auth-master-connection.h"
 #include "auth-client-connection.h"
 
@@ -202,6 +203,7 @@
 
 	lib_init_signals(sig_quit);
 	mech_init();
+	auth_requests_init();
 
 	env = getenv("AUTH_PROCESS");
 	standalone = env == NULL;
@@ -267,6 +269,7 @@
         password_schemes_deinit();
 	passdb_deinit();
 	userdb_deinit();
+	auth_requests_deinit();
 	mech_deinit();
 
 	random_deinit();
--- a/src/auth/mech-anonymous.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-anonymous.c	Fri Jan 07 20:51:10 2005 +0200
@@ -22,7 +22,7 @@
 	request->callback = callback;
 	request->user = p_strdup(request->pool, anonymous_username);
 
-	mech_auth_success(request, NULL, 0);
+	auth_request_success(request, NULL, 0);
 }
 
 static void
--- a/src/auth/mech-apop.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-apop.c	Fri Jan 07 20:51:10 2005 +0200
@@ -56,15 +56,15 @@
 	switch (result) {
 	case PASSDB_RESULT_OK:
 		if (verify_credentials(request, credentials))
-			mech_auth_success(auth_request, NULL, 0);
+			auth_request_success(auth_request, NULL, 0);
 		else
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(auth_request);
+		auth_request_internal_failure(auth_request);
 		break;
 	default:
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		break;
 	}
 }
@@ -87,7 +87,7 @@
 			i_info("apop(%s): no initial respone",
 			       get_log_prefix(auth_request));
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		return;
 	}
 
@@ -107,7 +107,7 @@
 			i_info("apop(%s): invalid challenge",
 			       get_log_prefix(auth_request));
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		return;
 	}
 	request->challenge = p_strdup(request->pool, (const char *)data);
@@ -124,7 +124,7 @@
 			i_info("apop(%s): malformed data",
 			       get_log_prefix(auth_request));
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		return;
 	}
 	tmp++;
@@ -135,7 +135,7 @@
 			i_info("apop(%s): %s",
 			       get_log_prefix(auth_request), error);
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		return;
 	}
 
--- a/src/auth/mech-cram-md5.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-cram-md5.c	Fri Jan 07 20:51:10 2005 +0200
@@ -119,15 +119,15 @@
 	switch (result) {
 	case PASSDB_RESULT_OK:
 		if (verify_credentials(request, credentials))
-			mech_auth_success(auth_request, NULL, 0);
+			auth_request_success(auth_request, NULL, 0);
 		else
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(auth_request);
+		auth_request_internal_failure(auth_request);
 		break;
 	default:
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		break;
 	}
 }
@@ -160,7 +160,7 @@
 
 	if (verbose)
 		i_info("cram-md5(%s): %s", get_log_prefix(auth_request), error);
-	mech_auth_fail(auth_request);
+	auth_request_fail(auth_request);
 }
 
 static void
--- a/src/auth/mech-digest-md5.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-digest-md5.c	Fri Jan 07 20:51:10 2005 +0200
@@ -524,19 +524,21 @@
 	switch (result) {
 	case PASSDB_RESULT_OK:
 		if (!verify_credentials(request, credentials)) {
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 			return;
 		}
 
 		request->authenticated = TRUE;
-		auth_request->callback(auth_request, AUTH_CLIENT_RESULT_CONTINUE,
-				       request->rspauth, strlen(request->rspauth));
+		auth_request->callback(auth_request,
+				       AUTH_CLIENT_RESULT_CONTINUE,
+				       request->rspauth,
+				       strlen(request->rspauth));
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(auth_request);
+		auth_request_internal_failure(auth_request);
 		break;
 	default:
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		break;
 	}
 }
@@ -553,7 +555,7 @@
 	if (request->authenticated) {
 		/* authentication is done, we were just waiting the last
 		   word from client */
-		mech_auth_success(auth_request, NULL, 0);
+		auth_request_success(auth_request, NULL, 0);
 		return;
 	}
 
@@ -583,7 +585,7 @@
 		       get_log_prefix(auth_request), error);
 	}
 
-	mech_auth_fail(auth_request);
+	auth_request_fail(auth_request);
 }
 
 static void
--- a/src/auth/mech-login.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-login.c	Fri Jan 07 20:51:10 2005 +0200
@@ -19,13 +19,13 @@
 {
 	switch (result) {
 	case PASSDB_RESULT_OK:
-		mech_auth_success(request, NULL, 0);
+		auth_request_success(request, NULL, 0);
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(request);
+		auth_request_internal_failure(request);
 		break;
 	default:
-		mech_auth_fail(request);
+		auth_request_fail(request);
 		break;
 	}
 }
@@ -48,7 +48,7 @@
 				i_info("login(%s): %s",
 				       get_log_prefix(request), error);
 			}
-			mech_auth_fail(request);
+			auth_request_fail(request);
 			return;
 		}
 
--- a/src/auth/mech-ntlm.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-ntlm.c	Fri Jan 07 20:51:10 2005 +0200
@@ -75,15 +75,15 @@
 	switch (result) {
 	case PASSDB_RESULT_OK:
 		if (lm_verify_credentials(request, credentials))
-			mech_auth_success(auth_request, NULL, 0);
+			auth_request_success(auth_request, NULL, 0);
 		else
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(auth_request);
+		auth_request_internal_failure(auth_request);
 		break;
 	default:
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		break;
 	}
 }
@@ -158,16 +158,16 @@
 	case PASSDB_RESULT_OK:
 		ret = ntlm_verify_credentials(request, credentials);
 		if (ret > 0) {
-			mech_auth_success(auth_request, NULL, 0);
+			auth_request_success(auth_request, NULL, 0);
 			return;
 		}
 		if (ret < 0) {
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 			return;
 		}
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(auth_request);
+		auth_request_internal_failure(auth_request);
 		return;
 	default:
 		break;
@@ -203,7 +203,7 @@
 				       get_log_prefix(auth_request),
 				       error);
 			}
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 			return;
 		}
 
@@ -228,7 +228,7 @@
 				       get_log_prefix(auth_request),
 				       error);
 			}
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 			return;
 		}
 
@@ -244,7 +244,7 @@
 				i_info("ntlm(%s): %s",
 				       get_log_prefix(auth_request), error);
 			}
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 			return;
 		}
 
--- a/src/auth/mech-plain.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-plain.c	Fri Jan 07 20:51:10 2005 +0200
@@ -10,13 +10,13 @@
 {
 	switch (result) {
 	case PASSDB_RESULT_OK:
-		mech_auth_success(request, NULL, 0);
+		auth_request_success(request, NULL, 0);
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(request);
+		auth_request_internal_failure(request);
 		break;
 	default:
-		mech_auth_fail(request);
+		auth_request_fail(request);
 		break;
 	}
 }
@@ -58,7 +58,7 @@
 			i_info("plain(%s): invalid input",
 			       get_log_prefix(request));
 		}
-		mech_auth_fail(request);
+		auth_request_fail(request);
 	} else {
 		/* split and save user/realm */
 		if (strchr(authenid, '@') == NULL && default_realm != NULL) {
@@ -75,7 +75,7 @@
 				i_info("plain(%s): %s",
 				       get_log_prefix(request), error);
 			}
-			mech_auth_fail(request);
+			auth_request_fail(request);
 		} else {
 			passdb->verify_plain(request, pass, verify_callback);
 		}
--- a/src/auth/mech-rpa.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech-rpa.c	Fri Jan 07 20:51:10 2005 +0200
@@ -425,7 +425,7 @@
 	switch (result) {
 	case PASSDB_RESULT_OK:
 		if (!verify_credentials(request, credentials))
-			mech_auth_fail(auth_request);
+			auth_request_fail(auth_request);
 		else {
 			token4 = mech_rpa_build_token4(request, &token4_size);
 			auth_request->callback(auth_request,
@@ -435,10 +435,10 @@
 		}
 		break;
 	case PASSDB_RESULT_INTERNAL_FAILURE:
-		mech_auth_internal_failure(auth_request);
+		auth_request_internal_failure(auth_request);
 		break;
 	default:
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		break;
 	}
 }
@@ -458,7 +458,7 @@
 			i_info("rpa(%s): invalid token 1, %s",
 			       get_log_prefix(auth_request), error);
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		return;
 	}
 
@@ -490,7 +490,7 @@
 			i_info("rpa(%s): invalid token 3, %s",
 			       get_log_prefix(auth_request), error);
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		return;
 	}
 
@@ -499,7 +499,7 @@
 			i_info("rpa(%s): %s",
 			       get_log_prefix(auth_request), error);
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		return;
 	}
 
@@ -519,9 +519,9 @@
 			i_info("rpa(%s): invalid token 5 or client rejects us",
 			       get_log_prefix(auth_request));
 		}
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 	} else {
-		mech_auth_success(auth_request, NULL, 0);
+		auth_request_success(auth_request, NULL, 0);
 	}
 }
 
@@ -546,7 +546,7 @@
 		mech_rpa_auth_phase3(auth_request, data, data_size);
 		break;
 	default:
-		mech_auth_fail(auth_request);
+		auth_request_fail(auth_request);
 		break;
 	}
 }
--- a/src/auth/mech.c	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech.c	Fri Jan 07 20:51:10 2005 +0200
@@ -2,28 +2,14 @@
 
 #include "common.h"
 #include "ioloop.h"
-#include "buffer.h"
-#include "hash.h"
 #include "mech.h"
-#include "safe-memset.h"
 #include "str.h"
-#include "str-sanitize.h"
-#include "var-expand.h"
-#include "auth-client-connection.h"
-#include "auth-master-connection.h"
 #include "passdb.h"
-#include "passdb-cache.h"
 
 #include <stdlib.h>
 
-struct auth_request_extra {
-	struct auth_request *request;
-	string_t *str;
-	char *user_password, *password;
-};
-
 struct mech_module_list *mech_modules;
-buffer_t *mech_handshake;
+string_t *mech_handshake;
 
 const char *const *auth_realms;
 const char *default_realm;
@@ -31,9 +17,6 @@
 char username_chars[256], username_translation[256];
 int ssl_require_client_cert;
 
-static buffer_t *auth_failures_buf;
-static struct timeout *to_auth_failures;
-
 void mech_register_module(struct mech_module *module)
 {
 	struct mech_module_list *list;
@@ -99,83 +82,6 @@
 	return NULL;
 }
 
-struct auth_request *auth_request_new(struct mech_module *mech)
-{
-	struct auth_request *request;
-
-	request = mech->auth_new();
-	if (request == NULL)
-		return NULL;
-
-	request->mech = mech;
-	request->created = ioloop_time;
-	return request;
-}
-
-void auth_request_destroy(struct auth_request *request)
-{
-	i_assert(request->refcount > 0);
-
-	if (request->destroyed)
-		return;
-	request->destroyed = TRUE;
-
-	if (request->conn != NULL) {
-		hash_remove(request->conn->auth_requests,
-			    POINTER_CAST(request->id));
-	}
-	auth_request_unref(request);
-}
-
-void mech_auth_success(struct auth_request *request,
-		       const void *data, size_t data_size)
-{
-	request->successful = TRUE;
-	if (request->conn != NULL) {
-		request->callback(request, AUTH_CLIENT_RESULT_SUCCESS,
-				  data, data_size);
-	}
-
-	if (request->no_login || request->conn == NULL ||
-	    AUTH_MASTER_IS_DUMMY(request->conn->master)) {
-		/* we don't have master process, the request is no longer
-		   needed */
-		auth_request_destroy(request);
-	}
-}
-
-void mech_auth_fail(struct auth_request *request)
-{
-	if (request->no_failure_delay) {
-		/* passdb specifically requested to to delay the reply. */
-		request->callback(request, AUTH_CLIENT_RESULT_FAILURE, NULL, 0);
-		auth_request_destroy(request);
-		return;
-	}
-
-	/* failure. don't announce it immediately to avoid
-	   a) timing attacks, b) flooding */
-	if (auth_failures_buf->used > 0) {
-		const struct auth_request *const *requests;
-
-		requests = auth_failures_buf->data;
-		requests += auth_failures_buf->used/sizeof(*requests)-1;
-		i_assert(*requests != request);
-	}
-
-	buffer_append(auth_failures_buf, &request, sizeof(request));
-
-	/* make sure the request isn't found anymore */
-	auth_request_ref(request);
-	auth_request_destroy(request);
-}
-
-void mech_auth_internal_failure(struct auth_request *request)
-{
-	request->internal_failure = TRUE;
-	mech_auth_fail(request);
-}
-
 int mech_fix_username(char *username, const char **error_r)
 {
 	unsigned char *p;
@@ -198,210 +104,6 @@
 	return TRUE;
 }
 
-void auth_request_ref(struct auth_request *request)
-{
-	request->refcount++;
-}
-
-int auth_request_unref(struct auth_request *request)
-{
-	i_assert(request->refcount > 0);
-	if (--request->refcount > 0)
-		return TRUE;
-
-	request->mech->auth_free(request);
-	return FALSE;
-}
-
-struct auth_request_extra *
-auth_request_extra_begin(struct auth_request *request,
-			 const char *user_password)
-{
-	struct auth_request_extra *extra;
-
-	extra = i_new(struct auth_request_extra, 1);
-	extra->request = request;
-	extra->user_password = i_strdup(user_password);
-	return extra;
-}
-
-void auth_request_extra_next(struct auth_request_extra *extra,
-			     const char *name, const char *value)
-{
-	string_t *str;
-
-	i_assert(value != NULL);
-
-	if (strcmp(name, "password") == 0) {
-		i_assert(extra->password == NULL);
-		extra->password = i_strdup(value);
-		return;
-	}
-
-	if (strcmp(name, "nodelay") == 0) {
-		/* don't delay replying to client of the failure */
-		extra->request->no_failure_delay = TRUE;
-		return;
-	}
-
-	str = extra->str;
-	if (str == NULL)
-		extra->str = str = str_new(extra->request->pool, 64);
-
-	if (strcmp(name, "nologin") == 0) {
-		/* user can't actually login - don't keep this
-		   reply for master */
-		extra->request->no_login = TRUE;
-		if (str_len(str) > 0)
-			str_append_c(str, '\t');
-		str_append(str, name);
-	} else if (strcmp(name, "proxy") == 0) {
-		/* we're proxying authentication for this user. send
-		   password back if using plaintext authentication. */
-		extra->request->proxy = TRUE;
-		if (str_len(str) > 0)
-			str_append_c(str, '\t');
-		str_append(str, name);
-	} else {
-		if (str_len(str) > 0)
-			str_append_c(str, '\t');
-		str_printfa(str, "%s=%s", name, value);
-	}
-}
-
-void auth_request_extra_finish(struct auth_request_extra *extra,
-			       const char *cache_key)
-{
-	string_t *str;
-
-	if (passdb_cache != NULL && cache_key != NULL) {
-		str = t_str_new(64);
-		if (extra->str != NULL)
-			str_append_str(str, extra->str);
-		if (extra->request->no_failure_delay) {
-			if (str_len(str) > 0)
-				str_append_c(str, '\t');
-			str_append(str, "nodelay");
-		}
-		auth_cache_insert(passdb_cache, extra->request, cache_key,
-				  t_strconcat(extra->password == NULL ? "" :
-					      extra->password,
-					      str_len(str) > 0 ? "\t" : "",
-					      str_c(str), NULL));
-	}
-
-	if (extra->user_password != NULL) {
-		if (extra->request->proxy) {
-			/* we're proxying - send back the password that was
-			   sent by user (not the password in passdb). */
-			str_printfa(extra->str, "\tpass=%s",
-				    extra->user_password);
-		}
-		safe_memset(extra->user_password, 0,
-			    strlen(extra->user_password));
-		i_free(extra->user_password);
-	}
-
-	if (extra->str != NULL)
-		extra->request->extra_fields = str_c(extra->str);
-
-	if (extra->password != NULL) {
-		safe_memset(extra->password, 0, strlen(extra->password));
-		i_free(extra->password);
-	}
-	i_free(extra);
-}
-
-static const char *escape_none(const char *str)
-{
-	return str;
-}
-
-const struct var_expand_table *
-auth_request_get_var_expand_table(const struct auth_request *auth_request,
-				  const char *(*escape_func)(const char *))
-{
-	static struct var_expand_table static_tab[] = {
-		{ 'u', NULL },
-		{ 'n', NULL },
-		{ 'd', NULL },
-		{ 's', NULL },
-		{ 'h', NULL },
-		{ 'l', NULL },
-		{ 'r', NULL },
-		{ 'p', NULL },
-		{ '\0', NULL }
-	};
-	struct var_expand_table *tab;
-
-	if (escape_func == NULL)
-		escape_func = escape_none;
-
-	tab = t_malloc(sizeof(static_tab));
-	memcpy(tab, static_tab, sizeof(static_tab));
-
-	tab[0].value = escape_func(auth_request->user);
-	tab[1].value = escape_func(t_strcut(auth_request->user, '@'));
-	tab[2].value = strchr(auth_request->user, '@');
-	if (tab[2].value != NULL)
-		tab[2].value = escape_func(tab[2].value+1);
-	tab[3].value = auth_request->service;
-	/* tab[4] = we have no home dir */
-	if (auth_request->local_ip.family != 0)
-		tab[5].value = net_ip2addr(&auth_request->local_ip);
-	if (auth_request->remote_ip.family != 0)
-		tab[6].value = net_ip2addr(&auth_request->remote_ip);
-	tab[7].value = dec2str(auth_request->conn->pid);
-	return tab;
-}
-
-const char *get_log_prefix(const struct auth_request *auth_request)
-{
-#define MAX_LOG_USERNAME_LEN 64
-	const char *ip;
-	string_t *str;
-
-	str = t_str_new(64);
-
-	if (auth_request->user == NULL)
-		str_append(str, "?");
-	else {
-		str_sanitize_append(str, auth_request->user,
-				    MAX_LOG_USERNAME_LEN);
-	}
-
-	ip = net_ip2addr(&auth_request->remote_ip);
-	if (ip != NULL) {
-		str_append_c(str, ',');
-		str_append(str, ip);
-	}
-	return str_c(str);
-}
-
-void auth_failure_buf_flush(void)
-{
-	struct auth_request **auth_request;
-	size_t i, size;
-
-	auth_request = buffer_get_modifyable_data(auth_failures_buf, &size);
-	size /= sizeof(*auth_request);
-
-	for (i = 0; i < size; i++) {
-		if (auth_request[i]->conn != NULL) {
-			auth_request[i]->callback(auth_request[i],
-						  AUTH_CLIENT_RESULT_FAILURE,
-						  NULL, 0);
-		}
-		auth_request_destroy(auth_request[i]);
-	}
-	buffer_set_used_size(auth_failures_buf, 0);
-}
-
-static void auth_failure_timeout(void *context __attr_unused__)
-{
-	auth_failure_buf_flush();
-}
-
 static void mech_list_verify_passdb(struct passdb_module *passdb)
 {
 	struct mech_module_list *list;
@@ -512,15 +214,10 @@
 	}
 
 	ssl_require_client_cert = getenv("SSL_REQUIRE_CLIENT_CERT") != NULL;
-
-	auth_failures_buf = buffer_create_dynamic(default_pool, 1024);
-        to_auth_failures = timeout_add(2000, auth_failure_timeout, NULL);
 }
 
 void mech_deinit(void)
 {
-	timeout_remove(to_auth_failures);
-
 	mech_unregister_module(&mech_plain);
 	mech_unregister_module(&mech_login);
 	mech_unregister_module(&mech_apop);
--- a/src/auth/mech.h	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/mech.h	Fri Jan 07 20:51:10 2005 +0200
@@ -1,7 +1,6 @@
 #ifndef __MECH_H
 #define __MECH_H
 
-#include "network.h"
 #include "auth-client-interface.h"
 
 enum auth_client_result {
@@ -11,38 +10,12 @@
 };
 
 struct auth_request;
-struct auth_client_connection;
 
 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;
-
-	pool_t pool;
-	char *user;
-	const char *extra_fields;
-
-	struct mech_module *mech;
-	struct auth_client_connection *conn;
-
-	unsigned int id;
-	time_t created;
-
-	const char *service;
-	struct ip_addr local_ip, remote_ip;
-	mech_callback_t *callback;
-
-	unsigned int successful:1;
-	unsigned int internal_failure:1;
-	unsigned int accept_input:1;
-	unsigned int no_failure_delay:1;
-	unsigned int no_login:1;
-	unsigned int proxy:1;
-	unsigned int destroyed:1;
-	/* ... mechanism specific data ... */
-};
+#include "auth-request.h"
 
 struct mech_module {
 	const char *mech_name;
@@ -82,33 +55,8 @@
 
 const string_t *auth_mechanisms_get_list(void);
 
-void mech_auth_success(struct auth_request *request,
-		       const void *data, size_t data_size);
-void mech_auth_fail(struct auth_request *request);
-void mech_auth_internal_failure(struct auth_request *request);
-
 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);
-
-struct auth_request_extra *
-auth_request_extra_begin(struct auth_request *request, const char *password);
-void auth_request_extra_next(struct auth_request_extra *extra,
-			     const char *name, const char *value);
-void auth_request_extra_finish(struct auth_request_extra *extra,
-			       const char *cache_key);
-
-const struct var_expand_table *
-auth_request_get_var_expand_table(const struct auth_request *auth_request,
-				  const char *(*escape_func)(const char *));
-
-const char *get_log_prefix(const struct auth_request *auth_request);
-
-void auth_failure_buf_flush(void);
-
 void mech_init(void);
 void mech_deinit(void);
 
--- a/src/auth/userdb.h	Fri Jan 07 20:25:10 2005 +0200
+++ b/src/auth/userdb.h	Fri Jan 07 20:51:10 2005 +0200
@@ -1,7 +1,7 @@
 #ifndef __USERDB_H
 #define __USERDB_H
 
-#include "mech.h"
+#include "auth-request.h"
 
 struct user_data {
 	const char *virtual_user;