Mercurial > dovecot > core-2.2
view src/lib-ssl-iostream/dovecot-openssl-common.c @ 22588:041460202062
ostream-multiplex: Unreference stream parent
Otherwise it won't get free'd.
author | Aki Tuomi <aki.tuomi@dovecot.fi> |
---|---|
date | Mon, 09 Oct 2017 18:21:24 +0300 |
parents | 0f676a75b649 |
children | cb108f786fb4 |
line wrap: on
line source
/* Copyright (c) 2016-2017 Dovecot authors, see the included COPYING file */ #include "lib.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(%"PRIuSIZE_T"): 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(%"PRIuSIZE_T"): 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) { unsigned char buf; 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(); /* PRNG initialization might want to use /dev/urandom, make sure it does it before chrooting. We might not have enough entropy at the first try, so this function may fail. It's still been initialized though. */ (void)RAND_bytes(&buf, 1); } 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; }