GUACAMOLE-223: Merge thread safety fix for SSL.
This commit is contained in:
commit
c8fca94899
@ -225,7 +225,7 @@ then
|
|||||||
have_ssl=yes
|
have_ssl=yes
|
||||||
|
|
||||||
AC_CHECK_HEADER(openssl/ssl.h,, [have_ssl=no])
|
AC_CHECK_HEADER(openssl/ssl.h,, [have_ssl=no])
|
||||||
AC_CHECK_LIB([ssl], [SSL_CTX_new], [SSL_LIBS="$SSL_LIBS -lssl"], [have_ssl=no])
|
AC_CHECK_LIB([ssl], [SSL_CTX_new], [SSL_LIBS="$SSL_LIBS -lssl -lcrypto"], [have_ssl=no])
|
||||||
|
|
||||||
if test "x${have_ssl}" = "xno"
|
if test "x${have_ssl}" = "xno"
|
||||||
then
|
then
|
||||||
|
@ -152,6 +152,97 @@ static int daemonize() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SSL
|
||||||
|
/**
|
||||||
|
* Array of mutexes, used by OpenSSL.
|
||||||
|
*/
|
||||||
|
static pthread_mutex_t* guacd_openssl_locks = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by OpenSSL when locking or unlocking the Nth mutex.
|
||||||
|
*
|
||||||
|
* @param mode
|
||||||
|
* A bitmask denoting the action to be taken on the Nth lock, such as
|
||||||
|
* CRYPTO_LOCK or CRYPTO_UNLOCK.
|
||||||
|
*
|
||||||
|
* @param n
|
||||||
|
* The index of the lock to lock or unlock.
|
||||||
|
*
|
||||||
|
* @param file
|
||||||
|
* The filename of the function setting the lock, for debugging purposes.
|
||||||
|
*
|
||||||
|
* @param line
|
||||||
|
* The line number of the function setting the lock, for debugging
|
||||||
|
* purposes.
|
||||||
|
*/
|
||||||
|
static void guacd_openssl_locking_callback(int mode, int n,
|
||||||
|
const char* file, int line){
|
||||||
|
|
||||||
|
/* Lock given mutex upon request */
|
||||||
|
if (mode & CRYPTO_LOCK)
|
||||||
|
pthread_mutex_lock(&(guacd_openssl_locks[n]));
|
||||||
|
|
||||||
|
/* Unlock given mutex upon request */
|
||||||
|
else if (mode & CRYPTO_UNLOCK)
|
||||||
|
pthread_mutex_unlock(&(guacd_openssl_locks[n]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by OpenSSL when determining the current thread ID.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* An ID which uniquely identifies the current thread.
|
||||||
|
*/
|
||||||
|
static unsigned long guacd_openssl_id_callback() {
|
||||||
|
return (unsigned long) pthread_self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the given number of mutexes, such that OpenSSL will have at least
|
||||||
|
* this number of mutexes at its disposal.
|
||||||
|
*
|
||||||
|
* @param count
|
||||||
|
* The number of mutexes (locks) to create.
|
||||||
|
*/
|
||||||
|
static void guacd_openssl_init_locks(int count) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Allocate required number of locks */
|
||||||
|
guacd_openssl_locks =
|
||||||
|
malloc(sizeof(pthread_mutex_t) * count);
|
||||||
|
|
||||||
|
/* Initialize each lock */
|
||||||
|
for (i=0; i < count; i++)
|
||||||
|
pthread_mutex_init(&(guacd_openssl_locks[i]), NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees the given number of mutexes.
|
||||||
|
*
|
||||||
|
* @param count
|
||||||
|
* The number of mutexes (locks) to free.
|
||||||
|
*/
|
||||||
|
static void guacd_openssl_free_locks(int count) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* SSL lock array was not initialized */
|
||||||
|
if (guacd_openssl_locks == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Free all locks */
|
||||||
|
for (i=0; i < count; i++)
|
||||||
|
pthread_mutex_destroy(&(guacd_openssl_locks[i]));
|
||||||
|
|
||||||
|
/* Free lock array */
|
||||||
|
free(guacd_openssl_locks);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
/* Server */
|
/* Server */
|
||||||
@ -266,8 +357,14 @@ int main(int argc, char* argv[]) {
|
|||||||
/* Init SSL if enabled */
|
/* Init SSL if enabled */
|
||||||
if (config->key_file != NULL || config->cert_file != NULL) {
|
if (config->key_file != NULL || config->cert_file != NULL) {
|
||||||
|
|
||||||
/* Init SSL */
|
|
||||||
guacd_log(GUAC_LOG_INFO, "Communication will require SSL/TLS.");
|
guacd_log(GUAC_LOG_INFO, "Communication will require SSL/TLS.");
|
||||||
|
|
||||||
|
/* Init threadsafety in OpenSSL */
|
||||||
|
guacd_openssl_init_locks(CRYPTO_num_locks());
|
||||||
|
CRYPTO_set_id_callback(guacd_openssl_id_callback);
|
||||||
|
CRYPTO_set_locking_callback(guacd_openssl_locking_callback);
|
||||||
|
|
||||||
|
/* Init SSL */
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
ssl_context = SSL_CTX_new(SSLv23_server_method());
|
ssl_context = SSL_CTX_new(SSLv23_server_method());
|
||||||
@ -391,6 +488,13 @@ int main(int argc, char* argv[]) {
|
|||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SSL
|
||||||
|
if (ssl_context != NULL) {
|
||||||
|
guacd_openssl_free_locks(CRYPTO_num_locks());
|
||||||
|
SSL_CTX_free(ssl_context);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,7 @@ static int __guac_socket_ssl_free_handler(guac_socket* socket) {
|
|||||||
/* Shutdown SSL */
|
/* Shutdown SSL */
|
||||||
guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
|
guac_socket_ssl_data* data = (guac_socket_ssl_data*) socket->data;
|
||||||
SSL_shutdown(data->ssl);
|
SSL_shutdown(data->ssl);
|
||||||
|
SSL_free(data->ssl);
|
||||||
|
|
||||||
/* Close file descriptor */
|
/* Close file descriptor */
|
||||||
close(data->fd);
|
close(data->fd);
|
||||||
@ -117,23 +118,29 @@ static int __guac_socket_ssl_free_handler(guac_socket* socket) {
|
|||||||
|
|
||||||
guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd) {
|
guac_socket* guac_socket_open_secure(SSL_CTX* context, int fd) {
|
||||||
|
|
||||||
|
/* Create new SSL structure */
|
||||||
|
SSL* ssl = SSL_new(context);
|
||||||
|
if (ssl == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Allocate socket and associated data */
|
/* Allocate socket and associated data */
|
||||||
guac_socket* socket = guac_socket_alloc();
|
guac_socket* socket = guac_socket_alloc();
|
||||||
guac_socket_ssl_data* data = malloc(sizeof(guac_socket_ssl_data));
|
guac_socket_ssl_data* data = malloc(sizeof(guac_socket_ssl_data));
|
||||||
|
|
||||||
/* Init SSL */
|
/* Init SSL */
|
||||||
data->context = context;
|
data->context = context;
|
||||||
data->ssl = SSL_new(context);
|
data->ssl = ssl;
|
||||||
SSL_set_fd(data->ssl, fd);
|
SSL_set_fd(data->ssl, fd);
|
||||||
|
|
||||||
/* Accept SSL connection, handle errors */
|
/* Accept SSL connection, handle errors */
|
||||||
if (SSL_accept(data->ssl) <= 0) {
|
if (SSL_accept(ssl) <= 0) {
|
||||||
|
|
||||||
guac_error = GUAC_STATUS_INTERNAL_ERROR;
|
guac_error = GUAC_STATUS_INTERNAL_ERROR;
|
||||||
guac_error_message = "SSL accept failed";
|
guac_error_message = "SSL accept failed";
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
guac_socket_free(socket);
|
guac_socket_free(socket);
|
||||||
|
SSL_free(ssl);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user