RTS API Documentation  1.10.11
Functions | Variables
switch_core_cert.c File Reference
#include <switch.h>
#include <switch_ssl.h>
+ Include dependency graph for switch_core_cert.c:

Go to the source code of this file.

Functions

static void switch_ssl_ssl_lock_callback (int mode, int type, char *file, int line)
 
static void switch_ssl_ssl_thread_id (CRYPTO_THREADID *id)
 
void switch_ssl_init_ssl_locks (void)
 
void switch_ssl_destroy_ssl_locks (void)
 
static const EVP_MD * get_evp_by_name (const char *name)
 
int switch_core_cert_verify (dtls_fingerprint_t *fp)
 
int switch_core_cert_expand_fingerprint (dtls_fingerprint_t *fp, const char *str)
 
int switch_core_cert_extract_fingerprint (X509 *x509, dtls_fingerprint_t *fp)
 
int switch_core_cert_gen_fingerprint (const char *prefix, dtls_fingerprint_t *fp)
 
static int mkcert (X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
 
int switch_core_gen_certs (const char *prefix)
 
switch_bool_t switch_core_check_dtls_pem (const char *file)
 

Variables

static switch_mutex_t ** ssl_mutexes
 
static switch_memory_pool_tssl_pool = NULL
 
static int ssl_count = 0
 

Function Documentation

◆ get_evp_by_name()

static const EVP_MD* get_evp_by_name ( const char *  name)
static

Definition at line 106 of file switch_core_cert.c.

Referenced by switch_core_cert_extract_fingerprint().

107 {
108  if (!strcasecmp(name, "md5")) return EVP_md5();
109  if (!strcasecmp(name, "sha1")) return EVP_sha1();
110  if (!strcasecmp(name, "sha-1")) return EVP_sha1();
111  if (!strcasecmp(name, "sha-256")) return EVP_sha256();
112  if (!strcasecmp(name, "sha-512")) return EVP_sha512();
113 
114  return NULL;
115 }
const char *const name
Definition: switch_cJSON.h:250

◆ mkcert()

static int mkcert ( X509 **  x509p,
EVP_PKEY **  pkeyp,
int  bits,
int  serial,
int  days 
)
static

Definition at line 412 of file switch_core_cert.c.

References name, and switch_assert.

Referenced by switch_core_cert_gen_fingerprint(), and switch_core_gen_certs().

413 {
414  X509 *x;
415  EVP_PKEY *pk;
416 #if OPENSSL_VERSION_NUMBER < 0x30000000
417  RSA *rsa;
418 #endif
419  X509_NAME *name=NULL;
420 
421  switch_assert(pkeyp);
422  switch_assert(x509p);
423 
424  if (*pkeyp == NULL) {
425  if ((pk = EVP_PKEY_new()) == NULL) {
426  abort();
427  }
428  } else {
429  pk = *pkeyp;
430  }
431 
432  if (*x509p == NULL) {
433  if ((x = X509_new()) == NULL) {
434  goto err;
435  }
436  } else {
437  x = *x509p;
438  }
439 
440 #if OPENSSL_VERSION_NUMBER >= 0x30000000
441  {
442  EVP_PKEY_CTX *ctx;
443 
444  ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
445  /* Setup the key context */
446  if ((!ctx) || (EVP_PKEY_keygen_init(ctx) <= 0) || (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0)) {
447  abort();
448  goto err;
449  }
450 
451  /* Generate key */
452  if (EVP_PKEY_generate(ctx, &pk) <= 0) {
453  abort();
454  goto err;
455  }
456 
457  EVP_PKEY_CTX_free(ctx);
458  }
459 #elif OPENSSL_VERSION_NUMBER >= 0x10100000
460  rsa = RSA_new();
461  {
462  static const BN_ULONG ULONG_RSA_F4 = RSA_F4;
463  BIGNUM* BN_value_RSA_F4 = BN_new();
464  if (!BN_value_RSA_F4) {
465  abort();
466  goto err;
467  }
468  BN_set_word(BN_value_RSA_F4,ULONG_RSA_F4);
469  RSA_generate_key_ex(rsa, bits, BN_value_RSA_F4, NULL);
470  BN_free(BN_value_RSA_F4);
471  }
472 #else
473  rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
474 #endif
475 
476 #if OPENSSL_VERSION_NUMBER < 0x30000000
477  if (!EVP_PKEY_assign_RSA(pk, rsa)) {
478  abort();
479  }
480 
481  rsa = NULL;
482 #endif
483 
484  X509_set_version(x, 2);
485  ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
486  X509_gmtime_adj(X509_get_notBefore(x), -(long)60*60*24*7);
487  X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
488  X509_set_pubkey(x, pk);
489 
490  name = X509_get_subject_name(x);
491 
492  /* This function creates and adds the entry, working out the
493  * correct string type and performing checks on its length.
494  * Normally we'd check the return value for errors...
495  */
496  X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"US", -1, -1, 0);
497  X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)"FreeSWITCH", -1, -1, 0);
498 
499 
500  /* Its self signed so set the issuer name to be the same as the
501  * subject.
502  */
503  X509_set_issuer_name(x, name);
504 
505 #if OPENSSL_VERSION_NUMBER >= 0x30000000
506  if (!X509_sign(x, pk, EVP_sha256())) {
507 #else
508  if (!X509_sign(x, pk, EVP_sha1())) {
509 #endif
510  goto err;
511  }
512 
513  *x509p = x;
514  *pkeyp = pk;
515 
516  return(1);
517 err:
518  ERR_print_errors_fp(stdout);
519 
520  return(0);
521 }
const char *const name
Definition: switch_cJSON.h:250
#define switch_assert(expr)

◆ switch_core_cert_expand_fingerprint()

int switch_core_cert_expand_fingerprint ( dtls_fingerprint_t fp,
const char *  str 
)

Definition at line 162 of file switch_core_cert.c.

References dtls_fp_s::data, and MAX_FPLEN.

Referenced by switch_rtp_add_dtls().

163 {
164  char *tmp = strdup(str);
165  char *p = tmp;
166  int i = 0;
167  char *v;
168 
169  while ((v = strsep(&p, ":")) && (i != (MAX_FPLEN - 1))) {
170  sscanf(v, "%02x", (uint32_t *) &fp->data[i++]);
171  }
172 
173  free(tmp);
174 
175  return i;
176 }
uint8_t data[MAX_FPLEN+1]
Definition: switch_core.h:154
#define MAX_FPLEN
Definition: switch_core.h:149

◆ switch_core_cert_extract_fingerprint()

int switch_core_cert_extract_fingerprint ( X509 *  x509,
dtls_fingerprint_t fp 
)

Definition at line 178 of file switch_core_cert.c.

References dtls_fp_s::data, get_evp_by_name(), dtls_fp_s::len, dtls_fp_s::str, SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, switch_log_printf(), and dtls_fp_s::type.

Referenced by do_dtls(), dtls_state_setup(), and switch_core_cert_gen_fingerprint().

179 {
180  const EVP_MD *evp;
181  unsigned int i, j;
182 
183  evp = get_evp_by_name(fp->type);
184 
185  if (X509_digest(x509, evp, fp->data, &fp->len) != 1 || fp->len <= 0) {
187  return -1;
188  }
189 
190  for (i = 0, j = 0; i < fp->len; ++i, j += 3){
191  sprintf((char*)&fp->str[j], (i == (fp->len - 1)) ? "%.2X" : "%.2X:", fp->data[i]);
192  }
193  *(&fp->str[fp->len * 3]) = '\0';
194 
195  return 0;
196 
197 }
#define SWITCH_CHANNEL_LOG
char str[MAX_FPSTRLEN]
Definition: switch_core.h:156
char * type
Definition: switch_core.h:155
uint8_t data[MAX_FPLEN+1]
Definition: switch_core.h:154
uint32_t len
Definition: switch_core.h:153
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
static const EVP_MD * get_evp_by_name(const char *name)

◆ switch_core_cert_gen_fingerprint()

int switch_core_cert_gen_fingerprint ( const char *  prefix,
dtls_fingerprint_t fp 
)

Definition at line 199 of file switch_core_cert.c.

References switch_directories::certs_dir, mkcert(), SWITCH_CHANNEL_LOG, switch_core_cert_extract_fingerprint(), switch_file_exists(), SWITCH_GLOBAL_dirs, SWITCH_LOG_ERROR, switch_log_printf(), switch_mprintf(), SWITCH_PATH_SEPARATOR, and SWITCH_STATUS_SUCCESS.

Referenced by generate_local_fingerprint().

200 {
201  X509* x509 = NULL;
202  BIO* bio = NULL;
203  int ret = 0;
204  char *rsa;
205 
207 
208  if (switch_file_exists(rsa, NULL) != SWITCH_STATUS_SUCCESS) {
209  free(rsa);
211  }
212 
213  if (!(bio = BIO_new(BIO_s_file()))) {
215  goto end;
216  }
217 
218  if (BIO_read_filename(bio, rsa) != 1) {
220  goto end;
221  }
222 
223  if (!(x509 = PEM_read_bio_X509(bio, NULL, 0, NULL))) {
225  goto end;
226  }
227 
229 
230  ret = 1;
231 
232  end:
233 
234  if (bio) {
235  BIO_free_all(bio);
236  }
237 
238  if (x509) {
239  X509_free(x509);
240  }
241 
242  free(rsa);
243 
244  return ret;
245 }
#define SWITCH_CHANNEL_LOG
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
int switch_core_cert_extract_fingerprint(X509 *x509, dtls_fingerprint_t *fp)
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_status_t switch_file_exists(const char *filename, switch_memory_pool_t *pool)
Definition: switch_apr.c:519
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)

◆ switch_core_cert_verify()

int switch_core_cert_verify ( dtls_fingerprint_t fp)

Definition at line 143 of file switch_core_cert.c.

References dtls_fp_s::data, MAX_FPLEN, and dtls_fp_s::str.

Referenced by do_dtls(), and dtls_state_setup().

144 {
145  unsigned char fdata[MAX_FPLEN] = { 0 };
146  char *tmp = strdup(fp->str);
147  char *p = tmp;
148  int i = 0;
149  char *v;
150 
151  while ((v = strsep(&p, ":")) && (i != (MAX_FPLEN - 1))) {
152  sscanf(v, "%02x", (uint32_t *) &fdata[i++]);
153  }
154 
155  free(tmp);
156 
157  i = !memcmp(fdata, fp->data, i);
158 
159  return i;
160 }
char str[MAX_FPSTRLEN]
Definition: switch_core.h:156
uint8_t data[MAX_FPLEN+1]
Definition: switch_core.h:154
#define MAX_FPLEN
Definition: switch_core.h:149

◆ switch_core_check_dtls_pem()

switch_bool_t switch_core_check_dtls_pem ( const char *  file)

Definition at line 338 of file switch_core_cert.c.

References switch_directories::certs_dir, SWITCH_CHANNEL_LOG, SWITCH_FALSE, switch_file_exists(), SWITCH_GLOBAL_dirs, switch_is_file_path(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, switch_mprintf(), SWITCH_PATH_SEPARATOR, switch_safe_free, SWITCH_STATUS_SUCCESS, and SWITCH_TRUE.

Referenced by switch_core_media_init().

339 {
340  char *pem = NULL, *old_pem = NULL;
341  FILE *fp = NULL;
342  EVP_PKEY *pkey = NULL;
343  int bits = 0;
344 
345  if (switch_is_file_path(file)) {
346  pem = strdup(file);
347  } else {
349  }
350 
351  if (switch_file_exists(pem, NULL) != SWITCH_STATUS_SUCCESS) {
352  switch_safe_free(pem);
353 
354  return SWITCH_FALSE;
355  }
356 
357  fp = fopen(pem, "r");
358  if (!fp) {
359  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot open %s: %s\n", pem, strerror(errno));
360  goto rename_pem;
361  }
362 
363  pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
364  fclose(fp);
365 
366  if (!pkey) {
367  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot read key %s: %s\n", pem, ERR_error_string(ERR_get_error(), NULL));
368  goto rename_pem;
369  }
370 
371  bits = EVP_PKEY_bits(pkey);
372  EVP_PKEY_free(pkey);
373 
374  if (bits < 4096) {
375  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%s cryptographic length is too short (%d), it will be regenerated\n", pem, bits);
376  goto rename_pem;
377  }
378 
379  switch_safe_free(pem);
380 
381  return SWITCH_TRUE;
382 
383 rename_pem:
384 
385  old_pem = switch_mprintf("%s.old", pem);
386 
387  if (rename(pem, old_pem) != -1) {
388  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Renamed %s to %s\n", pem, old_pem);
389  } else {
390  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not rename %s: %s\n", pem, strerror(errno));
391  }
392 
393  switch_safe_free(old_pem);
394  switch_safe_free(pem);
395 
396  return SWITCH_FALSE;
397 }
#define SWITCH_CHANNEL_LOG
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_status_t switch_file_exists(const char *filename, switch_memory_pool_t *pool)
Definition: switch_apr.c:519
static switch_bool_t switch_is_file_path(const char *file)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)

◆ switch_core_gen_certs()

int switch_core_gen_certs ( const char *  prefix)

Definition at line 250 of file switch_core_cert.c.

References switch_directories::certs_dir, mkcert(), SWITCH_CHANNEL_LOG, switch_file_exists(), SWITCH_GLOBAL_dirs, switch_is_file_path(), SWITCH_LOG_ERROR, switch_log_printf(), switch_mprintf(), SWITCH_PATH_SEPARATOR, switch_safe_free, SWITCH_STATUS_SUCCESS, and switch_stristr().

Referenced by load_config(), and switch_core_media_init().

251 {
252  //BIO *bio_err;
253  X509 *x509 = NULL;
254  EVP_PKEY *pkey = NULL;
255  char *rsa = NULL, *pvt = NULL;
256  FILE *fp;
257  char *pem = NULL;
258 
259  if (switch_stristr(".pem", prefix)) {
260 
261  if (switch_is_file_path(prefix)) {
262  pem = strdup(prefix);
263  } else {
265  }
266 
267  if (switch_file_exists(pem, NULL) == SWITCH_STATUS_SUCCESS) {
268  goto end;
269  }
270  } else {
271  if (switch_is_file_path(prefix)) {
272  pvt = switch_mprintf("%s.key", prefix);
273  rsa = switch_mprintf("%s.crt", prefix);
274  } else {
277  }
278 
280  goto end;
281  }
282  }
283 
284 #ifdef CRYPTO_MEM_CHECK_ON
285  CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
286 #endif
287 
288  //bio_err=BIO_new_fp(stderr, BIO_NOCLOSE);
289 
290  if (!mkcert(&x509, &pkey, 4096, 0, 36500)) {
291  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Certificate generation failed\n");
292  goto end;
293  }
294 
295  //RSA_print_fp(stdout, pkey->pkey.rsa, 0);
296  //X509_print_fp(stdout, x509);
297 
298  if (pem) {
299  if ((fp = fopen(pem, "w"))) {
300  PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
301  PEM_write_X509(fp, x509);
302  fclose(fp);
303  }
304 
305  } else {
306  if (pvt && (fp = fopen(pvt, "w"))) {
307  PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL);
308  fclose(fp);
309  }
310 
311  if (rsa && (fp = fopen(rsa, "w"))) {
312  PEM_write_X509(fp, x509);
313  fclose(fp);
314  }
315  }
316 
317  X509_free(x509);
318  EVP_PKEY_free(pkey);
319 
320 #ifndef OPENSSL_NO_ENGINE
321  ENGINE_cleanup();
322 #endif
323  CRYPTO_cleanup_all_ex_data();
324 
325  //CRYPTO_mem_leaks(bio_err);
326  //BIO_free(bio_err);
327 
328 
329  end:
330 
331  switch_safe_free(pvt);
332  switch_safe_free(rsa);
333  switch_safe_free(pem);
334 
335  return(0);
336 }
#define SWITCH_CHANNEL_LOG
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:124
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_directories SWITCH_GLOBAL_dirs
Definition: switch_core.c:82
switch_status_t switch_file_exists(const char *filename, switch_memory_pool_t *pool)
Definition: switch_apr.c:519
static switch_bool_t switch_is_file_path(const char *file)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
const char * switch_stristr(const char *instr, const char *str)
static int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int days)
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)

◆ switch_ssl_destroy_ssl_locks()

void switch_ssl_destroy_ssl_locks ( void  )

Definition at line 85 of file switch_core_cert.c.

References ssl_count, ssl_mutexes, ssl_pool, switch_core_destroy_memory_pool, and switch_mutex_destroy().

Referenced by switch_core_cert_extract_fingerprint(), and switch_core_destroy().

86 {
87  int i;
88 
89  if (ssl_count == 1) {
90  CRYPTO_set_locking_callback(NULL);
91  for (i = 0; i < CRYPTO_num_locks(); i++) {
92  if (ssl_mutexes[i]) {
94  }
95  }
96 
97  OPENSSL_free(ssl_mutexes);
98  ssl_count--;
99  }
100 
101  if (ssl_pool) {
103  }
104 }
switch_status_t switch_mutex_destroy(switch_mutex_t *lock)
Definition: switch_apr.c:303
static int ssl_count
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
static switch_mutex_t ** ssl_mutexes
static switch_memory_pool_t * ssl_pool

◆ switch_ssl_init_ssl_locks()

void switch_ssl_init_ssl_locks ( void  )

Definition at line 58 of file switch_core_cert.c.

References ssl_count, ssl_mutexes, ssl_pool, switch_assert, switch_core_new_memory_pool, switch_mutex_init(), SWITCH_MUTEX_NESTED, switch_ssl_ssl_lock_callback(), and switch_ssl_ssl_thread_id().

Referenced by switch_core_cert_extract_fingerprint(), and switch_core_init().

59 {
60 
61  int i, num;
62 
63  if (ssl_count == 0) {
64  num = CRYPTO_num_locks();
65 
66  ssl_mutexes = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(switch_mutex_t*));
67  switch_assert(ssl_mutexes != NULL);
68 
70 
71  for (i = 0; i < num; i++) {
73  switch_assert(ssl_mutexes[i] != NULL);
74  }
75 
76 #if OPENSSL_VERSION_NUMBER <= 0x10100000
77  CRYPTO_THREADID_set_callback(switch_ssl_ssl_thread_id);
78  CRYPTO_set_locking_callback((void (*)(int, int, const char*, int))switch_ssl_ssl_lock_callback);
79 #endif
80  }
81 
82  ssl_count++;
83 }
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
static void switch_ssl_ssl_thread_id(CRYPTO_THREADID *id)
static int ssl_count
static switch_mutex_t ** ssl_mutexes
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
static void switch_ssl_ssl_lock_callback(int mode, int type, char *file, int line)
static switch_memory_pool_t * ssl_pool
#define switch_assert(expr)

◆ switch_ssl_ssl_lock_callback()

static void switch_ssl_ssl_lock_callback ( int  mode,
int  type,
char *  file,
int  line 
)
inlinestatic

Definition at line 41 of file switch_core_cert.c.

References ssl_mutexes, switch_mutex_lock(), and switch_mutex_unlock().

Referenced by switch_ssl_init_ssl_locks().

42 {
43  if (mode & CRYPTO_LOCK) {
45  }
46  else {
48  }
49 }
static switch_mutex_t ** ssl_mutexes
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
switch_byte_t switch_byte_t uint32_t switch_bitpack_mode_t mode

◆ switch_ssl_ssl_thread_id()

static void switch_ssl_ssl_thread_id ( CRYPTO_THREADID *  id)
inlinestatic

Definition at line 51 of file switch_core_cert.c.

References switch_thread_self().

Referenced by switch_ssl_init_ssl_locks().

52 {
53  CRYPTO_THREADID_set_numeric(id, (unsigned long)switch_thread_self());
54 }
switch_thread_id_t switch_thread_self(void)
Definition: switch_apr.c:102

Variable Documentation

◆ ssl_count

int ssl_count = 0
static

Definition at line 37 of file switch_core_cert.c.

Referenced by switch_ssl_destroy_ssl_locks(), and switch_ssl_init_ssl_locks().

◆ ssl_mutexes

switch_mutex_t** ssl_mutexes
static

◆ ssl_pool

switch_memory_pool_t* ssl_pool = NULL
static

Definition at line 36 of file switch_core_cert.c.

Referenced by switch_ssl_destroy_ssl_locks(), and switch_ssl_init_ssl_locks().