summaryrefslogtreecommitdiffstats
path: root/src/lib-ssl-iostream/dovecot-openssl-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-ssl-iostream/dovecot-openssl-common.c')
-rw-r--r--src/lib-ssl-iostream/dovecot-openssl-common.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/lib-ssl-iostream/dovecot-openssl-common.c b/src/lib-ssl-iostream/dovecot-openssl-common.c
new file mode 100644
index 0000000..76f98bc
--- /dev/null
+++ b/src/lib-ssl-iostream/dovecot-openssl-common.c
@@ -0,0 +1,132 @@
+/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "randgen.h"
+#include "dovecot-openssl-common.h"
+
+#include <openssl/ssl.h>
+#include <openssl/engine.h>
+#include <openssl/rand.h>
+
+static int openssl_init_refcount = 0;
+static ENGINE *dovecot_openssl_engine;
+
+#ifdef HAVE_SSL_NEW_MEM_FUNCS
+static void *dovecot_openssl_malloc(size_t size, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED)
+#else
+static void *dovecot_openssl_malloc(size_t size)
+#endif
+{
+ /* this may be performance critical, so don't use
+ i_malloc() or calloc() */
+ void *mem = malloc(size);
+ if (mem == NULL) {
+ i_fatal_status(FATAL_OUTOFMEM,
+ "OpenSSL: malloc(%zu): Out of memory", size);
+ }
+ return mem;
+}
+
+#ifdef HAVE_SSL_NEW_MEM_FUNCS
+static void *dovecot_openssl_realloc(void *ptr, size_t size, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED)
+#else
+static void *dovecot_openssl_realloc(void *ptr, size_t size)
+#endif
+{
+ void *mem = realloc(ptr, size);
+ if (mem == NULL) {
+ i_fatal_status(FATAL_OUTOFMEM,
+ "OpenSSL: realloc(%zu): Out of memory", size);
+ }
+ return mem;
+}
+
+#ifdef HAVE_SSL_NEW_MEM_FUNCS
+static void dovecot_openssl_free(void *ptr, const char *u0 ATTR_UNUSED, int u1 ATTR_UNUSED)
+#else
+static void dovecot_openssl_free(void *ptr)
+#endif
+{
+ free(ptr);
+}
+
+void dovecot_openssl_common_global_ref(void)
+{
+ if (openssl_init_refcount++ > 0)
+ return;
+
+ /* use our own memory allocation functions that will die instead of
+ returning NULL. this avoids random failures on out-of-memory
+ conditions. */
+ if (CRYPTO_set_mem_functions(dovecot_openssl_malloc,
+ dovecot_openssl_realloc, dovecot_openssl_free) == 0) {
+ /*i_warning("CRYPTO_set_mem_functions() was called too late");*/
+ }
+
+ SSL_library_init();
+ SSL_load_error_strings();
+ OpenSSL_add_all_algorithms();
+}
+
+bool dovecot_openssl_common_global_unref(void)
+{
+ i_assert(openssl_init_refcount > 0);
+
+ if (--openssl_init_refcount > 0)
+ return TRUE;
+
+ if (dovecot_openssl_engine != NULL) {
+ ENGINE_finish(dovecot_openssl_engine);
+ dovecot_openssl_engine = NULL;
+ }
+ /* OBJ_cleanup() is called automatically by EVP_cleanup() in
+ newer versions. Doesn't hurt to call it anyway. */
+ OBJ_cleanup();
+#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS
+ SSL_COMP_free_compression_methods();
+#endif
+ ENGINE_cleanup();
+ EVP_cleanup();
+ CRYPTO_cleanup_all_ex_data();
+#ifdef HAVE_OPENSSL_AUTO_THREAD_DEINIT
+ /* no cleanup needed */
+#elif defined(HAVE_OPENSSL_ERR_REMOVE_THREAD_STATE)
+ /* This was marked as deprecated in v1.1. */
+ ERR_remove_thread_state(NULL);
+#else
+ /* This was deprecated by ERR_remove_thread_state(NULL) in v1.0.0. */
+ ERR_remove_state(0);
+#endif
+ ERR_free_strings();
+#ifdef HAVE_OPENSSL_CLEANUP
+ OPENSSL_cleanup();
+#endif
+ return FALSE;
+}
+
+int dovecot_openssl_common_global_set_engine(const char *engine,
+ const char **error_r)
+{
+ if (dovecot_openssl_engine != NULL)
+ return 1;
+
+ ENGINE_load_builtin_engines();
+ dovecot_openssl_engine = ENGINE_by_id(engine);
+ if (dovecot_openssl_engine == NULL) {
+ *error_r = t_strdup_printf("Unknown engine '%s'", engine);
+ return 0;
+ }
+ if (ENGINE_init(dovecot_openssl_engine) == 0) {
+ *error_r = t_strdup_printf("ENGINE_init(%s) failed", engine);
+ ENGINE_free(dovecot_openssl_engine);
+ dovecot_openssl_engine = NULL;
+ return -1;
+ }
+ if (ENGINE_set_default(dovecot_openssl_engine, ENGINE_METHOD_ALL) == 0) {
+ *error_r = t_strdup_printf("ENGINE_set_default(%s) failed", engine);
+ ENGINE_free(dovecot_openssl_engine);
+ dovecot_openssl_engine = NULL;
+ return -1;
+ }
+ return 1;
+}