Mercurial > dovecot > core-2.2
changeset 16159:f4bac0352464
lib-ssl-iostream: Added support for TLS SNI, which caused some API changes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 04 Apr 2013 17:39:17 +0300 |
parents | 52efc1740e15 |
children | 41c10ddda867 |
files | src/doveadm/server-connection.c src/lib-http/http-client-connection.c src/lib-imap-client/imapc-connection.c src/lib-master/master-service-ssl.c src/lib-ssl-iostream/iostream-openssl-context.c src/lib-ssl-iostream/iostream-openssl.c src/lib-ssl-iostream/iostream-openssl.h src/lib-ssl-iostream/iostream-ssl-private.h src/lib-ssl-iostream/iostream-ssl.c src/lib-ssl-iostream/iostream-ssl.h src/lib-storage/index/pop3c/pop3c-client.c |
diffstat | 11 files changed, 125 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- 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; }
--- 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);
--- 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;
--- 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)
--- 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; }
--- 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 };
--- 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 */
--- 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); };
--- 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, - struct istream **input, struct ostream **output, - struct ssl_iostream **iostream_r, - const char **error_r) +int io_stream_create_ssl_client(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) { - return ssl_vfuncs->create(ctx, source, set, input, output, + return ssl_vfuncs->create(ctx, host, set, input, output, + iostream_r, error_r); +} + +int io_stream_create_ssl_server(struct ssl_iostream_context *ctx, + const struct ssl_iostream_settings *set, + struct istream **input, struct ostream **output, + struct ssl_iostream **iostream_r, + const char **error_r) +{ + return ssl_vfuncs->create(ctx, NULL, set, input, output, iostream_r, error_r); } @@ -118,6 +128,12 @@ ssl_vfuncs->destroy(ssl_io); } +void ssl_iostream_set_log_prefix(struct ssl_iostream *ssl_io, + const char *prefix) +{ + ssl_vfuncs->set_log_prefix(ssl_io, prefix); +} + int ssl_iostream_handshake(struct ssl_iostream *ssl_io) { return ssl_vfuncs->handshake(ssl_io); @@ -155,6 +171,11 @@ return ssl_vfuncs->get_peer_name(ssl_io); } +const char *ssl_iostream_get_server_name(struct ssl_iostream *ssl_io) +{ + return ssl_vfuncs->get_server_name(ssl_io); +} + const char *ssl_iostream_get_security_string(struct ssl_iostream *ssl_io) { return ssl_vfuncs->get_security_string(ssl_io);
--- a/src/lib-ssl-iostream/iostream-ssl.h Thu Apr 04 17:34:23 2013 +0300 +++ b/src/lib-ssl-iostream/iostream-ssl.h Thu Apr 04 17:39:17 2013 +0300 @@ -24,16 +24,25 @@ typedef int ssl_iostream_handshake_callback_t(const char **error_r, void *context); -int io_stream_create_ssl(struct ssl_iostream_context *ctx, const char *source, - const struct ssl_iostream_settings *set, - struct istream **input, struct ostream **output, - struct ssl_iostream **iostream_r, - const char **error_r); +int io_stream_create_ssl_client(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); +int io_stream_create_ssl_server(struct ssl_iostream_context *ctx, + const struct ssl_iostream_settings *set, + struct istream **input, struct ostream **output, + struct ssl_iostream **iostream_r, + const char **error_r); /* returned input and output streams must also be unreferenced */ void ssl_iostream_unref(struct ssl_iostream **ssl_io); /* shutdown SSL connection and unreference ssl iostream */ void ssl_iostream_destroy(struct ssl_iostream **ssl_io); +/* If verbose logging is enabled, use the specified log prefix */ +void ssl_iostream_set_log_prefix(struct ssl_iostream *ssl_io, + const char *prefix); + int ssl_iostream_handshake(struct ssl_iostream *ssl_io); void ssl_iostream_set_handshake_callback(struct ssl_iostream *ssl_io, ssl_iostream_handshake_callback_t *callback, @@ -44,6 +53,7 @@ bool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io); int ssl_iostream_cert_match_name(struct ssl_iostream *ssl_io, const char *name); const char *ssl_iostream_get_peer_name(struct ssl_iostream *ssl_io); +const char *ssl_iostream_get_server_name(struct ssl_iostream *ssl_io); const char *ssl_iostream_get_security_string(struct ssl_iostream *ssl_io); const char *ssl_iostream_get_last_error(struct ssl_iostream *ssl_io);
--- a/src/lib-storage/index/pop3c/pop3c-client.c Thu Apr 04 17:34:23 2013 +0300 +++ b/src/lib-storage/index/pop3c/pop3c-client.c Thu Apr 04 17:39:17 2013 +0300 @@ -441,7 +441,7 @@ { struct ssl_iostream_settings ssl_set; struct stat st; - const char *source, *error; + const char *error; if (client->ssl_ctx == NULL) { i_error("pop3c(%s): No SSL context", client->set.host); @@ -468,10 +468,9 @@ client->output = client->raw_output; } - source = t_strdup_printf("pop3c(%s): ", client->set.host); - if (io_stream_create_ssl(client->ssl_ctx, source, &ssl_set, - &client->input, &client->output, - &client->ssl_iostream, &error) < 0) { + if (io_stream_create_ssl_client(client->ssl_ctx, client->set.host, + &ssl_set, &client->input, &client->output, + &client->ssl_iostream, &error) < 0) { i_error("pop3c(%s): Couldn't initialize SSL client: %s", client->set.host, error); return -1;