dovecot-2.2: lib-ssl-iostream: Simplified certificate validation...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Apr 4 18:10:12 EEST 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/ef939a32de27
changeset: 16161:ef939a32de27
user: Timo Sirainen <tss at iki.fi>
date: Thu Apr 04 18:10:04 2013 +0300
description:
lib-ssl-iostream: Simplified certificate validation. Also give better error messages.
diffstat:
src/doveadm/server-connection.c | 21 ++---------
src/lib-http/http-client-connection.c | 22 +++--------
src/lib-imap-client/imapc-connection.c | 30 +++++++--------
src/lib-ssl-iostream/iostream-openssl.c | 55 ++++++++++++++---------------
src/lib-ssl-iostream/iostream-ssl.c | 21 +++++++++++
src/lib-ssl-iostream/iostream-ssl.h | 2 +
src/lib-storage/index/pop3c/pop3c-client.c | 30 +++++++--------
7 files changed, 89 insertions(+), 92 deletions(-)
diffs (truncated from 311 to 300 lines):
diff -r 41c10ddda867 -r ef939a32de27 src/doveadm/server-connection.c
--- 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)
diff -r 41c10ddda867 -r ef939a32de27 src/lib-http/http-client-connection.c
--- 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
diff -r 41c10ddda867 -r ef939a32de27 src/lib-imap-client/imapc-connection.c
--- 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)
diff -r 41c10ddda867 -r ef939a32de27 src/lib-ssl-iostream/iostream-openssl.c
--- 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;
diff -r 41c10ddda867 -r ef939a32de27 src/lib-ssl-iostream/iostream-ssl.c
--- 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);
diff -r 41c10ddda867 -r ef939a32de27 src/lib-ssl-iostream/iostream-ssl.h
--- 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);
diff -r 41c10ddda867 -r ef939a32de27 src/lib-storage/index/pop3c/pop3c-client.c
--- 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);
+ }
More information about the dovecot-cvs
mailing list