The enum gives more details what failed.
http_client_connection_output, conn);
}
-static int
+static enum ssl_iostream_state
http_client_connection_ssl_handshaked(const char **error_r, void *context)
{
struct http_client_connection *conn = context;
struct http_client_peer_shared *pshared = conn->ppool->peer;
const char *error, *host = pshared->addr.a.tcp.https_name;
+ enum ssl_iostream_cert_validity validity =
+ ssl_iostream_check_cert_validity(conn->ssl_iostream, host, &error);
- if (ssl_iostream_check_cert_validity(conn->ssl_iostream,
- host, &error) == SSL_IOSTREAM_CERT_VALIDITY_OK)
+ if (validity == SSL_IOSTREAM_CERT_VALIDITY_OK)
e_debug(conn->event, "SSL handshake successful");
else if (ssl_iostream_get_allow_invalid_cert(conn->ssl_iostream)) {
e_debug(conn->event, "SSL handshake successful, "
"ignoring invalid certificate: %s", error);
} else {
*error_r = error;
- return -1;
+ return validity == SSL_IOSTREAM_CERT_VALIDITY_NAME_MISMATCH ?
+ SSL_IOSTREAM_STATE_NAME_MISMATCH :
+ SSL_IOSTREAM_STATE_INVALID_CERT;
}
- return 0;
+ return SSL_IOSTREAM_STATE_OK;
}
static int
imapc_connection_unref(&conn);
}
-static int imapc_connection_ssl_handshaked(const char **error_r, void *context)
+static enum ssl_iostream_state
+imapc_connection_ssl_handshaked(const char **error_r, void *context)
{
struct imapc_connection *conn = context;
const char *error;
+ enum ssl_iostream_cert_validity validity =
+ ssl_iostream_check_cert_validity(conn->ssl_iostream,
+ conn->client->set->imapc_host, &error);
- if (ssl_iostream_check_cert_validity(conn->ssl_iostream,
- conn->client->set->imapc_host,
- &error) == SSL_IOSTREAM_CERT_VALIDITY_OK) {
+ if (validity == SSL_IOSTREAM_CERT_VALIDITY_OK)
e_debug(conn->event, "SSL handshake successful");
- return 0;
- } else if (ssl_iostream_get_allow_invalid_cert(conn->ssl_iostream)) {
+ else if (ssl_iostream_get_allow_invalid_cert(conn->ssl_iostream)) {
e_debug(conn->event, "SSL handshake successful, "
"ignoring invalid certificate: %s", error);
- return 0;
} else {
*error_r = error;
- return -1;
+ return validity == SSL_IOSTREAM_CERT_VALIDITY_NAME_MISMATCH ?
+ SSL_IOSTREAM_STATE_NAME_MISMATCH :
+ SSL_IOSTREAM_STATE_INVALID_CERT;
}
+ return SSL_IOSTREAM_STATE_OK;
}
static int imapc_connection_ssl_init(struct imapc_connection *conn)
smtp_client_connection_output, conn);
}
-static int
+static enum ssl_iostream_state
smtp_client_connection_ssl_handshaked(const char **error_r, void *context)
{
struct smtp_client_connection *conn = context;
const char *error, *host = conn->host;
+ enum ssl_iostream_cert_validity validity =
+ ssl_iostream_check_cert_validity(conn->ssl_iostream, host, &error);
- if (ssl_iostream_check_cert_validity(conn->ssl_iostream,
- host, &error) == SSL_IOSTREAM_CERT_VALIDITY_OK) {
+ if (validity == SSL_IOSTREAM_CERT_VALIDITY_OK) {
e_debug(conn->event, "SSL handshake successful");
} else if (ssl_iostream_get_allow_invalid_cert(conn->ssl_iostream)) {
e_debug(conn->event, "SSL handshake successful, "
"ignoring invalid certificate: %s", error);
} else {
*error_r = error;
- return -1;
+ return validity == SSL_IOSTREAM_CERT_VALIDITY_NAME_MISMATCH ?
+ SSL_IOSTREAM_STATE_NAME_MISMATCH :
+ SSL_IOSTREAM_STATE_INVALID_CERT;
}
- return 0;
+ return SSL_IOSTREAM_STATE_OK;
}
static void
(void)openssl_iostream_bio_sync(ssl_io, OPENSSL_IOSTREAM_SYNC_TYPE_HANDSHAKE);
if (ssl_io->handshake_callback != NULL) {
- if (ssl_io->handshake_callback(&error, ssl_io->handshake_context) < 0) {
+ if (ssl_io->handshake_callback(&error, ssl_io->handshake_context) != SSL_IOSTREAM_STATE_OK) {
i_assert(error != NULL);
openssl_iostream_set_error(ssl_io, error);
ssl_io->handshake_failed = TRUE;
SSL_IOSTREAM_CERT_VALIDITY_NAME_MISMATCH,
};
+enum ssl_iostream_state {
+ /* Handshake is finished and successful. */
+ SSL_IOSTREAM_STATE_OK,
+ /* SSL certificate is missing/invalid/untrusted. */
+ SSL_IOSTREAM_STATE_INVALID_CERT,
+ /* SSL certificate is valid, but it doesn't match the name. */
+ SSL_IOSTREAM_STATE_NAME_MISMATCH,
+};
+
struct ssl_iostream_cert {
struct settings_file cert;
struct settings_file key;
/* Load SSL module */
int ssl_module_load(const char **error_r);
-/* Returns 0 if ok, -1 and sets error_r if failed. The returned error string
- becomes available via ssl_iostream_get_last_error(). The callback most
- likely should be calling ssl_iostream_check_cert_validity(). */
-typedef int
+/* If returned state is not SSL_IOSTREAM_STATE_OK, error_r is also returned.
+ The returned error string becomes available via
+ ssl_iostream_get_last_error(). The callback most likely should be calling
+ ssl_iostream_check_cert_validity(). */
+typedef enum ssl_iostream_state
ssl_iostream_handshake_callback_t(const char **error_r, void *context);
/* Called when TLS SNI becomes available. */
typedef int ssl_iostream_sni_callback_t(const char *name, const char **error_r,
}
}
-static int pop3c_client_ssl_handshaked(const char **error_r, void *context)
+static enum ssl_iostream_state
+pop3c_client_ssl_handshaked(const char **error_r, void *context)
{
struct pop3c_client *client = context;
const char *error;
+ enum ssl_iostream_cert_validity validity =
+ ssl_iostream_check_cert_validity(client->ssl_iostream,
+ client->set.host, &error);
- if (ssl_iostream_check_cert_validity(client->ssl_iostream,
- client->set.host, &error) == SSL_IOSTREAM_CERT_VALIDITY_OK) {
+ if (validity == SSL_IOSTREAM_CERT_VALIDITY_OK)
e_debug(client->event, "SSL handshake successful");
- return 0;
- } else if (ssl_iostream_get_allow_invalid_cert(client->ssl_iostream)) {
+ else if (ssl_iostream_get_allow_invalid_cert(client->ssl_iostream)) {
e_debug(client->event,
"SSL handshake successful, "
"ignoring invalid certificate: %s",
error);
- return 0;
} else {
*error_r = error;
- return -1;
+ return validity == SSL_IOSTREAM_CERT_VALIDITY_NAME_MISMATCH ?
+ SSL_IOSTREAM_STATE_NAME_MISMATCH :
+ SSL_IOSTREAM_STATE_INVALID_CERT;
}
+ return SSL_IOSTREAM_STATE_OK;
}
static int pop3c_client_ssl_init(struct pop3c_client *client)