Sun May 20 06:33:54 2012

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 #include "asterisk.h"
00027 
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 353317 $")
00029 
00030 #ifdef HAVE_OPENSSL
00031 #include <openssl/ssl.h>
00032 #include <openssl/err.h>
00033 #endif
00034 
00035 #include <dlfcn.h>
00036 
00037 #include "asterisk/_private.h" /* ast_ssl_init() */
00038 
00039 #include "asterisk/utils.h"
00040 #include "asterisk/lock.h"
00041 
00042 #ifdef HAVE_OPENSSL
00043 
00044 #define get_OpenSSL_function(func) do { real_##func = dlsym(RTLD_NEXT, __stringify(func)); } while(0)
00045 
00046 static int startup_complete;
00047 
00048 static ast_mutex_t *ssl_locks;
00049 
00050 static int ssl_num_locks;
00051 
00052 static unsigned long ssl_threadid(void)
00053 {
00054    return (unsigned long) pthread_self();
00055 }
00056 
00057 static void ssl_lock(int mode, int n, const char *file, int line)
00058 {
00059    if (n < 0 || n >= ssl_num_locks) {
00060       ast_log(LOG_ERROR, "OpenSSL is full of LIES!!! - "
00061             "ssl_num_locks '%d' - n '%d'\n",
00062             ssl_num_locks, n);
00063       return;
00064    }
00065 
00066    if (mode & CRYPTO_LOCK) {
00067       ast_mutex_lock(&ssl_locks[n]);
00068    } else {
00069       ast_mutex_unlock(&ssl_locks[n]);
00070    }
00071 }
00072 
00073 int SSL_library_init(void)
00074 {
00075 #if defined(AST_DEVMODE)
00076    if (startup_complete) {
00077       ast_debug(1, "Called after startup... ignoring!\n");
00078    }
00079 #endif
00080    return 0;
00081 }
00082 
00083 void SSL_load_error_strings(void)
00084 {
00085 #if defined(AST_DEVMODE)
00086    if (startup_complete) {
00087       ast_debug(1, "Called after startup... ignoring!\n");
00088    }
00089 #endif
00090 }
00091 
00092 void ERR_load_SSL_strings(void)
00093 {
00094 #if defined(AST_DEVMODE)
00095    if (startup_complete) {
00096       ast_debug(1, "Called after startup... ignoring!\n");
00097    }
00098 #endif
00099 }
00100 
00101 void ERR_load_crypto_strings(void)
00102 {
00103 #if defined(AST_DEVMODE)
00104    if (startup_complete) {
00105       ast_debug(1, "Called after startup... ignoring!\n");
00106    }
00107 #endif
00108 }
00109 
00110 void ERR_load_BIO_strings(void)
00111 {
00112 #if defined(AST_DEVMODE)
00113    if (startup_complete) {
00114       ast_debug(1, "Called after startup... ignoring!\n");
00115    }
00116 #endif
00117 }
00118 
00119 void CRYPTO_set_id_callback(unsigned long (*func)(void))
00120 {
00121 #if defined(AST_DEVMODE)
00122    if (startup_complete) {
00123       ast_debug(1, "Called after startup... ignoring!\n");
00124    }
00125 #endif
00126 }
00127 
00128 void CRYPTO_set_locking_callback(void (*func)(int mode,int type, const char *file, int line))
00129 {
00130 #if defined(AST_DEVMODE)
00131    if (startup_complete) {
00132       ast_debug(1, "Called after startup... ignoring!\n");
00133    }
00134 #endif
00135 }
00136 
00137 void ERR_free_strings(void)
00138 {
00139    /* we can't allow this to be called, ever */
00140 }
00141 
00142 #endif /* HAVE_OPENSSL */
00143 
00144 /*!
00145  * \internal
00146  * \brief Common OpenSSL initialization for all of Asterisk.
00147  */
00148 int ast_ssl_init(void)
00149 {
00150 #ifdef HAVE_OPENSSL
00151    unsigned int i;
00152    int (*real_SSL_library_init)(void);
00153    void (*real_CRYPTO_set_id_callback)(unsigned long (*)(void));
00154    void (*real_CRYPTO_set_locking_callback)(void (*)(int, int, const char *, int));
00155    void (*real_SSL_load_error_strings)(void);
00156    void (*real_ERR_load_SSL_strings)(void);
00157    void (*real_ERR_load_crypto_strings)(void);
00158    void (*real_ERR_load_BIO_strings)(void);
00159    const char *errstr;
00160 
00161    /* clear any previous dynamic linker errors */
00162    dlerror();
00163    get_OpenSSL_function(SSL_library_init);
00164    if ((errstr = dlerror()) != NULL) {
00165       ast_debug(1, "unable to get real address of SSL_library_init: %s\n", errstr);
00166       /* there is no way to continue in this situation... SSL will
00167        * likely be broken in this process
00168        */
00169       return -1;
00170    } else {
00171       real_SSL_library_init();
00172    }
00173 
00174    /* Make OpenSSL usage thread-safe. */
00175 
00176    dlerror();
00177    get_OpenSSL_function(CRYPTO_set_id_callback);
00178    if ((errstr = dlerror()) != NULL) {
00179       ast_debug(1, "unable to get real address of CRYPTO_set_id_callback: %s\n", errstr);
00180       /* there is no way to continue in this situation... SSL will
00181        * likely be broken in this process
00182        */
00183       return -1;
00184    } else {
00185       real_CRYPTO_set_id_callback(ssl_threadid);
00186    }
00187 
00188    dlerror();
00189    get_OpenSSL_function(CRYPTO_set_locking_callback);
00190    if ((errstr = dlerror()) != NULL) {
00191       ast_debug(1, "unable to get real address of CRYPTO_set_locking_callback: %s\n", errstr);
00192       /* there is no way to continue in this situation... SSL will
00193        * likely be broken in this process
00194        */
00195       return -1;
00196    } else {
00197       ssl_num_locks = CRYPTO_num_locks();
00198       if (!(ssl_locks = ast_calloc(ssl_num_locks, sizeof(ssl_locks[0])))) {
00199          return -1;
00200       }
00201       for (i = 0; i < ssl_num_locks; i++) {
00202          ast_mutex_init(&ssl_locks[i]);
00203       }
00204       real_CRYPTO_set_locking_callback(ssl_lock);
00205    }
00206 
00207    /* after this point, we don't check for errors from the dlsym() calls,
00208     * under the assumption that if the ones above were successful, all
00209     * the rest will be too. this assumption holds as long as OpenSSL still
00210     * provides all of these functions.
00211     */
00212 
00213    get_OpenSSL_function(SSL_load_error_strings);
00214    real_SSL_load_error_strings();
00215 
00216    get_OpenSSL_function(ERR_load_SSL_strings);
00217    real_ERR_load_SSL_strings();
00218 
00219    get_OpenSSL_function(ERR_load_crypto_strings);
00220    real_ERR_load_crypto_strings();
00221 
00222    get_OpenSSL_function(ERR_load_BIO_strings);
00223    real_ERR_load_BIO_strings();
00224 
00225 #if 0
00226    /* currently this is just another call to SSL_library_init, so we don't call it */
00227    OpenSSL_add_all_algorithms();
00228 #endif
00229 
00230    startup_complete = 1;
00231 
00232 #endif /* HAVE_OPENSSL */
00233    return 0;
00234 }
00235 

Generated on Sun May 20 06:33:54 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6