dovecot-2.2: dsync: Added tcps (TCP+SSL) target.

dovecot at dovecot.org dovecot at dovecot.org
Mon Feb 25 15:55:26 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/95ecdd9e13bf
changeset: 15934:95ecdd9e13bf
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Feb 25 15:55:06 2013 +0200
description:
dsync: Added tcps (TCP+SSL) target.

diffstat:

 src/doveadm/doveadm-server.h      |   1 +
 src/doveadm/doveadm-settings.c    |   6 ++
 src/doveadm/doveadm-settings.h    |   3 +
 src/doveadm/dsync/Makefile.am     |   1 +
 src/doveadm/dsync/doveadm-dsync.c |  40 +++++++++++++++++-
 src/doveadm/server-connection.c   |  84 ++++++++++++++++++++++++++++++++++++--
 src/doveadm/server-connection.h   |   4 +-
 7 files changed, 129 insertions(+), 10 deletions(-)

diffs (truncated from 317 to 300 lines):

diff -r 9a7680fe65ce -r 95ecdd9e13bf src/doveadm/doveadm-server.h
--- a/src/doveadm/doveadm-server.h	Mon Feb 25 15:54:01 2013 +0200
+++ b/src/doveadm/doveadm-server.h	Mon Feb 25 15:55:06 2013 +0200
@@ -8,6 +8,7 @@
 
 struct doveadm_server {
 	const char *name;
+	struct ssl_iostream_context *ssl_ctx;
 
 	ARRAY(struct server_connection *) connections;
 	ARRAY_TYPE(string) queue;
diff -r 9a7680fe65ce -r 95ecdd9e13bf src/doveadm/doveadm-settings.c
--- a/src/doveadm/doveadm-settings.c	Mon Feb 25 15:54:01 2013 +0200
+++ b/src/doveadm/doveadm-settings.c	Mon Feb 25 15:55:06 2013 +0200
@@ -65,6 +65,9 @@
 	DEF(SET_STR, dsync_alt_char),
 	DEF(SET_STR, dsync_remote_cmd),
 
+	DEF(SET_STR, ssl_client_ca_dir),
+	DEF(SET_STR, ssl_crypto_device),
+
 	{ SET_STRLIST, "plugin", offsetof(struct doveadm_settings, plugin_envs), NULL },
 
 	SETTING_DEFINE_LIST_END
@@ -83,6 +86,9 @@
 	.dsync_alt_char = "_",
 	.dsync_remote_cmd = "ssh -l%{login} %{host} doveadm dsync-server -u%u",
 
+	.ssl_client_ca_dir = "",
+	.ssl_crypto_device = "",
+
 	.plugin_envs = ARRAY_INIT
 };
 
diff -r 9a7680fe65ce -r 95ecdd9e13bf src/doveadm/doveadm-settings.h
--- a/src/doveadm/doveadm-settings.h	Mon Feb 25 15:54:01 2013 +0200
+++ b/src/doveadm/doveadm-settings.h	Mon Feb 25 15:55:06 2013 +0200
@@ -14,6 +14,9 @@
 	const char *dsync_alt_char;
 	const char *dsync_remote_cmd;
 
+	const char *ssl_client_ca_dir;
+	const char *ssl_crypto_device;
+
 	ARRAY(const char *) plugin_envs;
 };
 
diff -r 9a7680fe65ce -r 95ecdd9e13bf src/doveadm/dsync/Makefile.am
--- a/src/doveadm/dsync/Makefile.am	Mon Feb 25 15:54:01 2013 +0200
+++ b/src/doveadm/dsync/Makefile.am	Mon Feb 25 15:55:06 2013 +0200
@@ -4,6 +4,7 @@
 	-I$(top_srcdir)/src/lib \
 	-I$(top_srcdir)/src/lib-test \
 	-I$(top_srcdir)/src/lib-settings \
+	-I$(top_srcdir)/src/lib-ssl-iostream \
 	-I$(top_srcdir)/src/lib-master \
 	-I$(top_srcdir)/src/lib-mail \
 	-I$(top_srcdir)/src/lib-imap \
diff -r 9a7680fe65ce -r 95ecdd9e13bf src/doveadm/dsync/doveadm-dsync.c
--- a/src/doveadm/dsync/doveadm-dsync.c	Mon Feb 25 15:54:01 2013 +0200
+++ b/src/doveadm/dsync/doveadm-dsync.c	Mon Feb 25 15:55:06 2013 +0200
@@ -7,6 +7,7 @@
 #include "fd-set-nonblock.h"
 #include "istream.h"
 #include "ostream.h"
+#include "iostream-ssl.h"
 #include "iostream-rawlog.h"
 #include "write-full.h"
 #include "str.h"
@@ -14,6 +15,7 @@
 #include "var-expand.h"
 #include "settings-parser.h"
 #include "master-service.h"
+#include "master-service-ssl-settings.h"
 #include "mail-storage-service.h"
 #include "mail-user.h"
 #include "mail-namespace.h"
@@ -58,6 +60,9 @@
 	struct istream *input, *err_stream;
 	struct ostream *output;
 
+	struct ssl_iostream_context *ssl_ctx;
+	struct ssl_iostream *ssl_iostream;
+
 	enum dsync_run_type run_type;
 	struct server_connection *tcp_conn;
 	const char *error;
@@ -489,6 +494,10 @@
 	dsync_ibc_deinit(&ibc);
 	if (ibc2 != NULL)
 		dsync_ibc_deinit(&ibc2);
+	if (ctx->ssl_iostream != NULL)
+		ssl_iostream_destroy(&ctx->ssl_iostream);
+	if (ctx->ssl_ctx != NULL)
+		ssl_iostream_context_deinit(&ctx->ssl_ctx);
 	if (ctx->fd_in != -1) {
 		if (ctx->fd_out != ctx->fd_in)
 			i_close_fd(&ctx->fd_out);
@@ -529,7 +538,7 @@
 		break;
 	case SERVER_CMD_REPLY_OK:
 		server_connection_extract(ctx->tcp_conn, &ctx->input,
-					  &ctx->output);
+					  &ctx->output, &ctx->ssl_iostream);
 		ctx->fd_in = ctx->fd_out = -1;
 		break;
 	case SERVER_CMD_REPLY_INTERNAL_FAILURE:
@@ -541,8 +550,21 @@
 	io_loop_stop(current_ioloop);
 }
 
+static int dsync_init_ssl_ctx(struct dsync_cmd_context *ctx)
+{
+	struct ssl_iostream_settings ssl_set;
+
+	memset(&ssl_set, 0, sizeof(ssl_set));
+	ssl_set.ca_dir = doveadm_settings->ssl_client_ca_dir;
+	ssl_set.verify_remote_cert = TRUE;
+	ssl_set.crypto_device = doveadm_settings->ssl_crypto_device;
+
+	return ssl_iostream_context_init_client("doveadm", &ssl_set,
+						&ctx->ssl_ctx);
+}
+
 static int dsync_connect_tcp(struct dsync_cmd_context *ctx, const char *target,
-			     const char **error_r)
+			     bool ssl, const char **error_r)
 {
 	struct doveadm_server *server;
 	struct server_connection *conn;
@@ -551,6 +573,13 @@
 
 	server = p_new(ctx->ctx.pool, struct doveadm_server, 1);
 	server->name = p_strdup(ctx->ctx.pool, target);
+	if (ssl) {
+		if (dsync_init_ssl_ctx(ctx) < 0) {
+			*error_r = "Couldn't initialize SSL context";
+			return -1;
+		}
+		server->ssl_ctx = ctx->ssl_ctx;
+	}
 	p_array_init(&server->connections, ctx->ctx.pool, 1);
 	p_array_init(&server->queue, ctx->ctx.pool, 1);
 
@@ -596,7 +625,12 @@
 	if (strncmp(location, "tcp:", 4) == 0) {
 		/* TCP connection to remote dsync */
 		ctx->remote_name = location+4;
-		return dsync_connect_tcp(ctx, ctx->remote_name, error_r);
+		return dsync_connect_tcp(ctx, ctx->remote_name, FALSE, error_r);
+	}
+	if (strncmp(location, "tcps:", 5) == 0) {
+		/* TCP+SSL connection to remote dsync */
+		ctx->remote_name = location+5;
+		return dsync_connect_tcp(ctx, ctx->remote_name, TRUE, error_r);
 	}
 
 	if (strncmp(location, "remote:", 7) == 0) {
diff -r 9a7680fe65ce -r 95ecdd9e13bf src/doveadm/server-connection.c
--- a/src/doveadm/server-connection.c	Mon Feb 25 15:54:01 2013 +0200
+++ b/src/doveadm/server-connection.c	Mon Feb 25 15:55:06 2013 +0200
@@ -9,6 +9,7 @@
 #include "ostream.h"
 #include "str.h"
 #include "strescape.h"
+#include "iostream-ssl.h"
 #include "master-service.h"
 #include "master-service-settings.h"
 #include "settings-parser.h"
@@ -38,6 +39,7 @@
 	struct io *io;
 	struct istream *input;
 	struct ostream *output;
+	struct ssl_iostream *ssl_iostream;
 
 	const char *delayed_cmd;
 	server_cmd_callback_t *callback;
@@ -313,6 +315,67 @@
 	return 0;
 }
 
+static int server_connection_ssl_handshaked(void *context)
+{
+	struct server_connection *conn = context;
+	const char *host, *p;
+
+	host = conn->server->name;
+	p = strrchr(host, ':');
+	if (p != NULL)
+		host = t_strdup_until(host, p);
+
+	if (!ssl_iostream_has_valid_client_cert(conn->ssl_iostream)) {
+		if (!ssl_iostream_has_broken_client_cert(conn->ssl_iostream)) {
+			i_error("%s: SSL certificate not received",
+				conn->server->name);
+		} else {
+			i_error("%s: Received invalid SSL certificate",
+				conn->server->name);
+		}
+	} else if (ssl_iostream_cert_match_name(conn->ssl_iostream, host) < 0) {
+		i_error("%s: SSL certificate doesn't match host name",
+			conn->server->name);
+	} else {
+		if (doveadm_debug) {
+			i_debug("%s: SSL handshake successful",
+				conn->server->name);
+		}
+		return 0;
+	}
+	i_stream_close(conn->input);
+	return -1;
+}
+
+static int server_connection_init_ssl(struct server_connection *conn)
+{
+	struct ssl_iostream_settings ssl_set;
+
+	if (conn->server->ssl_ctx == NULL)
+		return 0;
+
+	memset(&ssl_set, 0, sizeof(ssl_set));
+	ssl_set.verify_remote_cert = TRUE;
+	ssl_set.require_valid_cert = TRUE;
+	ssl_set.verbose_invalid_cert = TRUE;
+
+	if (io_stream_create_ssl(conn->server->ssl_ctx, "doveadm", &ssl_set,
+				 &conn->input, &conn->output,
+				 &conn->ssl_iostream) < 0) {
+		i_error("Couldn't initialize SSL client");
+		return -1;
+	}
+	ssl_iostream_set_handshake_callback(conn->ssl_iostream,
+					    server_connection_ssl_handshaked,
+					    conn);
+	if (ssl_iostream_handshake(conn->ssl_iostream) < 0) {
+		i_error("SSL handshake failed: %s",
+			ssl_iostream_get_last_error(conn->ssl_iostream));
+		return -1;
+	}
+	return 0;
+}
+
 int server_connection_create(struct doveadm_server *server,
 			     struct server_connection **conn_r)
 {
@@ -330,15 +393,19 @@
 	conn->io = io_add(conn->fd, IO_READ, server_connection_input, conn);
 	conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE, FALSE);
 	conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE);
+
+	array_append(&conn->server->connections, &conn, 1);
+
+	if (server_connection_read_settings(conn) < 0 ||
+	    server_connection_init_ssl(conn) < 0) {
+		server_connection_destroy(&conn);
+		return -1;
+	}
+
 	o_stream_set_no_error_handling(conn->output, TRUE);
 	conn->state = SERVER_REPLY_STATE_DONE;
 	o_stream_nsend_str(conn->output, DOVEADM_SERVER_HANDSHAKE);
 
-	array_append(&conn->server->connections, &conn, 1);
-	if (server_connection_read_settings(conn) < 0) {
-		server_connection_destroy(&conn);
-		return -1;
-	}
 	*conn_r = conn;
 	return 0;
 }
@@ -370,6 +437,8 @@
 		i_stream_destroy(&conn->input);
 	if (conn->output != NULL)
 		o_stream_destroy(&conn->output);
+	if (conn->ssl_iostream != NULL)
+		ssl_iostream_unref(&conn->ssl_iostream);
 	if (conn->io != NULL)
 		io_remove(&conn->io);
 	if (conn->fd != -1) {
@@ -406,13 +475,16 @@
 
 void server_connection_extract(struct server_connection *conn,
 			       struct istream **istream_r,
-			       struct ostream **ostream_r)
+			       struct ostream **ostream_r,
+			       struct ssl_iostream **ssl_iostream_r)
 {
 	*istream_r = conn->input;
 	*ostream_r = conn->output;
+	*ssl_iostream_r = conn->ssl_iostream;
 
 	conn->input = NULL;
 	conn->output = NULL;
+	conn->ssl_iostream = NULL;
 	if (conn->io != NULL)
 		io_remove(&conn->io);
 	conn->fd = -1;
diff -r 9a7680fe65ce -r 95ecdd9e13bf src/doveadm/server-connection.h
--- a/src/doveadm/server-connection.h	Mon Feb 25 15:54:01 2013 +0200
+++ b/src/doveadm/server-connection.h	Mon Feb 25 15:55:06 2013 +0200


More information about the dovecot-cvs mailing list