From: Aki Tuomi Date: Mon, 24 Oct 2022 11:05:46 +0000 (+0300) Subject: lib-ssl-iostream: Fix compability with OpenSSL 3.0 X-Git-Tag: 2.4.0~3456 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=124c491aa688eec146c21718f0d98aec9ae03294;p=thirdparty%2Fdovecot%2Fcore.git lib-ssl-iostream: Fix compability with OpenSSL 3.0 --- diff --git a/src/lib-ssl-iostream/Makefile.am b/src/lib-ssl-iostream/Makefile.am index 83a2230995..fb99884615 100644 --- a/src/lib-ssl-iostream/Makefile.am +++ b/src/lib-ssl-iostream/Makefile.am @@ -5,7 +5,8 @@ NOPLUGIN_LDFLAGS = AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-test \ - -DMODULE_DIR=\""$(moduledir)"\" + -DMODULE_DIR=\""$(moduledir)"\" \ + $(SSL_CFLAGS) module_LTLIBRARIES = libssl_iostream_openssl.la diff --git a/src/lib-ssl-iostream/dovecot-openssl-common.c b/src/lib-ssl-iostream/dovecot-openssl-common.c index 72ef119e80..49e8f707c5 100644 --- a/src/lib-ssl-iostream/dovecot-openssl-common.c +++ b/src/lib-ssl-iostream/dovecot-openssl-common.c @@ -3,13 +3,23 @@ #include "lib.h" #include "randgen.h" #include "dovecot-openssl-common.h" +#include "iostream-openssl.h" #include -#include +#include +#ifdef HAVE_OSSL_PROVIDER_try_load +# include +#else +# include +#endif #include static int openssl_init_refcount = 0; -static ENGINE *dovecot_openssl_engine; +#ifdef HAVE_OSSL_PROVIDER_try_load +static OSSL_PROVIDER *dovecot_openssl_engine = NULL; +#else +static ENGINE *dovecot_openssl_engine = NULL; +#endif #ifdef HAVE_SSL_NEW_MEM_FUNCS static void *dovecot_openssl_malloc(size_t size, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED) @@ -63,9 +73,13 @@ void dovecot_openssl_common_global_ref(void) /*i_warning("CRYPTO_set_mem_functions() was called too late");*/ } +#ifdef HAVE_OPENSSL_init_ssl + OPENSSL_init_ssl(0, NULL); +#else SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); +#endif } bool dovecot_openssl_common_global_unref(void) @@ -76,30 +90,35 @@ bool dovecot_openssl_common_global_unref(void) return TRUE; if (dovecot_openssl_engine != NULL) { +#ifdef HAVE_OSSL_PROVIDER_try_load + OSSL_PROVIDER_unload(dovecot_openssl_engine); +#else ENGINE_finish(dovecot_openssl_engine); +#endif dovecot_openssl_engine = NULL; } +#ifdef HAVE_OPENSSL_cleanup + OPENSSL_cleanup(); +#else /* OBJ_cleanup() is called automatically by EVP_cleanup() in newer versions. Doesn't hurt to call it anyway. */ OBJ_cleanup(); -#if !defined(OPENSSL_NO_COMP) +# if !defined(OPENSSL_NO_COMP) SSL_COMP_free_compression_methods(); -#endif +# endif ENGINE_cleanup(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); -#ifdef HAVE_OPENSSL_thread_stop +# ifdef HAVE_OPENSSL_thread_stop /* no cleanup needed */ -#elif defined(HAVE_ERR_remove_thread_state) +# elif defined(HAVE_ERR_remove_thread_state) /* This was marked as deprecated in v1.1. */ ERR_remove_thread_state(NULL); -#elif defined(HAVE_ERR_remove_state) +# elif defined(HAVE_ERR_remove_state) /* This was deprecated by ERR_remove_thread_state(NULL) in v1.0.0. */ ERR_remove_state(0); -#endif +# endif ERR_free_strings(); -#ifdef HAVE_OPENSSL_cleanup - OPENSSL_cleanup(); #endif return FALSE; } @@ -110,6 +129,7 @@ int dovecot_openssl_common_global_set_engine(const char *engine, if (dovecot_openssl_engine != NULL) return 1; +#ifdef HAVE_ENGINE_by_id ENGINE_load_builtin_engines(); dovecot_openssl_engine = ENGINE_by_id(engine); if (dovecot_openssl_engine == NULL) { @@ -128,5 +148,15 @@ int dovecot_openssl_common_global_set_engine(const char *engine, dovecot_openssl_engine = NULL; return -1; } +#elif defined(HAVE_OSSL_PROVIDER_try_load) + if ((dovecot_openssl_engine = OSSL_PROVIDER_try_load(NULL, engine, 1)) == NULL) { + *error_r = t_strdup_printf("Cannot load '%s': %s", engine, + openssl_iostream_error()); + return 0; + } + return 1; +#else + *error_r = t_strdup_printf("Cannot load '%s': No engine/provider support available", engine); +#endif return 1; } diff --git a/src/lib-ssl-iostream/iostream-openssl-common.c b/src/lib-ssl-iostream/iostream-openssl-common.c index f532d11df0..3ffa1ef394 100644 --- a/src/lib-ssl-iostream/iostream-openssl-common.c +++ b/src/lib-ssl-iostream/iostream-openssl-common.c @@ -19,6 +19,14 @@ # define TLS_MAX_VERSION 0 #endif +#ifdef HAVE_ERR_get_error_all +# define openssl_get_error_data(data, flags) \ + ERR_get_error_all(NULL, NULL, NULL, data, flags) +#else +# define openssl_get_error_data(data, flags) \ + ERR_get_error_line_data(NULL, NULL, data, flags) +#endif + /* openssl_min_protocol_to_options() scans this array for name and returns version and opt. opt is used with SSL_set_options() and version is used with SSL_set_min_proto_version(). Using either method should enable the same @@ -69,7 +77,11 @@ bool openssl_cert_match_name(SSL *ssl, const char *verify_name, *reason_r = NULL; +#ifdef HAVE_SSL_get1_peer_certificate + cert = SSL_get1_peer_certificate(ssl); +#else cert = SSL_get_peer_certificate(ssl); +#endif i_assert(cert != NULL); char *peername; @@ -120,7 +132,7 @@ const char *openssl_iostream_error(void) const char *data, *final_error; int flags; - while ((err = ERR_get_error_line_data(NULL, NULL, &data, &flags)) != 0) { + while ((err = openssl_get_error_data(&data, &flags)) != 0) { if (ERR_GET_REASON(err) == ERR_R_MALLOC_FAILURE) i_fatal_status(FATAL_OUTOFMEM, "OpenSSL malloc() failed"); if (ERR_peek_error() == 0) diff --git a/src/lib-ssl-iostream/iostream-openssl-context.c b/src/lib-ssl-iostream/iostream-openssl-context.c index f0a5ad6625..80c3af812e 100644 --- a/src/lib-ssl-iostream/iostream-openssl-context.c +++ b/src/lib-ssl-iostream/iostream-openssl-context.c @@ -14,6 +14,10 @@ #include #include +#ifndef HAVE_EVP_PKEY_get0_DH +# define EVP_PKEY_get0_DH(x) ((x)->pkey.dh) +#endif + struct ssl_iostream_password_context { const char *password; const char *error; @@ -22,6 +26,7 @@ struct ssl_iostream_password_context { static bool ssl_global_initialized = FALSE; int dovecot_ssl_extdata_index; +#ifdef HAVE_SSL_CTX_set_tmp_rsa_callback static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED, int is_export ATTR_UNUSED, int keylength) { @@ -40,7 +45,9 @@ static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED, RSA_free(rsa); return NULL; } +#endif +#ifdef HAVE_SSL_CTX_set_tmp_dh_callback static DH *ssl_tmp_dh_callback(SSL *ssl, int is_export ATTR_UNUSED, int keylength ATTR_UNUSED) { @@ -51,6 +58,7 @@ static DH *ssl_tmp_dh_callback(SSL *ssl, "but no DH parameters provided. Set ssl_dh=ssl_ctx, pkey_dh) == 0) +#else DH *dh = EVP_PKEY_get0_DH(pkey_dh); if (SSL_CTX_set_tmp_dh(ctx->ssl_ctx, dh) == 0) +#endif { *error_r = t_strdup_printf( "Can't load DH parameters (ssl_dh setting): %s", @@ -498,10 +517,14 @@ ssl_proxy_ctx_set_crypto_params(SSL_CTX *ssl_ctx, const struct ssl_iostream_settings *set ATTR_UNUSED, const char **error_r ATTR_UNUSED) { +#ifdef HAVE_SSL_CTX_set_tmp_rsa_callback if (SSL_CTX_need_tmp_RSA(ssl_ctx) != 0) SSL_CTX_set_tmp_rsa_callback(ssl_ctx, ssl_gen_rsa_key); +#endif +#ifdef HAVE_SSL_CTX_set_tmp_dh_callback if (set->dh == NULL || *set->dh == '\0') SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_tmp_dh_callback); +#endif #ifndef OPENSSL_NO_ECDH /* In the non-recommended situation where ECDH cipher suites are being used instead of ECDHE, do not reuse the same ECDH key pair for diff --git a/src/lib-ssl-iostream/iostream-openssl.c b/src/lib-ssl-iostream/iostream-openssl.c index 825967bdb0..7237f90703 100644 --- a/src/lib-ssl-iostream/iostream-openssl.c +++ b/src/lib-ssl-iostream/iostream-openssl.c @@ -802,7 +802,11 @@ openssl_iostream_get_peer_name(struct ssl_iostream *ssl_io) if (!ssl_iostream_has_valid_client_cert(ssl_io)) return NULL; +#ifdef HAVE_SSL_get1_peer_certificate + x509 = SSL_get1_peer_certificate(ssl_io->ssl); +#else x509 = SSL_get_peer_certificate(ssl_io->ssl); +#endif i_assert(x509 != NULL); len = X509_NAME_get_text_by_NID(X509_get_subject_name(x509),