Asterisk - The Open Source Telephony Project  18.5.0
libasteriskssl.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009-2018, Digium, Inc.
5  *
6  * Russell Bryant <[email protected]>
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 <[email protected]>
24  */
25 
26 #include "asterisk.h"
27 
28 #include "asterisk/_private.h" /* ast_ssl_init() */
29 
30 #ifdef HAVE_OPENSSL
31 #include <openssl/opensslv.h> /* for OPENSSL_VERSION_NUMBER */
32 #endif
33 
34 #if defined(HAVE_OPENSSL) && \
35  (defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000L)
36 
37 #include <dlfcn.h> /* for dlerror, dlsym, RTLD_NEXT */
38 #include <openssl/crypto.h> /* for CRYPTO_num_locks, CRYPTO_set_id_call... */
39 #include <openssl/err.h> /* for ERR_free_strings */
40 #include <openssl/ssl.h> /* for SSL_library_init, SSL_load_error_str... */
41 #if OPENSSL_VERSION_NUMBER < 0x10000000L
42 #include <pthread.h> /* for pthread_self */
43 #endif
44 
45 #include "asterisk/lock.h" /* for ast_mutex_t, ast_mutex_init, ast_mut... */
46 #include "asterisk/logger.h" /* for ast_debug, ast_log, LOG_ERROR */
47 #include "asterisk/utils.h" /* for ast_calloc */
48 
49 #define get_OpenSSL_function(func) do { real_##func = dlsym(RTLD_NEXT, __stringify(func)); } while(0)
50 
51 static int startup_complete;
52 
54 
55 static int ssl_num_locks;
56 
57 #if OPENSSL_VERSION_NUMBER < 0x10000000L
58 static unsigned long ssl_threadid(void)
59 {
60  return (unsigned long) pthread_self();
61 }
62 #endif
63 
64 static void ssl_lock(int mode, int n, const char *file, int line)
65 {
66  if (n < 0 || n >= ssl_num_locks) {
67  ast_log(LOG_ERROR, "OpenSSL is full of LIES!!! - "
68  "ssl_num_locks '%d' - n '%d'\n",
69  ssl_num_locks, n);
70  return;
71  }
72 
73  if (mode & 0x1) {
74  ast_mutex_lock(&ssl_locks[n]);
75  } else {
76  ast_mutex_unlock(&ssl_locks[n]);
77  }
78 }
79 
81 {
82 #if defined(AST_DEVMODE)
83  if (startup_complete) {
84  ast_debug(1, "Called after startup... ignoring!\n");
85  }
86 #endif
87  return 1;
88 }
89 
91 {
92 #if defined(AST_DEVMODE)
93  if (startup_complete) {
94  ast_debug(1, "Called after startup... ignoring!\n");
95  }
96 #endif
97 }
98 
99 #if OPENSSL_VERSION_NUMBER < 0x10000000L
100 void CRYPTO_set_id_callback(unsigned long (*func)(void))
101 {
102 #if defined(AST_DEVMODE)
103  if (startup_complete) {
104  ast_debug(1, "Called after startup... ignoring!\n");
105  }
106 #endif
107 }
108 #endif
109 
110 void CRYPTO_set_locking_callback(void (*func)(int mode,int type, const char *file, int line))
111 {
112 #if defined(AST_DEVMODE)
113  if (startup_complete) {
114  ast_debug(1, "Called after startup... ignoring!\n");
115  }
116 #endif
117 }
118 
120 {
121  /* we can't allow this to be called, ever */
122 }
123 
124 /*!
125  * \internal
126  * \brief Common OpenSSL initialization for all of Asterisk.
127  *
128  * Not needed for OpenSSL versions >= 1.1.0
129  */
130 int ast_ssl_init(void)
131 {
132  unsigned int i;
133  int (*real_SSL_library_init)(void);
134 #if OPENSSL_VERSION_NUMBER < 0x10000000L
135  void (*real_CRYPTO_set_id_callback)(unsigned long (*)(void));
136 #endif
137  void (*real_CRYPTO_set_locking_callback)(void (*)(int, int, const char *, int));
138  void (*real_SSL_load_error_strings)(void);
139  const char *errstr;
140 
141  /* clear any previous dynamic linker errors */
142  dlerror();
144  if ((errstr = dlerror()) != NULL) {
145  ast_debug(1, "unable to get real address of SSL_library_init: %s\n", errstr);
146  /* there is no way to continue in this situation... SSL will
147  * likely be broken in this process
148  */
149  return -1;
150  } else {
151  real_SSL_library_init();
152  }
153 
154  /* Make OpenSSL usage thread-safe. */
155 
156 #if OPENSSL_VERSION_NUMBER < 0x10000000L
157  dlerror();
159  if ((errstr = dlerror()) != NULL) {
160  ast_debug(1, "unable to get real address of CRYPTO_set_id_callback: %s\n", errstr);
161  /* there is no way to continue in this situation... SSL will
162  * likely be broken in this process
163  */
164  return -1;
165  } else {
166  real_CRYPTO_set_id_callback(ssl_threadid);
167  }
168 #endif
169 
170  dlerror();
172  if ((errstr = dlerror()) != NULL) {
173  ast_debug(1, "unable to get real address of CRYPTO_set_locking_callback: %s\n", errstr);
174  /* there is no way to continue in this situation... SSL will
175  * likely be broken in this process
176  */
177  return -1;
178  } else {
179  ssl_num_locks = CRYPTO_num_locks();
180  if (!(ssl_locks = ast_calloc(ssl_num_locks, sizeof(ssl_locks[0])))) {
181  return -1;
182  }
183  for (i = 0; i < ssl_num_locks; i++) {
184  ast_mutex_init(&ssl_locks[i]);
185  }
186  real_CRYPTO_set_locking_callback(ssl_lock);
187  }
188 
189  /* after this point, we don't check for errors from the dlsym() calls,
190  * under the assumption that if the ones above were successful, all
191  * the rest will be too. this assumption holds as long as OpenSSL still
192  * provides all of these functions.
193  */
194 
196  real_SSL_load_error_strings();
197 
198  startup_complete = 1;
199 
200  return 0;
201 }
202 
203 #else
204 
205 int ast_ssl_init(void)
206 {
207  return 0;
208 }
209 
210 #endif
static const char type[]
Definition: chan_ooh323.c:109
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static int ssl_num_locks
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
Utility functions.
void SSL_load_error_strings(void)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static unsigned long ssl_threadid(void)
void CRYPTO_set_id_callback(unsigned long(*func)(void))
static ast_mutex_t * ssl_locks
#define LOG_ERROR
Definition: logger.h:285
static void ssl_lock(int mode, int n, const char *file, int line)
int SSL_library_init(void)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Prototypes for public functions only of internal interest,.
void ERR_free_strings(void)
Support for logging to various files, console and syslog Configuration in file logger.conf.
int ast_ssl_init(void)
#define ast_mutex_init(pmutex)
Definition: lock.h:184
void CRYPTO_set_locking_callback(void(*func)(int mode, int type, const char *file, int line))
Structure for mutex and tracking information.
Definition: lock.h:135
#define get_OpenSSL_function(func)
#define ast_mutex_unlock(a)
Definition: lock.h:188
static int startup_complete