dovecot-2.1: auth: Implemented support for Postfix's "TCP map" s...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jan 9 16:35:34 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/f562bcaca215
changeset: 13912:f562bcaca215
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jan 09 16:35:22 2012 +0200
description:
auth: Implemented support for Postfix's "TCP map" sockets for user existence lookups.

diffstat:

 src/auth/Makefile.am               |    2 +
 src/auth/auth-postfix-connection.c |  248 +++++++++++++++++++++++++++++++++++++
 src/auth/auth-postfix-connection.h |   10 +
 src/auth/main.c                    |   12 +-
 4 files changed, 269 insertions(+), 3 deletions(-)

diffs (truncated from 342 to 300 lines):

diff -r fd8fc3b7615e -r f562bcaca215 src/auth/Makefile.am
--- a/src/auth/Makefile.am	Mon Jan 09 16:29:37 2012 +0200
+++ b/src/auth/Makefile.am	Mon Jan 09 16:35:22 2012 +0200
@@ -60,6 +60,7 @@
 	auth-cache.c \
 	auth-client-connection.c \
 	auth-master-connection.c \
+	auth-postfix-connection.c \
 	mech-otp-skey-common.c \
 	mech-plain-common.c \
 	auth-penalty.c \
@@ -121,6 +122,7 @@
 	auth-client-connection.h \
 	auth-common.h \
 	auth-master-connection.h \
+	auth-postfix-connection.h \
 	mech-otp-skey-common.h \
 	mech-plain-common.h \
 	auth-penalty.h \
diff -r fd8fc3b7615e -r f562bcaca215 src/auth/auth-postfix-connection.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/auth-postfix-connection.c	Mon Jan 09 16:35:22 2012 +0200
@@ -0,0 +1,248 @@
+/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
+
+#include "auth-common.h"
+#include "ioloop.h"
+#include "network.h"
+#include "istream.h"
+#include "ostream.h"
+#include "llist.h"
+#include "str.h"
+#include "strescape.h"
+#include "str-sanitize.h"
+#include "master-service.h"
+#include "userdb.h"
+#include "auth-postfix-connection.h"
+
+#include <unistd.h>
+
+#define MAX_INBUF_SIZE 1024
+#define MAX_OUTBUF_SIZE (1024*50)
+
+struct auth_postfix_connection {
+	struct auth_postfix_connection *prev, *next;
+	struct auth *auth;
+	int refcount;
+
+	int fd;
+	char *path;
+	struct istream *input;
+	struct ostream *output;
+	struct io *io;
+
+	unsigned int destroyed:1;
+};
+
+static void postfix_input(struct auth_postfix_connection *conn);
+static void auth_postfix_connection_ref(struct auth_postfix_connection *conn);
+static void auth_postfix_connection_destroy(struct auth_postfix_connection **_conn);
+static void auth_postfix_connection_unref(struct auth_postfix_connection **_conn);
+
+static struct auth_postfix_connection *auth_postfix_connections;
+
+static int
+postfix_input_auth_request(struct auth_postfix_connection *conn,
+			   const char *username,
+			   struct auth_request **request_r, const char **error_r)
+{
+	struct auth_request *auth_request;
+
+	auth_request = auth_request_new_dummy();
+	auth_request->id = 1;
+	auth_request->context = conn;
+	auth_postfix_connection_ref(conn);
+
+	if (!auth_request_set_username(auth_request, username, error_r)) {
+		*request_r = auth_request;
+		return FALSE;
+	}
+	(void)auth_request_import_info(auth_request, "service", "postfix");
+
+	auth_request_init(auth_request);
+	*request_r = auth_request;
+	return TRUE;
+}
+
+static void
+user_callback(enum userdb_result result, struct auth_request *auth_request)
+{
+	struct auth_postfix_connection *conn = auth_request->context;
+	struct auth_stream_reply *reply = auth_request->userdb_reply;
+	string_t *str;
+	const char *value;
+
+	if (auth_request->userdb_lookup_failed)
+		result = USERDB_RESULT_INTERNAL_FAILURE;
+
+	str = t_str_new(128);
+	switch (result) {
+	case USERDB_RESULT_INTERNAL_FAILURE:
+		if (auth_request->userdb_lookup_failed)
+			value = auth_stream_reply_find(reply, "reason");
+		else
+			value = NULL;
+		str_printfa(str, "400 %s",
+			    value != NULL ? value: "Internal failure");
+		break;
+	case USERDB_RESULT_USER_UNKNOWN:
+		str_append(str, "500 User not found");
+		break;
+	case USERDB_RESULT_OK:
+		str_append(str, "200 1");
+		break;
+	}
+
+	if (conn->auth->set->debug)
+		i_debug("postfix out: %s", str_c(str));
+
+	str_append_c(str, '\n');
+	(void)o_stream_send(conn->output, str_data(str), str_len(str));
+
+	i_assert(conn->io == NULL);
+	if (!conn->destroyed)
+		conn->io = io_add(conn->fd, IO_READ, postfix_input, conn);
+
+	auth_request_unref(&auth_request);
+	auth_postfix_connection_unref(&conn);
+}
+
+static bool
+postfix_input_user(struct auth_postfix_connection *conn, const char *username)
+{
+	struct auth_request *auth_request;
+	const char *error;
+
+	io_remove(&conn->io);
+	if (!postfix_input_auth_request(conn, username,
+					&auth_request, &error)) {
+		auth_request_log_info(auth_request, "postfix", "%s", error);
+		user_callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
+	} else {
+		auth_request_set_state(auth_request, AUTH_REQUEST_STATE_USERDB);
+		auth_request_lookup_user(auth_request, user_callback);
+	}
+	return TRUE;
+}
+
+static bool
+auth_postfix_input_line(struct auth_postfix_connection *conn, const char *line)
+{
+	if (conn->auth->set->debug)
+		i_debug("postfix in: %s", line);
+
+	if (strncasecmp(line, "get ", 4) == 0)
+		return postfix_input_user(conn, line + 4);
+
+	i_error("BUG: Unknown command in postfix socket: %s",
+		str_sanitize(line, 80));
+	return FALSE;
+}
+
+static void postfix_input(struct auth_postfix_connection *conn)
+{
+ 	char *line;
+	bool ret;
+
+	switch (i_stream_read(conn->input)) {
+	case 0:
+		return;
+	case -1:
+		/* disconnected */
+                auth_postfix_connection_destroy(&conn);
+		return;
+	case -2:
+		/* buffer full */
+		i_error("BUG: Postfix sent us more than %d bytes",
+			(int)MAX_INBUF_SIZE);
+                auth_postfix_connection_destroy(&conn);
+		return;
+	}
+
+	while ((line = i_stream_next_line(conn->input)) != NULL) {
+		T_BEGIN {
+			ret = auth_postfix_input_line(conn, line);
+		} T_END;
+		if (!ret) {
+			auth_postfix_connection_destroy(&conn);
+			return;
+		}
+	}
+}
+
+struct auth_postfix_connection *
+auth_postfix_connection_create(struct auth *auth, int fd)
+{
+	struct auth_postfix_connection *conn;
+
+	conn = i_new(struct auth_postfix_connection, 1);
+	conn->refcount = 1;
+	conn->fd = fd;
+	conn->auth = auth;
+	conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
+	conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
+	conn->io = io_add(fd, IO_READ, postfix_input, conn);
+	DLLIST_PREPEND(&auth_postfix_connections, conn);
+	return conn;
+}
+
+static void
+auth_postfix_connection_destroy(struct auth_postfix_connection **_conn)
+{
+        struct auth_postfix_connection *conn = *_conn;
+
+	*_conn = NULL;
+	if (conn->destroyed)
+		return;
+	conn->destroyed = TRUE;
+
+	DLLIST_REMOVE(&auth_postfix_connections, conn);
+
+	if (conn->input != NULL)
+		i_stream_close(conn->input);
+	if (conn->output != NULL)
+		o_stream_close(conn->output);
+	if (conn->io != NULL)
+		io_remove(&conn->io);
+	if (conn->fd != -1) {
+		if (close(conn->fd) < 0)
+			i_error("close(%s): %m", conn->path);
+		conn->fd = -1;
+	}
+
+	master_service_client_connection_destroyed(master_service);
+	auth_postfix_connection_unref(&conn);
+}
+
+static void auth_postfix_connection_ref(struct auth_postfix_connection *conn)
+{
+	i_assert(conn->refcount > 0);
+
+	conn->refcount++;
+}
+
+static void
+auth_postfix_connection_unref(struct auth_postfix_connection **_conn)
+{
+	struct auth_postfix_connection *conn = *_conn;
+
+	*_conn = NULL;
+	i_assert(conn->refcount > 0);
+
+	if (--conn->refcount > 0)
+		return;
+
+	if (conn->input != NULL)
+		i_stream_unref(&conn->input);
+	if (conn->output != NULL)
+		o_stream_unref(&conn->output);
+	i_free(conn);
+}
+
+void auth_postfix_connections_destroy_all(void)
+{
+	struct auth_postfix_connection *conn;
+
+	while (auth_postfix_connections != NULL) {
+		conn = auth_postfix_connections;
+		auth_postfix_connection_destroy(&conn);
+	}
+}
diff -r fd8fc3b7615e -r f562bcaca215 src/auth/auth-postfix-connection.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/auth/auth-postfix-connection.h	Mon Jan 09 16:35:22 2012 +0200
@@ -0,0 +1,10 @@
+#ifndef AUTH_POSTFIX_CONNECTION_H
+#define AUTH_POSTFIX_CONNECTION_H
+
+struct auth_postfix_connection *
+auth_postfix_connection_create(struct auth *auth, int fd);
+
+void auth_postfix_connections_destroy_all(void);
+
+#endif
+
diff -r fd8fc3b7615e -r f562bcaca215 src/auth/main.c
--- a/src/auth/main.c	Mon Jan 09 16:29:37 2012 +0200
+++ b/src/auth/main.c	Mon Jan 09 16:35:22 2012 +0200
@@ -26,6 +26,7 @@
 #include "auth-worker-client.h"
 #include "auth-master-connection.h"
 #include "auth-client-connection.h"
+#include "auth-postfix-connection.h"
 
 #include <unistd.h>
 #include <sys/stat.h>
@@ -37,7 +38,8 @@
 	AUTH_SOCKET_CLIENT,
 	AUTH_SOCKET_LOGIN_CLIENT,
 	AUTH_SOCKET_MASTER,


More information about the dovecot-cvs mailing list