Mercurial > dovecot > core-2.2
changeset 16161:ef939a32de27
lib-ssl-iostream: Simplified certificate validation. Also give better error messages.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 04 Apr 2013 18:10:04 +0300 |
parents | 41c10ddda867 |
children | ec933ef95687 |
files | src/doveadm/server-connection.c src/lib-http/http-client-connection.c src/lib-imap-client/imapc-connection.c src/lib-ssl-iostream/iostream-openssl.c src/lib-ssl-iostream/iostream-ssl.c src/lib-ssl-iostream/iostream-ssl.h src/lib-storage/index/pop3c/pop3c-client.c |
diffstat | 7 files changed, 89 insertions(+), 92 deletions(-) [+] |
line wrap: on
line diff
--- a/src/doveadm/server-connection.c Thu Apr 04 17:40:30 2013 +0300 +++ b/src/doveadm/server-connection.c Thu Apr 04 18:10:04 2013 +0300 @@ -325,24 +325,11 @@ 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)) - *error_r = "SSL certificate not received"; - else - *error_r = "Received invalid SSL certificate"; + if (ssl_iostream_check_cert_validity(conn->ssl_iostream, host, error_r) < 0) return -1; - } else if (ssl_iostream_cert_match_name(conn->ssl_iostream, host) < 0) { - *error_r = t_strdup_printf( - "SSL certificate doesn't match expected host name %s", - host); - return -1; - } else { - if (doveadm_debug) { - i_debug("%s: SSL handshake successful", - conn->server->name); - } - return 0; - } + if (doveadm_debug) + i_debug("%s: SSL handshake successful", conn->server->name); + return 0; } static int server_connection_init_ssl(struct server_connection *conn)
--- a/src/lib-http/http-client-connection.c Thu Apr 04 17:40:30 2013 +0300 +++ b/src/lib-http/http-client-connection.c Thu Apr 04 18:10:04 2013 +0300 @@ -640,26 +640,18 @@ http_client_connection_ssl_handshaked(const char **error_r, void *context) { struct http_client_connection *conn = context; - const char *host = conn->peer->addr.https_name; + const char *error, *host = conn->peer->addr.https_name; - if (conn->client->set.ssl_allow_invalid_cert) { - /* skip certificate checks */ + if (ssl_iostream_check_cert_validity(conn->ssl_iostream, host, &error) == 0) http_client_connection_debug(conn, "SSL handshake successful"); - return 0; - } else if (!ssl_iostream_has_valid_client_cert(conn->ssl_iostream)) { - if (!ssl_iostream_has_broken_client_cert(conn->ssl_iostream)) - *error_r = "SSL certificate not received"; - else - *error_r = "Received invalid SSL certificate"; - return -1; - } else if (ssl_iostream_cert_match_name(conn->ssl_iostream, host) == 0) { - http_client_connection_debug(conn, "SSL handshake successful"); - return 0; + else if (conn->client->set.ssl_allow_invalid_cert) { + http_client_connection_debug(conn, "SSL handshake successful, " + "ignoring invalid certificate: %s", error); } else { - *error_r = t_strdup_printf( - "SSL certificate doesn't match expected host name %s", host); + *error_r = error; return -1; } + return 0; } static int
--- a/src/lib-imap-client/imapc-connection.c Thu Apr 04 17:40:30 2013 +0300 +++ b/src/lib-imap-client/imapc-connection.c Thu Apr 04 18:10:04 2013 +0300 @@ -1129,29 +1129,27 @@ static int imapc_connection_ssl_handshaked(const char **error_r, void *context) { struct imapc_connection *conn = context; + const char *error; - if (!conn->client->set.ssl_verify) { - /* skip certificate checks */ - return 0; - } else if (!ssl_iostream_has_valid_client_cert(conn->ssl_iostream)) { - if (!ssl_iostream_has_broken_client_cert(conn->ssl_iostream)) - *error_r = "SSL certificate not received"; - else - *error_r = "Received invalid SSL certificate"; - } else if (ssl_iostream_cert_match_name(conn->ssl_iostream, - conn->client->set.host) < 0) { - *error_r = t_strdup_printf( - "SSL certificate doesn't match expected host name %s", - conn->client->set.host); - } else { + if (ssl_iostream_check_cert_validity(conn->ssl_iostream, + conn->client->set.host, &error) == 0) { if (conn->client->set.debug) { i_debug("imapc(%s): SSL handshake successful", conn->name); } return 0; + } else if (!conn->client->set.ssl_verify) { + if (conn->client->set.debug) { + i_debug("imapc(%s): SSL handshake successful, " + "ignoring invalid certificate: %s", + conn->name, error); + } + return 0; + } else { + conn->handshake_failed = TRUE; + *error_r = error; + return -1; } - conn->handshake_failed = TRUE; - return -1; } static int imapc_connection_ssl_init(struct imapc_connection *conn)
--- a/src/lib-ssl-iostream/iostream-openssl.c Thu Apr 04 17:40:30 2013 +0300 +++ b/src/lib-ssl-iostream/iostream-openssl.c Thu Apr 04 18:10:04 2013 +0300 @@ -9,6 +9,13 @@ static void openssl_iostream_free(struct ssl_iostream *ssl_io); +static void +openssl_iostream_set_error(struct ssl_iostream *ssl_io, const char *str) +{ + i_free(ssl_io->last_error); + ssl_io->last_error = i_strdup(str); +} + static void openssl_info_callback(const SSL *ssl, int where, int ret) { struct ssl_iostream *ssl_io; @@ -86,28 +93,27 @@ int ssl_extidx = SSL_get_ex_data_X509_STORE_CTX_idx(); SSL *ssl; struct ssl_iostream *ssl_io; + char certname[1024]; + X509_NAME *subject; ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_extidx); ssl_io = SSL_get_ex_data(ssl, dovecot_ssl_extdata_index); ssl_io->cert_received = TRUE; - if (ssl_io->verbose || - (ssl_io->verbose_invalid_cert && !preverify_ok)) { - char buf[1024]; - X509_NAME *subject; - - subject = X509_get_subject_name(ctx->current_cert); - if (subject == NULL || - X509_NAME_oneline(subject, buf, sizeof(buf)) == NULL) - buf[0] = '\0'; - else - buf[sizeof(buf)-1] = '\0'; /* just in case.. */ - if (!preverify_ok) { - i_info("Invalid certificate: %s: %s", - X509_verify_cert_error_string(ctx->error), buf); - } else { - i_info("Valid certificate: %s", buf); - } + subject = X509_get_subject_name(ctx->current_cert); + if (subject == NULL || + X509_NAME_oneline(subject, certname, sizeof(certname)) == NULL) + certname[0] = '\0'; + else + certname[sizeof(certname)-1] = '\0'; /* just in case.. */ + if (!preverify_ok) { + openssl_iostream_set_error(ssl_io, t_strdup_printf( + "Received invalid SSL certificate: %s: %s", + X509_verify_cert_error_string(ctx->error), certname)); + if (ssl_io->verbose_invalid_cert) + i_info("%s", ssl_io->last_error); + } else if (ssl_io->verbose) { + i_info("Received valid SSL certificate: %s", certname); } if (!preverify_ok) { ssl_io->cert_broken = TRUE; @@ -173,7 +179,7 @@ } ssl_io->verbose = set->verbose; - ssl_io->verbose_invalid_cert = set->verbose_invalid_cert; + ssl_io->verbose_invalid_cert = set->verbose_invalid_cert || set->verbose; ssl_io->require_valid_cert = set->require_valid_cert; return 0; } @@ -422,13 +428,6 @@ return 1; } -static void -openssl_iostream_set_error(struct ssl_iostream *ssl_io, const char *str) -{ - i_free(ssl_io->last_error); - ssl_io->last_error = i_strdup(str); -} - static int openssl_iostream_handle_error_full(struct ssl_iostream *ssl_io, int ret, const char *func_name, bool write_error) @@ -545,9 +544,6 @@ /* handshake finished */ (void)openssl_iostream_bio_sync(ssl_io); - i_free_and_null(ssl_io->last_error); - ssl_io->handshaked = TRUE; - if (ssl_io->handshake_callback != NULL) { if (ssl_io->handshake_callback(&error, ssl_io->handshake_context) < 0) { i_assert(error != NULL); @@ -558,6 +554,9 @@ return -1; } } + i_free_and_null(ssl_io->last_error); + ssl_io->handshaked = TRUE; + if (ssl_io->ssl_output != NULL) (void)o_stream_flush(ssl_io->ssl_output); return 1;
--- a/src/lib-ssl-iostream/iostream-ssl.c Thu Apr 04 17:40:30 2013 +0300 +++ b/src/lib-ssl-iostream/iostream-ssl.c Thu Apr 04 18:10:04 2013 +0300 @@ -166,6 +166,27 @@ return ssl_vfuncs->cert_match_name(ssl_io, name); } +int ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io, + const char *host, const char **error_r) +{ + if (!ssl_iostream_has_valid_client_cert(ssl_io)) { + if (!ssl_iostream_has_broken_client_cert(ssl_io)) + *error_r = "SSL certificate not received"; + else { + *error_r = t_strdup(ssl_iostream_get_last_error(ssl_io)); + if (*error_r == NULL) + *error_r = "Received invalid SSL certificate"; + } + return -1; + } else if (ssl_iostream_cert_match_name(ssl_io, host) < 0) { + *error_r = t_strdup_printf( + "SSL certificate doesn't match expected host name %s", + host); + return -1; + } + return 0; +} + const char *ssl_iostream_get_peer_name(struct ssl_iostream *ssl_io) { return ssl_vfuncs->get_peer_name(ssl_io);
--- a/src/lib-ssl-iostream/iostream-ssl.h Thu Apr 04 17:40:30 2013 +0300 +++ b/src/lib-ssl-iostream/iostream-ssl.h Thu Apr 04 18:10:04 2013 +0300 @@ -51,6 +51,8 @@ bool ssl_iostream_is_handshaked(const struct ssl_iostream *ssl_io); bool ssl_iostream_has_valid_client_cert(const struct ssl_iostream *ssl_io); bool ssl_iostream_has_broken_client_cert(struct ssl_iostream *ssl_io); +int ssl_iostream_check_cert_validity(struct ssl_iostream *ssl_io, + const char *host, const char **error_r); 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);
--- a/src/lib-storage/index/pop3c/pop3c-client.c Thu Apr 04 17:40:30 2013 +0300 +++ b/src/lib-storage/index/pop3c/pop3c-client.c Thu Apr 04 18:10:04 2013 +0300 @@ -412,29 +412,27 @@ static int pop3c_client_ssl_handshaked(const char **error_r, void *context) { struct pop3c_client *client = context; + const char *error; - if (!client->set.ssl_verify) { - /* skip certificate checks */ - return 0; - } else if (!ssl_iostream_has_valid_client_cert(client->ssl_iostream)) { - if (!ssl_iostream_has_broken_client_cert(client->ssl_iostream)) - *error_r = "SSL certificate not received"; - else - *error_r = "Received invalid SSL certificate"; - } else if (ssl_iostream_cert_match_name(client->ssl_iostream, - client->set.host) < 0) { - *error_r = t_strdup_printf( - "SSL certificate doesn't match expected host name %s", - client->set.host); - } else { + if (ssl_iostream_check_cert_validity(client->ssl_iostream, + client->set.host, &error) == 0) { if (client->set.debug) { i_debug("pop3c(%s): SSL handshake successful", client->set.host); } return 0; + } else if (!client->set.ssl_verify) { + if (client->set.debug) { + i_debug("pop3c(%s): SSL handshake successful, " + "ignoring invalid certificate: %s", + client->set.host, error); + } + return 0; + } else { + client->handshake_failed = TRUE; + *error_r = error; + return -1; } - client->handshake_failed = TRUE; - return -1; } static int pop3c_client_ssl_init(struct pop3c_client *client)