-
Notifications
You must be signed in to change notification settings - Fork 271
/
dovecot-openssl-common.c
132 lines (116 loc) · 3.48 KB
/
dovecot-openssl-common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Copyright (c) 2016 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;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
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;
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
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;
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
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;
}
#if OPENSSL_VERSION_NUMBER < 0x10001000L
OBJ_cleanup();
#endif
#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS
SSL_COMP_free_compression_methods();
#endif
ENGINE_cleanup();
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
#if OPENSSL_VERSION_NUMBER < 0x10000000L
ERR_remove_state(0);
#elif OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_remove_thread_state(NULL);
#endif
ERR_free_strings();
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;
}