9da63de4c569a0bd8cfae0a31c445e0f85510d4e
[asterisk/asterisk.git] / main / libasteriskssl.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009-2012, Digium, Inc.
5  *
6  * Russell Bryant <russell@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Common OpenSSL support code
22  *
23  * \author Russell Bryant <russell@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 #ifdef HAVE_OPENSSL
33 #include <openssl/ssl.h>
34 #include <openssl/err.h>
35 #endif
36
37 #include <dlfcn.h>
38
39 #include "asterisk/_private.h" /* ast_ssl_init() */
40
41 #include "asterisk/utils.h"
42 #include "asterisk/lock.h"
43
44 #ifdef HAVE_OPENSSL
45
46 #define get_OpenSSL_function(func) do { real_##func = dlsym(RTLD_NEXT, __stringify(func)); } while(0)
47
48 static int startup_complete;
49
50 static ast_mutex_t *ssl_locks;
51
52 static int ssl_num_locks;
53
54 static unsigned long ssl_threadid(void)
55 {
56         return (unsigned long) pthread_self();
57 }
58
59 static void ssl_lock(int mode, int n, const char *file, int line)
60 {
61         if (n < 0 || n >= ssl_num_locks) {
62                 ast_log(LOG_ERROR, "OpenSSL is full of LIES!!! - "
63                                 "ssl_num_locks '%d' - n '%d'\n",
64                                 ssl_num_locks, n);
65                 return;
66         }
67
68         if (mode & 0x1) {
69                 ast_mutex_lock(&ssl_locks[n]);
70         } else {
71                 ast_mutex_unlock(&ssl_locks[n]);
72         }
73 }
74
75 #if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
76 int SSL_library_init(void)
77 {
78 #if defined(AST_DEVMODE)
79         if (startup_complete) {
80                 ast_debug(1, "Called after startup... ignoring!\n");
81         }
82 #endif
83         return 1;
84 }
85
86 void SSL_load_error_strings(void)
87 {
88 #if defined(AST_DEVMODE)
89         if (startup_complete) {
90                 ast_debug(1, "Called after startup... ignoring!\n");
91         }
92 #endif
93 }
94
95 void CRYPTO_set_id_callback(unsigned long (*func)(void))
96 {
97 #if defined(AST_DEVMODE)
98         if (startup_complete) {
99                 ast_debug(1, "Called after startup... ignoring!\n");
100         }
101 #endif
102 }
103
104 void CRYPTO_set_locking_callback(void (*func)(int mode,int type, const char *file, int line))
105 {
106 #if defined(AST_DEVMODE)
107         if (startup_complete) {
108                 ast_debug(1, "Called after startup... ignoring!\n");
109         }
110 #endif
111 }
112
113 void ERR_free_strings(void)
114 {
115         /* we can't allow this to be called, ever */
116 }
117 #endif /* !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L */
118
119 #endif /* HAVE_OPENSSL */
120
121 /*!
122  * \internal
123  * \brief Common OpenSSL initialization for all of Asterisk.
124  *
125  * Not needed for OpenSSL versions >= 1.1.0
126  */
127 int ast_ssl_init(void)
128 {
129 #if defined(HAVE_OPENSSL) && defined(OPENSSL_VERSION_NUMBER) && \
130         (OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER))
131         unsigned int i;
132         int (*real_SSL_library_init)(void);
133         void (*real_CRYPTO_set_id_callback)(unsigned long (*)(void));
134         void (*real_CRYPTO_set_locking_callback)(void (*)(int, int, const char *, int));
135         void (*real_SSL_load_error_strings)(void);
136         const char *errstr;
137
138         /* clear any previous dynamic linker errors */
139         dlerror();
140         get_OpenSSL_function(SSL_library_init);
141         if ((errstr = dlerror()) != NULL) {
142                 ast_debug(1, "unable to get real address of SSL_library_init: %s\n", errstr);
143                 /* there is no way to continue in this situation... SSL will
144                  * likely be broken in this process
145                  */
146                 return -1;
147         } else {
148                 real_SSL_library_init();
149         }
150
151         /* Make OpenSSL usage thread-safe. */
152
153         dlerror();
154         get_OpenSSL_function(CRYPTO_set_id_callback);
155         if ((errstr = dlerror()) != NULL) {
156                 ast_debug(1, "unable to get real address of CRYPTO_set_id_callback: %s\n", errstr);
157                 /* there is no way to continue in this situation... SSL will
158                  * likely be broken in this process
159                  */
160                 return -1;
161         } else {
162                 real_CRYPTO_set_id_callback(ssl_threadid);
163         }
164
165         dlerror();
166         get_OpenSSL_function(CRYPTO_set_locking_callback);
167         if ((errstr = dlerror()) != NULL) {
168                 ast_debug(1, "unable to get real address of CRYPTO_set_locking_callback: %s\n", errstr);
169                 /* there is no way to continue in this situation... SSL will
170                  * likely be broken in this process
171                  */
172                 return -1;
173         } else {
174                 ssl_num_locks = CRYPTO_num_locks();
175                 if (!(ssl_locks = ast_calloc(ssl_num_locks, sizeof(ssl_locks[0])))) {
176                         return -1;
177                 }
178                 for (i = 0; i < ssl_num_locks; i++) {
179                         ast_mutex_init(&ssl_locks[i]);
180                 }
181                 real_CRYPTO_set_locking_callback(ssl_lock);
182         }
183
184         /* after this point, we don't check for errors from the dlsym() calls,
185          * under the assumption that if the ones above were successful, all
186          * the rest will be too. this assumption holds as long as OpenSSL still
187          * provides all of these functions.
188          */
189
190         get_OpenSSL_function(SSL_load_error_strings);
191         real_SSL_load_error_strings();
192
193         startup_complete = 1;
194
195 #endif /* HAVE_OPENSSL and its version < 1.1 */
196         return 0;
197 }
198