dovecot-2.2: lib-ssl-iostream: Added support for TLS SNI, which ...

dovecot at dovecot.org dovecot at dovecot.org
Thu Apr 4 17:39:29 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/f4bac0352464
changeset: 16159:f4bac0352464
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Apr 04 17:39:17 2013 +0300
description:
lib-ssl-iostream: Added support for TLS SNI, which caused some API changes.

diffstat:

 src/doveadm/server-connection.c                 |   7 ++-
 src/lib-http/http-client-connection.c           |  11 +++---
 src/lib-imap-client/imapc-connection.c          |  10 +++---
 src/lib-master/master-service-ssl.c             |   4 +-
 src/lib-ssl-iostream/iostream-openssl-context.c |  28 +++++++++++++++++
 src/lib-ssl-iostream/iostream-openssl.c         |  40 ++++++++++++++++++------
 src/lib-ssl-iostream/iostream-openssl.h         |   5 +-
 src/lib-ssl-iostream/iostream-ssl-private.h     |   4 +-
 src/lib-ssl-iostream/iostream-ssl.c             |  33 ++++++++++++++++---
 src/lib-ssl-iostream/iostream-ssl.h             |  20 +++++++++---
 src/lib-storage/index/pop3c/pop3c-client.c      |   9 ++---
 11 files changed, 125 insertions(+), 46 deletions(-)

diffs (truncated from 417 to 300 lines):

diff -r 52efc1740e15 -r f4bac0352464 src/doveadm/server-connection.c
--- a/src/doveadm/server-connection.c	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/doveadm/server-connection.c	Thu Apr 04 17:39:17 2013 +0300
@@ -358,9 +358,10 @@
 	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, &error) < 0) {
+	if (io_stream_create_ssl_client(conn->server->ssl_ctx,
+					conn->server->name, &ssl_set,
+					&conn->input, &conn->output,
+					&conn->ssl_iostream, &error) < 0) {
 		i_error("Couldn't initialize SSL client: %s", error);
 		return -1;
 	}
diff -r 52efc1740e15 -r f4bac0352464 src/lib-http/http-client-connection.c
--- a/src/lib-http/http-client-connection.c	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-http/http-client-connection.c	Thu Apr 04 17:39:17 2013 +0300
@@ -667,7 +667,7 @@
 				const char **error_r)
 {
 	struct ssl_iostream_settings ssl_set;
-	const char *source, *error;
+	const char *error;
 
 	i_assert(conn->client->ssl_ctx != NULL);
 
@@ -681,11 +681,10 @@
 	if (conn->client->set.debug)
 		http_client_connection_debug(conn, "Starting SSL handshake");
 
-	source = t_strdup_printf
-		("connection %s: ", http_client_connection_label(conn));
-	if (io_stream_create_ssl(conn->client->ssl_ctx, source, &ssl_set,
-				 &conn->conn.input, &conn->conn.output,
-				 &conn->ssl_iostream, &error) < 0) {
+	if (io_stream_create_ssl_client(conn->client->ssl_ctx,
+					conn->peer->addr.https_name, &ssl_set,
+					&conn->conn.input, &conn->conn.output,
+					&conn->ssl_iostream, &error) < 0) {
 		*error_r = t_strdup_printf(
 			"Couldn't initialize SSL client for %s: %s",
 			conn->conn.name, error);
diff -r 52efc1740e15 -r f4bac0352464 src/lib-imap-client/imapc-connection.c
--- a/src/lib-imap-client/imapc-connection.c	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-imap-client/imapc-connection.c	Thu Apr 04 17:39:17 2013 +0300
@@ -1158,7 +1158,7 @@
 {
 	struct ssl_iostream_settings ssl_set;
 	struct stat st;
-	const char *source, *error;
+	const char *error;
 
 	if (conn->client->ssl_ctx == NULL) {
 		i_error("imapc(%s): No SSL context", conn->name);
@@ -1185,10 +1185,10 @@
 		conn->output = conn->raw_output;
 	}
 
-	source = t_strdup_printf("imapc(%s): ", conn->name);
-	if (io_stream_create_ssl(conn->client->ssl_ctx, source, &ssl_set,
-				 &conn->input, &conn->output,
-				 &conn->ssl_iostream, &error) < 0) {
+	if (io_stream_create_ssl_client(conn->client->ssl_ctx,
+					conn->client->set.host,
+					&ssl_set, &conn->input, &conn->output,
+					&conn->ssl_iostream, &error) < 0) {
 		i_error("imapc(%s): Couldn't initialize SSL client: %s",
 			conn->name, error);
 		return -1;
diff -r 52efc1740e15 -r f4bac0352464 src/lib-master/master-service-ssl.c
--- a/src/lib-master/master-service-ssl.c	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-master/master-service-ssl.c	Thu Apr 04 17:39:17 2013 +0300
@@ -82,8 +82,8 @@
 	ssl_set.verbose = set->verbose_ssl;
 	ssl_set.verify_remote_cert = set->ssl_verify_client_cert;
 
-	return io_stream_create_ssl(service->ssl_ctx, service->name, &ssl_set,
-				    input, output, ssl_iostream_r, error_r);
+	return io_stream_create_ssl_server(service->ssl_ctx, &ssl_set,
+					   input, output, ssl_iostream_r, error_r);
 }
 
 bool master_service_ssl_is_enabled(struct master_service *service)
diff -r 52efc1740e15 -r f4bac0352464 src/lib-ssl-iostream/iostream-openssl-context.c
--- a/src/lib-ssl-iostream/iostream-openssl-context.c	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-openssl-context.c	Thu Apr 04 17:39:17 2013 +0300
@@ -291,6 +291,25 @@
 	return new_set;
 }
 
+#ifdef HAVE_SSL_GET_SERVERNAME
+static int ssl_servername_callback(SSL *ssl, int *al ATTR_UNUSED,
+				   void *context ATTR_UNUSED)
+{
+	struct ssl_iostream *ssl_io;
+	const char *host;
+
+	ssl_io = SSL_get_ex_data(ssl, dovecot_ssl_extdata_index);
+	host = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+	if (SSL_get_servername_type(ssl) != -1) {
+		i_free(ssl_io->host);
+		ssl_io->host = i_strdup(host);
+	} else if (ssl_io->verbose) {
+		i_debug("SSL_get_servername() failed");
+	}
+	return SSL_TLSEXT_ERR_OK;
+}
+#endif
+
 static int
 ssl_iostream_context_set(struct ssl_iostream_context *ctx,
 			 const struct ssl_iostream_settings *set,
@@ -355,6 +374,15 @@
 			return -1;
 		}
 	}
+#ifdef HAVE_SSL_GET_SERVERNAME
+	if (!ctx->client_ctx) {
+		if (SSL_CTX_set_tlsext_servername_callback(ctx->ssl_ctx,
+					ssl_servername_callback) != 1) {
+			if (set->verbose)
+				i_debug("OpenSSL library doesn't support SNI");
+		}
+	}
+#endif
 	return 0;
 }
 
diff -r 52efc1740e15 -r f4bac0352464 src/lib-ssl-iostream/iostream-openssl.c
--- a/src/lib-ssl-iostream/iostream-openssl.c	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-openssl.c	Thu Apr 04 17:39:17 2013 +0300
@@ -15,16 +15,16 @@
 
 	ssl_io = SSL_get_ex_data(ssl, dovecot_ssl_extdata_index);
 	if ((where & SSL_CB_ALERT) != 0) {
-		i_warning("%s: SSL alert: where=0x%x, ret=%d: %s %s",
-			  ssl_io->source, where, ret,
+		i_warning("%sSSL alert: where=0x%x, ret=%d: %s %s",
+			  ssl_io->log_prefix, where, ret,
 			  SSL_alert_type_string_long(ret),
 			  SSL_alert_desc_string_long(ret));
 	} else if (ret == 0) {
-		i_warning("%s: SSL failed: where=0x%x: %s",
-			  ssl_io->source, where, SSL_state_string_long(ssl));
+		i_warning("%sSSL failed: where=0x%x: %s",
+			  ssl_io->log_prefix, where, SSL_state_string_long(ssl));
 	} else {
-		i_debug("%s: SSL: where=0x%x, ret=%d: %s",
-			ssl_io->source, where, ret,
+		i_debug("%sSSL: where=0x%x, ret=%d: %s",
+			ssl_io->log_prefix, where, ret,
 			SSL_state_string_long(ssl));
 	}
 }
@@ -128,7 +128,7 @@
 	if (set->verbose)
 		SSL_set_info_callback(ssl_io->ssl, openssl_info_callback);
 
-	if (set->cipher_list != NULL &&
+       if (set->cipher_list != NULL &&
 	    strcmp(ctx_set->cipher_list, set->cipher_list) != 0) {
 		if (!SSL_set_cipher_list(ssl_io->ssl, set->cipher_list)) {
 			*error_r = t_strdup_printf(
@@ -179,7 +179,7 @@
 }
 
 static int
-openssl_iostream_create(struct ssl_iostream_context *ctx, const char *source,
+openssl_iostream_create(struct ssl_iostream_context *ctx, const char *host,
 			const struct ssl_iostream_settings *set,
 			struct istream **input, struct ostream **output,
 			struct ssl_iostream **iostream_r,
@@ -215,10 +215,15 @@
 	ssl_io->bio_ext = bio_ext;
 	ssl_io->plain_input = *input;
 	ssl_io->plain_output = *output;
-	ssl_io->source = i_strdup(source);
+	ssl_io->host = i_strdup(host);
+	ssl_io->log_prefix = host == NULL ? i_strdup("") :
+		i_strdup_printf("%s: ", host);
 	/* bio_int will be freed by SSL_free() */
 	SSL_set_bio(ssl_io->ssl, bio_int, bio_int);
         SSL_set_ex_data(ssl_io->ssl, dovecot_ssl_extdata_index, ssl_io);
+#ifdef HAVE_SSL_GET_SERVERNAME
+	SSL_set_tlsext_host_name(ssl_io->ssl, host);
+#endif
 
 	if (openssl_iostream_set(ssl_io, set, error_r) < 0) {
 		openssl_iostream_free(ssl_io);
@@ -249,7 +254,8 @@
 	BIO_free(ssl_io->bio_ext);
 	SSL_free(ssl_io->ssl);
 	i_free(ssl_io->last_error);
-	i_free(ssl_io->source);
+	i_free(ssl_io->host);
+	i_free(ssl_io->log_prefix);
 	i_free(ssl_io);
 }
 
@@ -566,6 +572,13 @@
 	ssl_io->handshake_context = context;
 }
 
+static void openssl_iostream_set_log_prefix(struct ssl_iostream *ssl_io,
+					    const char *prefix)
+{
+	i_free(ssl_io->log_prefix);
+	ssl_io->log_prefix = i_strdup(prefix);
+}
+
 static bool openssl_iostream_is_handshaked(const struct ssl_iostream *ssl_io)
 {
 	return ssl_io->handshaked;
@@ -617,6 +630,11 @@
 	return *name == '\0' ? NULL : name;
 }
 
+static const char *openssl_iostream_get_server_name(struct ssl_iostream *ssl_io)
+{
+	return ssl_io->host;
+}
+
 static const char *
 openssl_iostream_get_security_string(struct ssl_iostream *ssl_io)
 {
@@ -666,11 +684,13 @@
 	openssl_iostream_handshake,
 	openssl_iostream_set_handshake_callback,
 
+	openssl_iostream_set_log_prefix,
 	openssl_iostream_is_handshaked,
 	openssl_iostream_has_valid_client_cert,
 	openssl_iostream_has_broken_client_cert,
 	openssl_iostream_cert_match_name,
 	openssl_iostream_get_peer_name,
+	openssl_iostream_get_server_name,
 	openssl_iostream_get_security_string,
 	openssl_iostream_get_last_error
 };
diff -r 52efc1740e15 -r f4bac0352464 src/lib-ssl-iostream/iostream-openssl.h
--- a/src/lib-ssl-iostream/iostream-openssl.h	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-openssl.h	Thu Apr 04 17:39:17 2013 +0300
@@ -21,8 +21,6 @@
 	int refcount;
 	struct ssl_iostream_context *ctx;
 
-	const struct ssl_iostream_settings *set;
-
 	SSL *ssl;
 	BIO *bio_ext;
 
@@ -30,8 +28,9 @@
 	struct ostream *plain_output;
 	struct ostream *ssl_output;
 
-	char *source;
+	char *host;
 	char *last_error;
+	char *log_prefix;
 	int plain_stream_errno;
 
 	/* copied settings */
diff -r 52efc1740e15 -r f4bac0352464 src/lib-ssl-iostream/iostream-ssl-private.h
--- a/src/lib-ssl-iostream/iostream-ssl-private.h	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-ssl-private.h	Thu Apr 04 17:39:17 2013 +0300
@@ -16,7 +16,7 @@
 	int (*context_import_params)(struct ssl_iostream_context *ctx,
 				     const buffer_t *input);
 
-	int (*create)(struct ssl_iostream_context *ctx, const char *source,
+	int (*create)(struct ssl_iostream_context *ctx, const char *host,
 		      const struct ssl_iostream_settings *set,
 		      struct istream **input, struct ostream **output,
 		      struct ssl_iostream **iostream_r, const char **error_r);
@@ -28,11 +28,13 @@
 				       ssl_iostream_handshake_callback_t *callback,
 				       void *context);
 
+	void (*set_log_prefix)(struct ssl_iostream *ssl_io, const char *prefix);
 	bool (*is_handshaked)(const struct ssl_iostream *ssl_io);
 	bool (*has_valid_client_cert)(const struct ssl_iostream *ssl_io);
 	bool (*has_broken_client_cert)(struct ssl_iostream *ssl_io);
 	int (*cert_match_name)(struct ssl_iostream *ssl_io, const char *name);
 	const char *(*get_peer_name)(struct ssl_iostream *ssl_io);
+	const char *(*get_server_name)(struct ssl_iostream *ssl_io);
 	const char *(*get_security_string)(struct ssl_iostream *ssl_io);
 	const char *(*get_last_error)(struct ssl_iostream *ssl_io);
 };
diff -r 52efc1740e15 -r f4bac0352464 src/lib-ssl-iostream/iostream-ssl.c
--- a/src/lib-ssl-iostream/iostream-ssl.c	Thu Apr 04 17:34:23 2013 +0300
+++ b/src/lib-ssl-iostream/iostream-ssl.c	Thu Apr 04 17:39:17 2013 +0300
@@ -92,13 +92,23 @@
 	return ssl_vfuncs->context_import_params(ctx, input);
 }
 
-int io_stream_create_ssl(struct ssl_iostream_context *ctx, const char *source,
-			 const struct ssl_iostream_settings *set,


More information about the dovecot-cvs mailing list