From: Aki Tuomi Date: Tue, 1 Nov 2022 10:29:40 +0000 (+0200) Subject: lib-dcrypt: Improve OpenSSL error handling X-Git-Tag: 2.4.0~3455 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a717dad1eeafa2db1bd5b8280e3ca62eba5346a2;p=thirdparty%2Fdovecot%2Fcore.git lib-dcrypt: Improve OpenSSL error handling Will now try to get the error more thoroughly and handles out of memory correctly. --- diff --git a/src/lib-dcrypt/dcrypt-openssl.c b/src/lib-dcrypt/dcrypt-openssl.c index 510a0ab724..49180063e7 100644 --- a/src/lib-dcrypt/dcrypt-openssl.c +++ b/src/lib-dcrypt/dcrypt-openssl.c @@ -110,6 +110,14 @@ #define t_base64url_decode_str(x) t_base64url_decode_str(BASE64_DECODE_FLAG_IGNORE_PADDING, (x)) +#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 + struct dcrypt_context_symmetric { pool_t pool; const EVP_CIPHER *cipher; @@ -198,17 +206,59 @@ static int EC_GROUP_order_bits(const EC_GROUP *grp) } #endif -static bool dcrypt_openssl_error(const char **error_r) +static const char *ssl_err2str(unsigned long err, const char *data, int flags) { - unsigned long ec; + const char *ret; + char *buf; + const size_t err_size = 256; - if (error_r == NULL) { - /* caller is not really interested */ - return FALSE; + buf = t_malloc_no0(err_size); + /* will add \0 and the end */ + ERR_error_string_n(err, buf, err_size); + ret = buf; + + if ((flags & ERR_TXT_STRING) != 0) + ret = t_strdup_printf("%s: %s", buf, data); + return ret; +} + +static bool dcrypt_openssl_error(const char **error_r) +{ + string_t *errstr = NULL; + unsigned long err; + const char *data, *final_error; + int flags; + + 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) + break; + if (error_r == NULL) + continue; + if (errstr == NULL) + errstr = t_str_new(128); + else + str_append(errstr, ", "); + str_append(errstr, ssl_err2str(err, data, flags)); + } + if (error_r == NULL) + return FALSE; + if (err == 0) { + if (errno != 0) + final_error = strerror(errno); + else + final_error = "Unknown error"; + } else { + final_error = ssl_err2str(err, data, flags); + } + if (errstr == NULL) + *error_r = final_error; + else { + str_printfa(errstr, ", %s", final_error); + *error_r = str_c(errstr); } - ec = ERR_get_error(); - DCRYPT_SET_ERROR(t_strdup_printf("%s", ERR_error_string(ec, NULL))); return FALSE; }