]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-dcrypt: Improve OpenSSL error handling
authorAki Tuomi <aki.tuomi@open-xchange.com>
Tue, 1 Nov 2022 10:29:40 +0000 (12:29 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Thu, 3 Nov 2022 07:40:40 +0000 (07:40 +0000)
Will now try to get the error more thoroughly and handles out of memory
correctly.

src/lib-dcrypt/dcrypt-openssl.c

index 510a0ab724fa9afeb636d9ca65d75a627128242e..49180063e72a4db21eca3ecd1ec837ad26eb272e 100644 (file)
 
 #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;
 }