Commit 8a6d6677 by Edward Thomson

global: make openssl registration like the rest

parent bad2702c
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
#include "global.h" #include "global.h"
#include "hash.h" #include "hash.h"
#include "sysdir.h" #include "sysdir.h"
#include "git2/global.h" #include "filter.h"
#include "git2/sys/openssl.h" #include "openssl_stream.h"
#include "thread-utils.h" #include "thread-utils.h"
#include "git2/global.h"
#if defined(GIT_MSVC_CRTDBG) #if defined(GIT_MSVC_CRTDBG)
#include "win32/w32_stack.h" #include "win32/w32_stack.h"
#include "win32/w32_crtdbg_stacktrace.h" #include "win32/w32_crtdbg_stacktrace.h"
...@@ -33,9 +35,6 @@ static git_atomic git__n_shutdown_callbacks; ...@@ -33,9 +35,6 @@ static git_atomic git__n_shutdown_callbacks;
static git_atomic git__n_inits; static git_atomic git__n_inits;
char *git__user_agent; char *git__user_agent;
static int init_ssl(void);
static void shutdown_ssl(void);
void git__on_shutdown(git_global_shutdown_fn callback) void git__on_shutdown(git_global_shutdown_fn callback)
{ {
int count = git_atomic_inc(&git__n_shutdown_callbacks); int count = git_atomic_inc(&git__n_shutdown_callbacks);
...@@ -65,8 +64,8 @@ static int init_common(void) ...@@ -65,8 +64,8 @@ static int init_common(void)
/* Initialize any other subsystems that have global state */ /* Initialize any other subsystems that have global state */
if ((ret = git_hash_global_init()) == 0 && if ((ret = git_hash_global_init()) == 0 &&
(ret = git_sysdir_global_init()) == 0 && (ret = git_sysdir_global_init()) == 0 &&
(ret = init_ssl()) == 0) { (ret = git_filter_global_init()) == 0)
} ret = git_openssl_stream_global_init();
GIT_MEMORY_BARRIER; GIT_MEMORY_BARRIER;
...@@ -89,8 +88,6 @@ static void shutdown_common(void) ...@@ -89,8 +88,6 @@ static void shutdown_common(void)
cb(); cb();
} }
shutdown_ssl();
git__free(git__user_agent); git__free(git__user_agent);
#if defined(GIT_MSVC_CRTDBG) #if defined(GIT_MSVC_CRTDBG)
...@@ -99,112 +96,6 @@ static void shutdown_common(void) ...@@ -99,112 +96,6 @@ static void shutdown_common(void)
#endif #endif
} }
#if defined(GIT_THREADS) && defined(GIT_OPENSSL)
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]);
}
}
static void shutdown_ssl_locking(void)
{
int num_locks, i;
num_locks = CRYPTO_num_locks();
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < num_locks; ++i)
git_mutex_free(openssl_locks);
git__free(openssl_locks);
}
#endif
static int init_ssl(void)
{
#ifdef GIT_OPENSSL
long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
/* Older OpenSSL and MacOS OpenSSL doesn't have this */
#ifdef SSL_OP_NO_COMPRESSION
ssl_opts |= SSL_OP_NO_COMPRESSION;
#endif
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
/*
* Load SSLv{2,3} and TLSv1 so that we can talk with servers
* which use the SSL hellos, which are often used for
* compatibility. We then disable SSL so we only allow OpenSSL
* to speak TLSv1 to perform the encryption itself.
*/
git__ssl_ctx = SSL_CTX_new(SSLv23_method());
SSL_CTX_set_options(git__ssl_ctx, ssl_opts);
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;
return -1;
}
#endif
return 0;
}
/**
* This function aims to clean-up the SSL context which
* we allocated.
*/
static void shutdown_ssl(void)
{
#ifdef GIT_OPENSSL
if (git__ssl_ctx) {
SSL_CTX_free(git__ssl_ctx);
git__ssl_ctx = NULL;
}
#endif
}
int git_openssl_set_locking(void)
{
#ifdef GIT_OPENSSL
# ifdef GIT_THREADS
int num_locks, i;
num_locks = CRYPTO_num_locks();
openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
GITERR_CHECK_ALLOC(openssl_locks);
for (i = 0; i < num_locks; i++) {
if (git_mutex_init(&openssl_locks[i]) != 0) {
giterr_set(GITERR_SSL, "failed to initialize openssl locks");
return -1;
}
}
CRYPTO_set_locking_callback(openssl_locking_function);
git__on_shutdown(shutdown_ssl_locking);
return 0;
# else
giterr_set(GITERR_THREAD, "libgit2 as not built with threads");
return -1;
# endif
#else
giterr_set(GITERR_SSL, "libgit2 was not built with OpenSSL support");
return -1;
#endif
}
/** /**
* Handle the global state with TLS * Handle the global state with TLS
* *
......
...@@ -31,6 +31,115 @@ ...@@ -31,6 +31,115 @@
#include <openssl/x509v3.h> #include <openssl/x509v3.h>
#include <openssl/bio.h> #include <openssl/bio.h>
SSL_CTX *git__ssl_ctx;
#ifdef GIT_THREADS
static git_mutex *openssl_locks;
static 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]);
}
}
static void shutdown_ssl_locking(void)
{
int num_locks, i;
num_locks = CRYPTO_num_locks();
CRYPTO_set_locking_callback(NULL);
for (i = 0; i < num_locks; ++i)
git_mutex_free(openssl_locks);
git__free(openssl_locks);
}
#endif /* GIT_THREADS */
/**
* This function aims to clean-up the SSL context which
* we allocated.
*/
static void shutdown_ssl(void)
{
if (git__ssl_ctx) {
SSL_CTX_free(git__ssl_ctx);
git__ssl_ctx = NULL;
}
}
int git_openssl_stream_global_init(void)
{
#ifdef GIT_OPENSSL
long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
/* Older OpenSSL and MacOS OpenSSL doesn't have this */
#ifdef SSL_OP_NO_COMPRESSION
ssl_opts |= SSL_OP_NO_COMPRESSION;
#endif
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
/*
* Load SSLv{2,3} and TLSv1 so that we can talk with servers
* which use the SSL hellos, which are often used for
* compatibility. We then disable SSL so we only allow OpenSSL
* to speak TLSv1 to perform the encryption itself.
*/
git__ssl_ctx = SSL_CTX_new(SSLv23_method());
SSL_CTX_set_options(git__ssl_ctx, ssl_opts);
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;
return -1;
}
#endif
git__on_shutdown(shutdown_ssl);
return 0;
}
int git_openssl_set_locking(void)
{
#ifdef GIT_THREADS
int num_locks, i;
num_locks = CRYPTO_num_locks();
openssl_locks = git__calloc(num_locks, sizeof(git_mutex));
GITERR_CHECK_ALLOC(openssl_locks);
for (i = 0; i < num_locks; i++) {
if (git_mutex_init(&openssl_locks[i]) != 0) {
giterr_set(GITERR_SSL, "failed to initialize openssl locks");
return -1;
}
}
CRYPTO_set_locking_callback(openssl_locking_function);
git__on_shutdown(shutdown_ssl_locking);
return 0;
#else
giterr_set(GITERR_THREAD, "libgit2 as not built with threads");
return -1;
#endif
}
static int bio_create(BIO *b) static int bio_create(BIO *b)
{ {
b->init = 1; b->init = 1;
...@@ -472,6 +581,17 @@ int git_openssl_stream_new(git_stream **out, const char *host, const char *port) ...@@ -472,6 +581,17 @@ int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
#include "stream.h" #include "stream.h"
int git_openssl_stream_global_init(void)
{
return 0;
}
int git_openssl_set_locking(void)
{
giterr_set(GITERR_SSL, "libgit2 was not built with OpenSSL support");
return -1;
}
int git_openssl_stream_new(git_stream **out, const char *host, const char *port) int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
{ {
GIT_UNUSED(out); GIT_UNUSED(out);
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "git2/sys/stream.h" #include "git2/sys/stream.h"
extern int git_openssl_stream_global_init(void);
extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port); extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment