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