summaryrefslogtreecommitdiff
path: root/src/openssl_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openssl_stream.c')
-rw-r--r--src/openssl_stream.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index 54dd761ca..0705d90e7 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -31,6 +31,115 @@
#include <openssl/x509v3.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)
{
b->init = 1;
@@ -472,6 +581,17 @@ int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
#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)
{
GIT_UNUSED(out);