From fbcf8a1e0d2ee9258d4b1573534746529dfdd2f7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Thu, 9 Jul 2015 12:02:31 -0700 Subject: [PATCH] GUAC-1171: Move initialization of SSH, OpenSSL, etc. to common SSH base. --- src/common-ssh/guac_ssh.c | 104 ++++++++++++++++++++++++++++++++- src/common-ssh/guac_ssh.h | 15 ++++- src/protocols/ssh/ssh_client.c | 75 ++---------------------- 3 files changed, 120 insertions(+), 74 deletions(-) diff --git a/src/common-ssh/guac_ssh.c b/src/common-ssh/guac_ssh.c index 694806b5..6a85decd 100644 --- a/src/common-ssh/guac_ssh.c +++ b/src/common-ssh/guac_ssh.c @@ -26,8 +26,108 @@ #include #include -void guac_common_ssh_init() { - /* STUB */ +#ifdef LIBSSH2_USES_GCRYPT +#include +#endif + +#include +#include + +#include + +#ifdef LIBSSH2_USES_GCRYPT +GCRY_THREAD_OPTION_PTHREAD_IMPL; +#endif + +/** + * Array of mutexes, used by OpenSSL. + */ +static pthread_mutex_t* guac_common_ssh_openssl_locks; + +/** + * Called by OpenSSL when locking or unlocking the Nth mutex. + */ +static void guac_common_ssh_openssl_locking_callback(int mode, int n, + const char* file, int line){ + + /* Lock given mutex upon request */ + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(&(guac_common_ssh_openssl_locks[n])); + + /* Unlock given mutex upon request */ + else if (mode & CRYPTO_UNLOCK) + pthread_mutex_unlock(&(guac_common_ssh_openssl_locks[n])); + +} + +/** + * Called by OpenSSL when determining the current thread ID. + */ +static unsigned long guac_common_ssh_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. + */ +static void guac_common_ssh_openssl_init_locks(int count) { + + int i; + + /* Allocate required number of locks */ + guac_common_ssh_openssl_locks = + malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); + + /* Initialize each lock */ + for (i=0; i < count; i++) + pthread_mutex_init(&(guac_common_ssh_openssl_locks[i]), NULL); + +} + +/** + * Frees the given number of mutexes. + */ +static void guac_common_ssh_openssl_free_locks(int count) { + + int i; + + /* Free all locks */ + for (i=0; i < count; i++) + pthread_mutex_destroy(&(guac_common_ssh_openssl_locks[i])); + +} + +int guac_common_ssh_init(guac_client* client) { + +#ifdef LIBSSH2_USES_GCRYPT + /* Init threadsafety in libgcrypt */ + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + if (!gcry_check_version(GCRYPT_VERSION)) { + guac_client_log(client, GUAC_LOG_ERROR, "libgcrypt version mismatch."); + return 1; + } +#endif + + /* Init threadsafety in OpenSSL */ + guac_common_ssh_openssl_init_locks(CRYPTO_num_locks()); + CRYPTO_set_id_callback(guac_common_ssh_openssl_id_callback); + CRYPTO_set_locking_callback(guac_common_ssh_openssl_locking_callback); + + /* Init OpenSSL */ + SSL_library_init(); + ERR_load_crypto_strings(); + + /* Init libssh2 */ + libssh2_init(0); + + /* Success */ + return 0; + +} + +void guac_common_ssh_uninit() { + guac_common_ssh_openssl_free_locks(CRYPTO_num_locks()); } LIBSSH2_SESSION* guac_common_ssh_connect_password(const char* hostname, diff --git a/src/common-ssh/guac_ssh.h b/src/common-ssh/guac_ssh.h index eea8ca8a..302d6f0e 100644 --- a/src/common-ssh/guac_ssh.h +++ b/src/common-ssh/guac_ssh.h @@ -31,8 +31,21 @@ * Initializes the underlying SSH and encryption libraries used by Guacamole. * This function must be called before any other guac_common_ssh_*() functions * are called. + * + * @param client + * The Guacamole client that will be using SSH. + * + * @return + * Zero if initialization, or non-zero if an error occurs. */ -void guac_common_ssh_init(); +int guac_common_ssh_init(guac_client* client); + +/** + * Cleans up the underlying SSH and encryption libraries used by Guacamole. + * This function must be called once no other guac_common_ssh_*() functions + * will be used. + */ +void guac_common_ssh_uninit(); /** * Connects to the SSH server running at the given hostname and port using the diff --git a/src/protocols/ssh/ssh_client.c b/src/protocols/ssh/ssh_client.c index 24f5fd8d..301f83e0 100644 --- a/src/protocols/ssh/ssh_client.c +++ b/src/protocols/ssh/ssh_client.c @@ -23,6 +23,7 @@ #include "config.h" #include "client.h" +#include "guac_ssh.h" #include "sftp.h" #include "ssh_key.h" #include "terminal.h" @@ -270,59 +271,6 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client, } -#ifdef LIBSSH2_USES_GCRYPT -GCRY_THREAD_OPTION_PTHREAD_IMPL; -#endif - -/** - * Array of mutexes, used by OpenSSL. - */ -static pthread_mutex_t* __openssl_locks; - -/** - * Called by OpenSSL when locking or unlocking the Nth mutex. - */ -static void __openssl_locking_callback(int mode, int n, const char* file, int line){ - if (mode & CRYPTO_LOCK) - pthread_mutex_lock(&(__openssl_locks[n])); - else if (mode & CRYPTO_UNLOCK) - pthread_mutex_unlock(&(__openssl_locks[n])); -} - -/** - * Called by OpenSSL when determining the current thread ID. - */ -static unsigned long __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. - */ -static void __openssl_init_locks(int count) { - - int i; - - __openssl_locks = malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); - - for (i=0; iusername[0] == 0) @@ -574,8 +507,8 @@ void* ssh_client_thread(void* data) { guac_client_stop(client); pthread_join(input_thread, NULL); - __openssl_free_locks(CRYPTO_num_locks()); pthread_mutex_destroy(&client_data->term_channel_lock); + guac_common_ssh_uninit(); guac_client_log(client, GUAC_LOG_INFO, "SSH connection ended."); return NULL;