summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2014-06-12 16:20:52 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2014-06-12 16:58:25 +0200
commit081e76bac26e1ed6adafb402d15b30c622866d61 (patch)
treeb7e5ea0fc44590bce64b373a0fdf05191b302aad
parent8f897b6f2f4742a7d9189528e082cfe7cecd6f29 (diff)
downloadlibgit2-cmn/init-ssl-once.tar.gz
ssl: init everything all the timecmn/init-ssl-once
Bring together all of the OpenSSL initialization to git_threads_init() so it's together and doesn't need locks. Moving it here also gives us libssh2 thread safety (when built against openssl).
-rw-r--r--src/global.c53
-rw-r--r--src/global.h2
-rw-r--r--src/netops.c83
3 files changed, 51 insertions, 87 deletions
diff --git a/src/global.c b/src/global.c
index 41428ec42..b144b050a 100644
--- a/src/global.c
+++ b/src/global.c
@@ -19,11 +19,9 @@ git_mutex git__mwindow_mutex;
#ifdef GIT_SSL
# include <openssl/ssl.h>
SSL_CTX *git__ssl_ctx;
+static git_mutex *openssl_locks;
#endif
-git_mutex git__ssl_mutex;
-git_atomic git__ssl_init;
-
static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
static git_atomic git__n_shutdown_callbacks;
static git_atomic git__n_inits;
@@ -47,12 +45,59 @@ static void git__shutdown(void)
}
+#if defined(GIT_THREADS) && defined(GIT_SSL)
+void openssl_locking_function(int mode, int n, const char *file, int line)
+{
+ int lock;
+
+ GIT_UNUSED(file);
+ GIT_UNUSED(line);
+
+ lock = mode & CRYPTO_LOCK;
+
+ if (lock) {
+ git_mutex_lock(&openssl_locks[n]);
+ } else {
+ git_mutex_unlock(&openssl_locks[n]);
+ }
+}
+#endif
+
+
static void init_ssl(void)
{
#ifdef GIT_SSL
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
git__ssl_ctx = SSL_CTX_new(SSLv23_method());
+ SSL_CTX_set_mode(git__ssl_ctx, SSL_MODE_AUTO_RETRY);
+ SSL_CTX_set_verify(git__ssl_ctx, SSL_VERIFY_NONE, NULL);
+ if (!SSL_CTX_set_default_verify_paths(git__ssl_ctx)) {
+ SSL_CTX_free(git__ssl_ctx);
+ git__ssl_ctx = NULL;
+ }
+
+# ifdef GIT_THREADS
+ {
+ int num_locks, i;
+
+ num_locks = CRYPTO_num_locks();
+ openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
+ if (openssl_locks == NULL) {
+ SSL_CTX_free(git__ssl_ctx);
+ git__ssl_ctx = NULL;
+ }
+
+ for (i = 0; i < num_locks; i++) {
+ if (git_mutex_init(&openssl_locks[i]) != 0) {
+ SSL_CTX_free(git__ssl_ctx);
+ git__ssl_ctx = NULL;
+ }
+ }
+
+ CRYPTO_set_locking_callback(openssl_locking_function);
+ }
+# endif
#endif
}
@@ -183,8 +228,6 @@ static void init_once(void)
{
if ((init_error = git_mutex_init(&git__mwindow_mutex)) != 0)
return;
- if ((init_error = git_mutex_init(&git__ssl_mutex)) != 0)
- return;
pthread_key_create(&_tls_key, &cb__free_status);
diff --git a/src/global.h b/src/global.h
index 8904e2de5..745df3e4a 100644
--- a/src/global.h
+++ b/src/global.h
@@ -23,8 +23,6 @@ extern SSL_CTX *git__ssl_ctx;
git_global_st *git__global_state(void);
extern git_mutex git__mwindow_mutex;
-extern git_mutex git__ssl_mutex;
-extern git_atomic git__ssl_init;
#define GIT_GLOBAL (git__global_state())
diff --git a/src/netops.c b/src/netops.c
index 54804d418..965e4775d 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -35,11 +35,6 @@
#include "http_parser.h"
#include "global.h"
-#if defined(GIT_SSL) && defined(GIT_THREADS)
-/* OpenSSL wants us to keep an array of locks */
-static git_mutex *openssl_locks;
-#endif
-
#ifdef GIT_WIN32
static void net_set_error(const char *str)
{
@@ -391,86 +386,14 @@ cert_fail_name:
return -1;
}
-#ifdef GIT_THREADS
-void openssl_locking_function(int mode, int n, const char *file, int line)
-{
- int lock;
-
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- lock = mode & CRYPTO_LOCK;
-
- if (lock) {
- git_mutex_lock(&openssl_locks[n]);
- } else {
- git_mutex_unlock(&openssl_locks[n]);
- }
-}
-#endif
-
-/**
- * The OpenSSL init functions are not reentrant so we need to init
- * them under lock.
- */
-static int init_ssl(void)
-{
- if (git__ssl_init.val)
- return 0;
-
- if (git_mutex_lock(&git__ssl_mutex) < 0) {
- giterr_set(GITERR_OS, "failed to acquire ssl init lock");
- return -1;
- }
-
- /* if we had to wait for the lock, someone else did it, we can return */
- if (git__ssl_init.val)
- return 0;
-
- SSL_CTX_set_mode(git__ssl_ctx, SSL_MODE_AUTO_RETRY);
- SSL_CTX_set_verify(git__ssl_ctx, SSL_VERIFY_NONE, NULL);
- if (!SSL_CTX_set_default_verify_paths(git__ssl_ctx)) {
- unsigned long err = ERR_get_error();
- giterr_set(GITERR_SSL, "failed to set verify paths: %s\n", ERR_error_string(err, NULL));
- return -1;
- }
-
-#ifdef GIT_THREADS
- {
- int num_locks, i;
-
- num_locks = CRYPTO_num_locks();
- openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
- if (openssl_locks == NULL) {
- git_mutex_unlock(&git__ssl_mutex);
- return -1;
- }
- GITERR_CHECK_ALLOC(openssl_locks);
-
- for (i = 0; i < num_locks; i++) {
- if (git_mutex_init(&openssl_locks[i]) != 0) {
- git_mutex_unlock(&git__ssl_mutex);
- giterr_set(GITERR_SSL, "failed to init lock %d", i);
- return -1;
- }
- }
- }
-
- CRYPTO_set_locking_callback(openssl_locking_function);
-#endif
-
- git_atomic_inc(&git__ssl_init);
- git_mutex_unlock(&git__ssl_mutex);
-
- return 0;
-}
-
static int ssl_setup(gitno_socket *socket, const char *host, int flags)
{
int ret;
- if (init_ssl() < 0)
+ if (git__ssl_ctx == NULL) {
+ giterr_set(GITERR_NET, "OpenSSL initialization failed");
return -1;
+ }
socket->ssl.ssl = SSL_new(git__ssl_ctx);
if (socket->ssl.ssl == NULL)