Sat Apr 26 2014 22:01:37

Asterisk developer's documentation


libasteriskssl.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2009-2012, Digium, Inc.
00005  *
00006  * Russell Bryant <russell@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*!
00020  * \file
00021  * \brief Common OpenSSL support code
00022  *
00023  * \author Russell Bryant <russell@digium.com>
00024  */
00025 
00026 /*** MODULEINFO
00027    <support_level>core</support_level>
00028  ***/
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 373079 $")
00033 
00034 #ifdef HAVE_OPENSSL
00035 #include <openssl/ssl.h>
00036 #include <openssl/err.h>
00037 #endif
00038 
00039 #include <dlfcn.h>
00040 
00041 #include "asterisk/_private.h" /* ast_ssl_init() */
00042 
00043 #include "asterisk/utils.h"
00044 #include "asterisk/lock.h"
00045 
00046 #ifdef HAVE_OPENSSL
00047 
00048 #define get_OpenSSL_function(func) do { real_##func = dlsym(RTLD_NEXT, __stringify(func)); } while(0)
00049 
00050 static int startup_complete;
00051 
00052 static ast_mutex_t *ssl_locks;
00053 
00054 static int ssl_num_locks;
00055 
00056 static unsigned long ssl_threadid(void)
00057 {
00058    return (unsigned long) pthread_self();
00059 }
00060 
00061 static void ssl_lock(int mode, int n, const char *file, int line)
00062 {
00063    if (n < 0 || n >= ssl_num_locks) {
00064       ast_log(LOG_ERROR, "OpenSSL is full of LIES!!! - "
00065             "ssl_num_locks '%d' - n '%d'\n",
00066             ssl_num_locks, n);
00067       return;
00068    }
00069 
00070    if (mode & CRYPTO_LOCK) {
00071       ast_mutex_lock(&ssl_locks[n]);
00072    } else {
00073       ast_mutex_unlock(&ssl_locks[n]);
00074    }
00075 }
00076 
00077 int SSL_library_init(void)
00078 {
00079 #if defined(AST_DEVMODE)
00080    if (startup_complete) {
00081       ast_debug(1, "Called after startup... ignoring!\n");
00082    }
00083 #endif
00084    return 1;
00085 }
00086 
00087 void SSL_load_error_strings(void)
00088 {
00089 #if defined(AST_DEVMODE)
00090    if (startup_complete) {
00091       ast_debug(1, "Called after startup... ignoring!\n");
00092    }
00093 #endif
00094 }
00095 
00096 void ERR_load_SSL_strings(void)
00097 {
00098 #if defined(AST_DEVMODE)
00099    if (startup_complete) {
00100       ast_debug(1, "Called after startup... ignoring!\n");
00101    }
00102 #endif
00103 }
00104 
00105 void ERR_load_crypto_strings(void)
00106 {
00107 #if defined(AST_DEVMODE)
00108    if (startup_complete) {
00109       ast_debug(1, "Called after startup... ignoring!\n");
00110    }
00111 #endif
00112 }
00113 
00114 void ERR_load_BIO_strings(void)
00115 {
00116 #if defined(AST_DEVMODE)
00117    if (startup_complete) {
00118       ast_debug(1, "Called after startup... ignoring!\n");
00119    }
00120 #endif
00121 }
00122 
00123 void CRYPTO_set_id_callback(unsigned long (*func)(void))
00124 {
00125 #if defined(AST_DEVMODE)
00126    if (startup_complete) {
00127       ast_debug(1, "Called after startup... ignoring!\n");
00128    }
00129 #endif
00130 }
00131 
00132 void CRYPTO_set_locking_callback(void (*func)(int mode,int type, const char *file, int line))
00133 {
00134 #if defined(AST_DEVMODE)
00135    if (startup_complete) {
00136       ast_debug(1, "Called after startup... ignoring!\n");
00137    }
00138 #endif
00139 }
00140 
00141 void ERR_free_strings(void)
00142 {
00143    /* we can't allow this to be called, ever */
00144 }
00145 
00146 #endif /* HAVE_OPENSSL */
00147 
00148 /*!
00149  * \internal
00150  * \brief Common OpenSSL initialization for all of Asterisk.
00151  */
00152 int ast_ssl_init(void)
00153 {
00154 #ifdef HAVE_OPENSSL
00155    unsigned int i;
00156    int (*real_SSL_library_init)(void);
00157    void (*real_CRYPTO_set_id_callback)(unsigned long (*)(void));
00158    void (*real_CRYPTO_set_locking_callback)(void (*)(int, int, const char *, int));
00159    void (*real_SSL_load_error_strings)(void);
00160    void (*real_ERR_load_SSL_strings)(void);
00161    void (*real_ERR_load_BIO_strings)(void);
00162    const char *errstr;
00163 
00164    /* clear any previous dynamic linker errors */
00165    dlerror();
00166    get_OpenSSL_function(SSL_library_init);
00167    if ((errstr = dlerror()) != NULL) {
00168       ast_debug(1, "unable to get real address of SSL_library_init: %s\n", errstr);
00169       /* there is no way to continue in this situation... SSL will
00170        * likely be broken in this process
00171        */
00172       return -1;
00173    } else {
00174       real_SSL_library_init();
00175    }
00176 
00177    /* Make OpenSSL usage thread-safe. */
00178 
00179    dlerror();
00180    get_OpenSSL_function(CRYPTO_set_id_callback);
00181    if ((errstr = dlerror()) != NULL) {
00182       ast_debug(1, "unable to get real address of CRYPTO_set_id_callback: %s\n", errstr);
00183       /* there is no way to continue in this situation... SSL will
00184        * likely be broken in this process
00185        */
00186       return -1;
00187    } else {
00188       real_CRYPTO_set_id_callback(ssl_threadid);
00189    }
00190 
00191    dlerror();
00192    get_OpenSSL_function(CRYPTO_set_locking_callback);
00193    if ((errstr = dlerror()) != NULL) {
00194       ast_debug(1, "unable to get real address of CRYPTO_set_locking_callback: %s\n", errstr);
00195       /* there is no way to continue in this situation... SSL will
00196        * likely be broken in this process
00197        */
00198       return -1;
00199    } else {
00200       ssl_num_locks = CRYPTO_num_locks();
00201       if (!(ssl_locks = ast_calloc(ssl_num_locks, sizeof(ssl_locks[0])))) {
00202          return -1;
00203       }
00204       for (i = 0; i < ssl_num_locks; i++) {
00205          ast_mutex_init(&ssl_locks[i]);
00206       }
00207       real_CRYPTO_set_locking_callback(ssl_lock);
00208    }
00209 
00210    /* after this point, we don't check for errors from the dlsym() calls,
00211     * under the assumption that if the ones above were successful, all
00212     * the rest will be too. this assumption holds as long as OpenSSL still
00213     * provides all of these functions.
00214     */
00215 
00216    get_OpenSSL_function(SSL_load_error_strings);
00217    real_SSL_load_error_strings();
00218 
00219    get_OpenSSL_function(ERR_load_SSL_strings);
00220    real_ERR_load_SSL_strings();
00221 
00222    get_OpenSSL_function(ERR_load_BIO_strings);
00223    real_ERR_load_BIO_strings();
00224 
00225    startup_complete = 1;
00226 
00227 #endif /* HAVE_OPENSSL */
00228    return 0;
00229 }
00230