From 57704c1d8eb972812510b3f0a2049ee3bfff90e1 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 15 Oct 2024 14:22:03 +0100 Subject: [PATCH] [Fix] Do not abort when OpenSSL is broken, report that to a user Issue: #5181 --- src/libcryptobox/cryptobox.c | 19 +++++++++++-- src/libcryptobox/cryptobox.h | 3 +- src/libserver/dkim.c | 53 ++++++++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/libcryptobox/cryptobox.c b/src/libcryptobox/cryptobox.c index a976653df..6c9f9a82e 100644 --- a/src/libcryptobox/cryptobox.c +++ b/src/libcryptobox/cryptobox.c @@ -40,6 +40,7 @@ #include #include #include +#include #endif #include @@ -456,9 +457,10 @@ bool rspamd_cryptobox_verify_evp_rsa(int nid, gsize siglen, const unsigned char *digest, gsize dlen, - EVP_PKEY *pub_key) + EVP_PKEY *pub_key, + GError **err) { - bool ret = false; + bool ret = false, r; EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(pub_key, NULL); g_assert(pctx != NULL); @@ -467,7 +469,18 @@ bool rspamd_cryptobox_verify_evp_rsa(int nid, g_assert(EVP_PKEY_verify_init(pctx) == 1); g_assert(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) == 1); - g_assert(EVP_PKEY_CTX_set_signature_md(pctx, md) == 1); + + if ((r = EVP_PKEY_CTX_set_signature_md(pctx, md)) <= 0) { + g_set_error(err, g_quark_from_static_string("OpenSSL"), + r, + "cannot set digest %s for RSA verification (%s returned from OpenSSL), try use `update-crypto-policies --set LEGACY` on RH", + EVP_MD_get0_name(md), + ERR_lib_error_string(ERR_get_error())); + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(mdctx); + + return false; + } ret = (EVP_PKEY_verify(pctx, sig, siglen, digest, dlen) == 1); diff --git a/src/libcryptobox/cryptobox.h b/src/libcryptobox/cryptobox.h index afe9c4f9a..8d1f5669e 100644 --- a/src/libcryptobox/cryptobox.h +++ b/src/libcryptobox/cryptobox.h @@ -238,7 +238,8 @@ bool rspamd_cryptobox_verify_evp_rsa(int nid, gsize siglen, const unsigned char *digest, gsize dlen, - EVP_PKEY *pub_key); + EVP_PKEY *pub_key, + GError **err); #endif /** diff --git a/src/libserver/dkim.c b/src/libserver/dkim.c index a76ed31ab..0f51c66c0 100644 --- a/src/libserver/dkim.c +++ b/src/libserver/dkim.c @@ -2871,25 +2871,48 @@ rspamd_dkim_check(rspamd_dkim_context_t *ctx, nid = NID_sha1; } switch (key->type) { - case RSPAMD_DKIM_KEY_RSA: + case RSPAMD_DKIM_KEY_RSA: { + GError *err = NULL; + if (!rspamd_cryptobox_verify_evp_rsa(nid, ctx->b, ctx->blen, raw_digest, dlen, - key->specific.key_ssl.key_evp)) { - msg_debug_dkim("headers rsa verify failed"); - ERR_clear_error(); - res->rcode = DKIM_REJECT; - res->fail_reason = "headers rsa verify failed"; + key->specific.key_ssl.key_evp, &err)) { - msg_info_dkim( - "%s: headers RSA verification failure; " - "body length %d->%d; headers length %d; d=%s; s=%s; key_md5=%*xs; orig header: %s", - rspamd_dkim_type_to_string(ctx->common.type), - (int) (body_end - body_start), ctx->common.body_canonicalised, - ctx->common.headers_canonicalised, - ctx->domain, ctx->selector, - RSPAMD_DKIM_KEY_ID_LEN, rspamd_dkim_key_id(key), - ctx->dkim_header); + if (err == NULL) { + msg_debug_dkim("headers rsa verify failed"); + ERR_clear_error(); + res->rcode = DKIM_REJECT; + res->fail_reason = "headers rsa verify failed"; + + msg_info_dkim( + "%s: headers RSA verification failure; " + "body length %d->%d; headers length %d; d=%s; s=%s; key_md5=%*xs; orig header: %s", + rspamd_dkim_type_to_string(ctx->common.type), + (int) (body_end - body_start), ctx->common.body_canonicalised, + ctx->common.headers_canonicalised, + ctx->domain, ctx->selector, + RSPAMD_DKIM_KEY_ID_LEN, rspamd_dkim_key_id(key), + ctx->dkim_header); + } + else { + res->rcode = DKIM_PERM_ERROR; + res->fail_reason = "openssl internal error"; + msg_err_dkim("internal OpenSSL error: %s", err->message); + msg_info_dkim( + "%s: headers RSA verification failure due to OpenSSL internal error; " + "body length %d->%d; headers length %d; d=%s; s=%s; key_md5=%*xs; orig header: %s", + rspamd_dkim_type_to_string(ctx->common.type), + (int) (body_end - body_start), ctx->common.body_canonicalised, + ctx->common.headers_canonicalised, + ctx->domain, ctx->selector, + RSPAMD_DKIM_KEY_ID_LEN, rspamd_dkim_key_id(key), + ctx->dkim_header); + + ERR_clear_error(); + g_error_free(err); + } } break; + } case RSPAMD_DKIM_KEY_ECDSA: if (rspamd_cryptobox_verify_evp_ecdsa(nid, ctx->b, ctx->blen, raw_digest, dlen, key->specific.key_ssl.key_evp) != 1) { -- 2.39.5