dovecot-2.2: director: Added "authreply" socket type.

dovecot at dovecot.org dovecot at dovecot.org
Wed May 13 13:24:26 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/52cdf321fa07
changeset: 18675:52cdf321fa07
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 13 16:22:27 2015 +0300
description:
director: Added "authreply" socket type.
This allows defining a socket, which receives auth replies. Director then
adds the "host" field to it if it's missing and returns back the original
string. The idea is that eventually a director ring could be running
independently from Dovecot proxies.

diffstat:

 src/director/login-connection.c |  71 +++++++++++++++++++++++++++++++++++-----
 src/director/login-connection.h |   9 ++++-
 src/director/main.c             |  12 ++++++-
 3 files changed, 81 insertions(+), 11 deletions(-)

diffs (208 lines):

diff -r c97d10467b62 -r 52cdf321fa07 src/director/login-connection.c
--- a/src/director/login-connection.c	Wed May 13 15:59:48 2015 +0300
+++ b/src/director/login-connection.c	Wed May 13 16:22:27 2015 +0300
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "net.h"
+#include "istream.h"
 #include "ostream.h"
 #include "llist.h"
 #include "master-service.h"
@@ -13,19 +14,24 @@
 
 #include <unistd.h>
 
+#define AUTHREPLY_PROTOCOL_MAJOR_VERSION 1
+#define AUTHREPLY_PROTOCOL_MINOR_VERSION 0
+
 struct login_connection {
 	struct login_connection *prev, *next;
 
 	int refcount;
+	enum login_connection_type type;
 
 	int fd;
 	struct io *io;
+	struct istream *input;
 	struct ostream *output;
 	struct auth_connection *auth;
 	struct director *dir;
 
+	unsigned int handshaked:1;
 	unsigned int destroyed:1;
-	unsigned int userdb:1;
 };
 
 struct login_host_request {
@@ -40,6 +46,7 @@
 
 static struct login_connection *login_connections;
 
+static void auth_input_line(const char *line, void *context);
 static void login_connection_unref(struct login_connection **_conn);
 
 static void login_connection_input(struct login_connection *conn)
@@ -63,6 +70,33 @@
 	o_stream_nsend(output, buf, ret);
 }
 
+static void login_connection_authreply_input(struct login_connection *conn)
+{
+	const char *line;
+
+	while ((line = i_stream_read_next_line(conn->input)) != NULL) T_BEGIN {
+		if (!conn->handshaked) {
+			if (!version_string_verify(line, "director-authreply-client",
+						   AUTHREPLY_PROTOCOL_MAJOR_VERSION)) {
+				i_error("authreply client sent invalid handshake: %s", line);
+				login_connection_deinit(&conn);
+				return;
+			}
+			conn->handshaked = TRUE;
+		} else {
+			auth_input_line(line, conn);
+		}
+	} T_END;
+	if (conn->input->eof) {
+		if (conn->input->stream_errno != 0 &&
+		    conn->input->stream_errno != ECONNRESET) {
+			i_error("read(authreply connection) failed: %s",
+				i_stream_get_error(conn->input));
+		}
+		login_connection_deinit(&conn);
+	}
+}
+
 static void
 login_connection_send_line(struct login_connection *conn, const char *line)
 {
@@ -138,9 +172,11 @@
 		login_connection_deinit(&conn);
 		return;
 	}
-	if (!conn->userdb && strncmp(line, "OK\t", 3) == 0)
+	if (conn->type != LOGIN_CONNECTION_TYPE_USERDB &&
+	    strncmp(line, "OK\t", 3) == 0)
 		line_params = line + 3;
-	else if (conn->userdb && strncmp(line, "PASS\t", 5) == 0)
+	else if (conn->type == LOGIN_CONNECTION_TYPE_USERDB &&
+		 strncmp(line, "PASS\t", 5) == 0)
 		line_params = line + 5;
 	else {
 		login_connection_send_line(conn, line);
@@ -208,21 +244,35 @@
 
 struct login_connection *
 login_connection_init(struct director *dir, int fd,
-		      struct auth_connection *auth, bool userdb)
+		      struct auth_connection *auth,
+		      enum login_connection_type type)
 {
 	struct login_connection *conn;
 
 	conn = i_new(struct login_connection, 1);
 	conn->refcount = 1;
 	conn->fd = fd;
-	conn->auth = auth;
 	conn->dir = dir;
 	conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE);
 	o_stream_set_no_error_handling(conn->output, TRUE);
-	conn->io = io_add(conn->fd, IO_READ, login_connection_input, conn);
-	conn->userdb = userdb;
+	if (type != LOGIN_CONNECTION_TYPE_AUTHREPLY) {
+		i_assert(auth != NULL);
+		conn->auth = auth;
+		conn->io = io_add(conn->fd, IO_READ,
+				  login_connection_input, conn);
+		auth_connection_set_callback(conn->auth, auth_input_line, conn);
+	} else {
+		i_assert(auth == NULL);
+		conn->input = i_stream_create_fd(conn->fd, IO_BLOCK_SIZE, FALSE);
+		conn->io = io_add(conn->fd, IO_READ,
+				  login_connection_authreply_input, conn);
+		o_stream_nsend_str(conn->output, t_strdup_printf(
+			"VERSION\tdirector-authreply-server\t%d\t%d\n",
+			AUTHREPLY_PROTOCOL_MAJOR_VERSION,
+			AUTHREPLY_PROTOCOL_MINOR_VERSION));
+	}
+	conn->type = type;
 
-	auth_connection_set_callback(conn->auth, auth_input_line, conn);
 	DLLIST_PREPEND(&login_connections, conn);
 	return conn;
 }
@@ -239,12 +289,15 @@
 
 	DLLIST_REMOVE(&login_connections, conn);
 	io_remove(&conn->io);
+	if (conn->input != NULL)
+		i_stream_destroy(&conn->input);
 	o_stream_destroy(&conn->output);
 	if (close(conn->fd) < 0)
 		i_error("close(login connection) failed: %m");
 	conn->fd = -1;
 
-	auth_connection_deinit(&conn->auth);
+	if (conn->auth != NULL)
+		auth_connection_deinit(&conn->auth);
 	login_connection_unref(&conn);
 
 	master_service_client_connection_destroyed(master_service);
diff -r c97d10467b62 -r 52cdf321fa07 src/director/login-connection.h
--- a/src/director/login-connection.h	Wed May 13 15:59:48 2015 +0300
+++ b/src/director/login-connection.h	Wed May 13 16:22:27 2015 +0300
@@ -3,9 +3,16 @@
 
 struct director;
 
+enum login_connection_type {
+	LOGIN_CONNECTION_TYPE_AUTH,
+	LOGIN_CONNECTION_TYPE_USERDB,
+	LOGIN_CONNECTION_TYPE_AUTHREPLY
+};
+
 struct login_connection *
 login_connection_init(struct director *dir, int fd,
-		      struct auth_connection *auth, bool userdb);
+		      struct auth_connection *auth,
+		      enum login_connection_type type);
 void login_connection_deinit(struct login_connection **conn);
 
 void login_connections_deinit(void);
diff -r c97d10467b62 -r 52cdf321fa07 src/director/main.c
--- a/src/director/main.c	Wed May 13 15:59:48 2015 +0300
+++ b/src/director/main.c	Wed May 13 16:22:27 2015 +0300
@@ -30,6 +30,7 @@
 	DIRECTOR_SOCKET_TYPE_UNKNOWN = 0,
 	DIRECTOR_SOCKET_TYPE_AUTH,
 	DIRECTOR_SOCKET_TYPE_USERDB,
+	DIRECTOR_SOCKET_TYPE_AUTHREPLY,
 	DIRECTOR_SOCKET_TYPE_RING,
 	DIRECTOR_SOCKET_TYPE_DOVEADM
 };
@@ -81,6 +82,8 @@
 		return DIRECTOR_SOCKET_TYPE_AUTH;
 	else if (strcmp(suffix, "userdb") == 0)
 		return DIRECTOR_SOCKET_TYPE_USERDB;
+	else if (strcmp(suffix, "authreply") == 0)
+		return DIRECTOR_SOCKET_TYPE_AUTHREPLY;
 	else if (strcmp(suffix, "ring") == 0)
 		return DIRECTOR_SOCKET_TYPE_RING;
 	else if (strcmp(suffix, "admin") == 0 ||
@@ -188,7 +191,14 @@
 			break;
 		}
 		master_service_client_connection_accept(conn);
-		(void)login_connection_init(director, conn->fd, auth, userdb);
+		(void)login_connection_init(director, conn->fd, auth,
+			userdb ? LOGIN_CONNECTION_TYPE_USERDB :
+			LOGIN_CONNECTION_TYPE_AUTH);
+		break;
+	case DIRECTOR_SOCKET_TYPE_AUTHREPLY:
+		master_service_client_connection_accept(conn);
+		(void)login_connection_init(director, conn->fd, NULL,
+			LOGIN_CONNECTION_TYPE_AUTHREPLY);
 		break;
 	case DIRECTOR_SOCKET_TYPE_RING:
 		if (director_client_connected(conn->fd, &conn->remote_ip) == 0)


More information about the dovecot-cvs mailing list