summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-08-11 01:30:38 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2021-08-12 23:08:19 +0100
commite9c4caa8f4b5a004c56189a6f83395f809e8cbf8 (patch)
treeb2847f96fc1c72463741caa31a10a7b1f67433eb
parent806778dc482e40d26bc7a9d44ccd18b888f6ec33 (diff)
downloadlibgit2-ethomson/ssl_refactor.tar.gz
openssl: dynamically load libssl and symbols (optionally)ethomson/ssl_refactor
Provide an interface around OpenSSL to dynamically load the libraries and symbols, so that users can distribute a libgit2 library that is not linked directly against OpenSSL. This enables users to target multiple distributions with a single binary. This mechanism is optional and disabled by default. Configure cmake with -DUSE_HTTPS=OpenSSL-Dynamic to use it.
-rw-r--r--COPYING110
-rw-r--r--cmake/SelectHTTPSBackend.cmake4
-rw-r--r--src/features.h.in1
-rw-r--r--src/libgit2.c8
-rw-r--r--src/netops.h2
-rw-r--r--src/streams/openssl.c18
-rw-r--r--src/streams/openssl.h10
-rw-r--r--src/streams/openssl_dynamic.c304
-rw-r--r--src/streams/openssl_dynamic.h347
-rw-r--r--src/streams/openssl_legacy.c77
-rw-r--r--src/streams/openssl_legacy.h57
11 files changed, 875 insertions, 63 deletions
diff --git a/COPYING b/COPYING
index c0f61fb91..6bb39b0c1 100644
--- a/COPYING
+++ b/COPYING
@@ -420,7 +420,7 @@ The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
-
+
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
@@ -1019,3 +1019,111 @@ following restrictions are are met:
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+----------------------------------------------------------------------
+
+Portions of the OpenSSL headers are included under the OpenSSL license:
+
+Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+All rights reserved.
+
+This package is an SSL implementation written
+by Eric Young (eay@cryptsoft.com).
+The implementation was written so as to conform with Netscapes SSL.
+
+This library is free for commercial and non-commercial use as long as
+the following conditions are aheared to. The following conditions
+apply to all code found in this distribution, be it the RC4, RSA,
+lhash, DES, etc., code; not just the SSL code. The SSL documentation
+included with this distribution is covered by the same copyright terms
+except that the holder is Tim Hudson (tjh@cryptsoft.com).
+
+Copyright remains Eric Young's, and as such any Copyright notices in
+the code are not to be removed.
+If this package is used in a product, Eric Young should be given attribution
+as the author of the parts of the library used.
+This can be in the form of a textual message at program startup or
+in documentation (online or textual) provided with the package.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ "This product includes cryptographic software written by
+ Eric Young (eay@cryptsoft.com)"
+ The word 'cryptographic' can be left out if the rouines from the library
+ being used are not cryptographic related :-).
+4. If you include any Windows specific code (or a derivative thereof) from
+ the apps directory (application code) you must include an acknowledgement:
+ "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+
+THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+The licence and distribution terms for any publically available version or
+derivative of this code cannot be changed. i.e. this code cannot simply be
+copied and put under another distribution licence
+[including the GNU Public Licence.]
+
+====================================================================
+Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+3. All advertising materials mentioning features or use of this
+ software must display the following acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+
+4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ endorse or promote products derived from this software without
+ prior written permission. For written permission, please contact
+ openssl-core@openssl.org.
+
+5. Products derived from this software may not be called "OpenSSL"
+ nor may "OpenSSL" appear in their names without prior written
+ permission of the OpenSSL Project.
+
+6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes software developed by the OpenSSL Project
+ for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+
+THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/cmake/SelectHTTPSBackend.cmake b/cmake/SelectHTTPSBackend.cmake
index afbeac424..4998f0f2a 100644
--- a/cmake/SelectHTTPSBackend.cmake
+++ b/cmake/SelectHTTPSBackend.cmake
@@ -108,6 +108,10 @@ IF(USE_HTTPS)
LIST(APPEND LIBGIT2_PC_LIBS ${MBEDTLS_LIBRARIES})
ELSEIF (USE_HTTPS STREQUAL "WinHTTP")
# WinHTTP setup was handled in the WinHTTP-specific block above
+ ELSEIF (USE_HTTPS STREQUAL "OpenSSL-Dynamic")
+ SET(GIT_OPENSSL 1)
+ SET(GIT_OPENSSL_DYNAMIC 1)
+ LIST(APPEND LIBGIT2_LIBS dl)
ELSE()
MESSAGE(FATAL_ERROR "Asked for backend ${USE_HTTPS} but it wasn't found")
ENDIF()
diff --git a/src/features.h.in b/src/features.h.in
index ab523f90b..41f2734ac 100644
--- a/src/features.h.in
+++ b/src/features.h.in
@@ -34,6 +34,7 @@
#cmakedefine GIT_WINHTTP 1
#cmakedefine GIT_HTTPS 1
#cmakedefine GIT_OPENSSL 1
+#cmakedefine GIT_OPENSSL_DYNAMIC 1
#cmakedefine GIT_SECURE_TRANSPORT 1
#cmakedefine GIT_MBEDTLS 1
diff --git a/src/libgit2.c b/src/libgit2.c
index 089c83590..aee9cf2cd 100644
--- a/src/libgit2.c
+++ b/src/libgit2.c
@@ -36,14 +36,6 @@
# include "win32/w32_leakcheck.h"
#endif
-#ifdef GIT_OPENSSL
-# include <openssl/err.h>
-#endif
-
-#ifdef GIT_MBEDTLS
-# include <mbedtls/error.h>
-#endif
-
/* Declarations for tuneable settings */
extern size_t git_mwindow__window_size;
extern size_t git_mwindow__mapped_limit;
diff --git a/src/netops.h b/src/netops.h
index 771c87b64..7140b39bc 100644
--- a/src/netops.h
+++ b/src/netops.h
@@ -14,7 +14,7 @@
#include "net.h"
#ifdef GIT_OPENSSL
-# include <openssl/ssl.h>
+# include "streams/openssl.h"
#endif
typedef struct gitno_ssl {
diff --git a/src/streams/openssl.c b/src/streams/openssl.c
index 95989341b..0dc400d32 100644
--- a/src/streams/openssl.c
+++ b/src/streams/openssl.c
@@ -7,6 +7,7 @@
#include "streams/openssl.h"
#include "streams/openssl_legacy.h"
+#include "streams/openssl_dynamic.h"
#ifdef GIT_OPENSSL
@@ -27,10 +28,12 @@
# include <netinet/in.h>
#endif
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/x509v3.h>
-#include <openssl/bio.h>
+#ifndef GIT_OPENSSL_DYNAMIC
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+#endif
SSL_CTX *git__ssl_ctx;
@@ -93,6 +96,11 @@ int git_openssl_stream_global_init(void)
ssl_opts |= SSL_OP_NO_COMPRESSION;
#endif
+#ifdef GIT_OPENSSL_DYNAMIC
+ if (git_openssl_stream_dynamic_init() < 0)
+ return -1;
+#endif
+
#ifdef VALGRIND
/* Swap in our own allocator functions that initialize allocated memory */
if (!allocators_initialized &&
@@ -139,7 +147,7 @@ error:
return -1;
}
-#ifndef GIT_OPENSSL_LEGACY
+#if !defined(GIT_OPENSSL_LEGACY) && !defined(GIT_OPENSSL_DYNAMIC)
int git_openssl_set_locking(void)
{
# ifdef GIT_THREADS
diff --git a/src/streams/openssl.h b/src/streams/openssl.h
index 826d1efbc..89fb60a82 100644
--- a/src/streams/openssl.h
+++ b/src/streams/openssl.h
@@ -8,14 +8,22 @@
#define INCLUDE_streams_openssl_h__
#include "common.h"
+#include "streams/openssl_legacy.h"
+#include "streams/openssl_dynamic.h"
#include "git2/sys/stream.h"
extern int git_openssl_stream_global_init(void);
+#if defined(GIT_OPENSSL) && !defined(GIT_OPENSSL_DYNAMIC)
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+# endif
+
#ifdef GIT_OPENSSL
extern int git_openssl__set_cert_location(const char *file, const char *path);
-
extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
extern int git_openssl_stream_wrap(git_stream **out, git_stream *in, const char *host);
#endif
diff --git a/src/streams/openssl_dynamic.c b/src/streams/openssl_dynamic.c
new file mode 100644
index 000000000..82faf39b3
--- /dev/null
+++ b/src/streams/openssl_dynamic.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "streams/openssl.h"
+#include "streams/openssl_dynamic.h"
+
+#if defined(GIT_OPENSSL) && defined(GIT_OPENSSL_DYNAMIC)
+
+#include "runtime.h"
+
+#include <dlfcn.h>
+
+unsigned char *(*ASN1_STRING_data)(ASN1_STRING *x);
+const unsigned char *(*ASN1_STRING_get0_data)(const ASN1_STRING *x);
+int (*ASN1_STRING_length)(const ASN1_STRING *x);
+int (*ASN1_STRING_to_UTF8)(unsigned char **out, const ASN1_STRING *in);
+int (*ASN1_STRING_type)(const ASN1_STRING *x);
+
+void *(*BIO_get_data)(BIO *a);
+int (*BIO_get_new_index)(void);
+int (*OPENSSL_init_ssl)(uint64_t opts, const void *settings);
+void (*BIO_meth_free)(BIO_METHOD *biom);
+int (*BIO_meth_set_create)(BIO_METHOD *biom, int (*create) (BIO *));
+int (*BIO_meth_set_ctrl)(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
+int (*BIO_meth_set_destroy)(BIO_METHOD *biom, int (*destroy) (BIO *));
+int (*BIO_meth_set_gets)(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
+int (*BIO_meth_set_puts)(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
+int (*BIO_meth_set_read)(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
+int (*BIO_meth_set_write)(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
+BIO_METHOD *(*BIO_meth_new)(int type, const char *name);
+BIO *(*BIO_new)(const BIO_METHOD *type);
+void (*BIO_set_data)(BIO *a, void *ptr);
+void (*BIO_set_init)(BIO *a, int init);
+
+void (*CRYPTO_free)(void *ptr, const char *file, int line);
+void *(*CRYPTO_malloc)(size_t num, const char *file, int line);
+int (*CRYPTO_num_locks)(void);
+void (*CRYPTO_set_locking_callback)(void (*func)(int mode, int type, const char *file, int line));
+int (*CRYPTO_THREADID_set_callback)(void (*func)(CRYPTO_THREADID *id));
+void (*CRYPTO_THREADID_set_numeric)(CRYPTO_THREADID *id, unsigned long val);
+
+char *(*ERR_error_string)(unsigned long e, char *buf);
+void (*ERR_error_string_n)(unsigned long e, char *buf, size_t len);
+unsigned long (*ERR_get_error)(void);
+
+int (*SSL_connect)(SSL *ssl);
+long (*SSL_ctrl)(SSL *ssl, int cmd, long arg, void *parg);
+void (*SSL_free)(SSL *ssl);
+int (*SSL_get_error)(SSL *ssl, int ret);
+X509 *(*SSL_get_peer_certificate)(const SSL *ssl);
+long (*SSL_get_verify_result)(const SSL *ssl);
+int (*SSL_library_init)(void);
+void (*SSL_load_error_strings)(void);
+SSL *(*SSL_new)(SSL_CTX *ctx);
+int (*SSL_read)(SSL *ssl, const void *buf, int num);
+void (*SSL_set_bio)(SSL *ssl, BIO *rbio, BIO *wbio);
+int (*SSL_shutdown)(SSL *ssl);
+int (*SSL_write)(SSL *ssl, const void *buf, int num);
+
+long (*SSL_CTX_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg);
+void (*SSL_CTX_free)(SSL_CTX *ctx);
+SSL_CTX *(*SSL_CTX_new)(const SSL_METHOD *method);
+int (*SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
+int (*SSL_CTX_set_default_verify_paths)(SSL_CTX *ctx);
+long (*SSL_CTX_set_options)(SSL_CTX *ctx, long options);
+void (*SSL_CTX_set_verify)(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
+int (*SSL_CTX_load_verify_locations)(SSL_CTX *ctx, const char *CAfile, const char *CApath);
+
+const SSL_METHOD *(*SSLv23_method)(void);
+const SSL_METHOD *(*TLS_method)(void);
+
+ASN1_STRING *(*X509_NAME_ENTRY_get_data)(const X509_NAME_ENTRY *ne);
+X509_NAME_ENTRY *(*X509_NAME_get_entry)(X509_NAME *name, int loc);
+int (*X509_NAME_get_index_by_NID)(X509_NAME *name, int nid, int lastpos);
+void (*X509_free)(X509 *a);
+void *(*X509_get_ext_d2i)(const X509 *x, int nid, int *crit, int *idx);
+X509_NAME *(*X509_get_subject_name)(const X509 *x);
+
+int (*i2d_X509)(X509 *a, unsigned char **ppout);
+
+int (*OPENSSL_sk_num)(const void *sk);
+void *(*OPENSSL_sk_value)(const void *sk, int i);
+void (*OPENSSL_sk_free)(void *sk);
+
+int (*sk_num)(const void *sk);
+void *(*sk_value)(const void *sk, int i);
+void (*sk_free)(void *sk);
+
+void *openssl_handle;
+
+GIT_INLINE(void *) openssl_sym(int *err, const char *name, bool required)
+{
+ void *symbol;
+
+ /* if we've seen an err, noop to retain it */
+ if (*err)
+ return NULL;
+
+
+ if ((symbol = dlsym(openssl_handle, name)) == NULL && required) {
+ const char *msg = dlerror();
+ git_error_set(GIT_ERROR_SSL, "could not load ssl function '%s': %s", name, msg ? msg : "unknown error");
+ *err = -1;
+ }
+
+ return symbol;
+}
+
+static void dynamic_shutdown(void)
+{
+ dlclose(openssl_handle);
+ openssl_handle = NULL;
+}
+
+int git_openssl_stream_dynamic_init(void)
+{
+ int err = 0;
+
+ if ((openssl_handle = dlopen("libssl.so.1.1", RTLD_NOW)) == NULL &&
+ (openssl_handle = dlopen("libssl.so.10", RTLD_NOW)) == NULL) {
+ git_error_set(GIT_ERROR_SSL, "could not load ssl libraries");
+ return -1;
+ }
+
+ ASN1_STRING_data = (unsigned char *(*)(ASN1_STRING *x))openssl_sym(&err, "ASN1_STRING_data", false);
+ ASN1_STRING_get0_data = (const unsigned char *(*)(const ASN1_STRING *x))openssl_sym(&err, "ASN1_STRING_get0_data", false);
+ ASN1_STRING_length = (int (*)(const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_length", true);
+ ASN1_STRING_to_UTF8 = (int (*)(unsigned char **, const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_to_UTF8", true);
+ ASN1_STRING_type = (int (*)(const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_type", true);
+
+ BIO_get_data = (void *(*)(BIO *))openssl_sym(&err, "BIO_get_data", false);
+ BIO_get_new_index = (int (*)(void))openssl_sym(&err, "BIO_get_new_index", false);
+ BIO_meth_free = (void (*)(BIO_METHOD *))openssl_sym(&err, "BIO_meth_free", false);
+ BIO_meth_new = (BIO_METHOD *(*)(int, const char *))openssl_sym(&err, "BIO_meth_new", false);
+ BIO_meth_set_create = (int (*)(BIO_METHOD *, int (*)(BIO *)))openssl_sym(&err, "BIO_meth_set_create", false);
+ BIO_meth_set_ctrl = (int (*)(BIO_METHOD *, long (*)(BIO *, int, long, void *)))openssl_sym(&err, "BIO_meth_set_ctrl", false);
+ BIO_meth_set_destroy = (int (*)(BIO_METHOD *, int (*)(BIO *)))openssl_sym(&err, "BIO_meth_set_destroy", false);
+ BIO_meth_set_gets = (int (*)(BIO_METHOD *, int (*)(BIO *, char *, int)))openssl_sym(&err, "BIO_meth_set_gets", false);
+ BIO_meth_set_puts = (int (*)(BIO_METHOD *, int (*)(BIO *, const char *)))openssl_sym(&err, "BIO_meth_set_puts", false);
+ BIO_meth_set_read = (int (*)(BIO_METHOD *, int (*)(BIO *, char *, int)))openssl_sym(&err, "BIO_meth_set_read", false);
+ BIO_meth_set_write = (int (*)(BIO_METHOD *, int (*)(BIO *, const char *, int)))openssl_sym(&err, "BIO_meth_set_write", false);
+ BIO_new = (BIO *(*)(const BIO_METHOD *))openssl_sym(&err, "BIO_new", true);
+ BIO_set_data = (void (*)(BIO *a, void *))openssl_sym(&err, "BIO_set_data", false);
+ BIO_set_init = (void (*)(BIO *a, int))openssl_sym(&err, "BIO_set_init", false);
+
+ CRYPTO_free = (void (*)(void *, const char *, int))openssl_sym(&err, "CRYPTO_free", true);
+ CRYPTO_malloc = (void *(*)(size_t, const char *, int))openssl_sym(&err, "CRYPTO_malloc", true);
+ CRYPTO_num_locks = (int (*)(void))openssl_sym(&err, "CRYPTO_num_locks", false);
+ CRYPTO_set_locking_callback = (void (*)(void (*)(int, int, const char *, int)))openssl_sym(&err, "CRYPTO_set_locking_callback", false);
+
+ CRYPTO_THREADID_set_callback = (int (*)(void (*)(CRYPTO_THREADID *)))openssl_sym(&err, "CRYPTO_THREADID_set_callback", false);
+ CRYPTO_THREADID_set_numeric = (void (*)(CRYPTO_THREADID *, unsigned long))openssl_sym(&err, "CRYPTO_THREADID_set_numeric", false);
+
+ ERR_error_string = (char *(*)(unsigned long, char *))openssl_sym(&err, "ERR_error_string", true);
+ ERR_error_string_n = (void (*)(unsigned long, char *, size_t))openssl_sym(&err, "ERR_error_string_n", true);
+ ERR_get_error = (unsigned long (*)(void))openssl_sym(&err, "ERR_get_error", true);
+
+ OPENSSL_init_ssl = (int (*)(uint64_t opts, const void *settings))openssl_sym(&err, "OPENSSL_init_ssl", false);
+ OPENSSL_sk_num = (int (*)(const void *))openssl_sym(&err, "OPENSSL_sk_num", false);
+ OPENSSL_sk_value = (void *(*)(const void *sk, int i))openssl_sym(&err, "OPENSSL_sk_value", false);
+ OPENSSL_sk_free = (void (*)(void *))openssl_sym(&err, "OPENSSL_sk_free", false);
+
+ sk_num = (int (*)(const void *))openssl_sym(&err, "sk_num", false);
+ sk_value = (void *(*)(const void *sk, int i))openssl_sym(&err, "sk_value", false);
+ sk_free = (void (*)(void *))openssl_sym(&err, "sk_free", false);
+
+ SSL_connect = (int (*)(SSL *))openssl_sym(&err, "SSL_connect", true);
+ SSL_ctrl = (long (*)(SSL *, int, long, void *))openssl_sym(&err, "SSL_ctrl", true);
+ SSL_get_peer_certificate = (X509 *(*)(const SSL *))openssl_sym(&err, "SSL_get_peer_certificate", true);
+ SSL_library_init = (int (*)(void))openssl_sym(&err, "SSL_library_init", false);
+ SSL_free = (void (*)(SSL *))openssl_sym(&err, "SSL_free", true);
+ SSL_get_error = (int (*)(SSL *, int))openssl_sym(&err, "SSL_get_error", true);
+ SSL_get_verify_result = (long (*)(const SSL *ssl))openssl_sym(&err, "SSL_get_verify_result", true);
+ SSL_load_error_strings = (void (*)(void))openssl_sym(&err, "SSL_load_error_strings", false);
+ SSL_new = (SSL *(*)(SSL_CTX *))openssl_sym(&err, "SSL_new", true);
+ SSL_read = (int (*)(SSL *, const void *, int))openssl_sym(&err, "SSL_read", true);
+ SSL_set_bio = (void (*)(SSL *, BIO *, BIO *))openssl_sym(&err, "SSL_set_bio", true);
+ SSL_shutdown = (int (*)(SSL *ssl))openssl_sym(&err, "SSL_shutdown", true);
+ SSL_write = (int (*)(SSL *, const void *, int))openssl_sym(&err, "SSL_write", true);
+
+ SSL_CTX_ctrl = (long (*)(SSL_CTX *, int, long, void *))openssl_sym(&err, "SSL_CTX_ctrl", true);
+ SSL_CTX_free = (void (*)(SSL_CTX *))openssl_sym(&err, "SSL_CTX_free", true);
+ SSL_CTX_new = (SSL_CTX *(*)(const SSL_METHOD *))openssl_sym(&err, "SSL_CTX_new", true);
+ SSL_CTX_set_cipher_list = (int (*)(SSL_CTX *, const char *))openssl_sym(&err, "SSL_CTX_set_cipher_list", true);
+ SSL_CTX_set_default_verify_paths = (int (*)(SSL_CTX *ctx))openssl_sym(&err, "SSL_CTX_set_default_verify_paths", true);
+ SSL_CTX_set_options = (long (*)(SSL_CTX *, long))openssl_sym(&err, "SSL_CTX_set_options", false);
+ SSL_CTX_set_verify = (void (*)(SSL_CTX *, int, int (*)(int, X509_STORE_CTX *)))openssl_sym(&err, "SSL_CTX_set_verify", true);
+ SSL_CTX_load_verify_locations = (int (*)(SSL_CTX *, const char *, const char *))openssl_sym(&err, "SSL_CTX_load_verify_locations", true);
+
+ SSLv23_method = (const SSL_METHOD *(*)(void))openssl_sym(&err, "SSLv23_method", false);
+ TLS_method = (const SSL_METHOD *(*)(void))openssl_sym(&err, "TLS_method", false);
+
+ X509_NAME_ENTRY_get_data = (ASN1_STRING *(*)(const X509_NAME_ENTRY *))openssl_sym(&err, "X509_NAME_ENTRY_get_data", true);
+ X509_NAME_get_entry = (X509_NAME_ENTRY *(*)(X509_NAME *, int))openssl_sym(&err, "X509_NAME_get_entry", true);
+ X509_NAME_get_index_by_NID = (int (*)(X509_NAME *, int, int))openssl_sym(&err, "X509_NAME_get_index_by_NID", true);
+ X509_free = (void (*)(X509 *))openssl_sym(&err, "X509_free", true);
+ X509_get_ext_d2i = (void *(*)(const X509 *x, int nid, int *crit, int *idx))openssl_sym(&err, "X509_get_ext_d2i", true);
+ X509_get_subject_name = (X509_NAME *(*)(const X509 *))openssl_sym(&err, "X509_get_subject_name", true);
+
+ i2d_X509 = (int (*)(X509 *a, unsigned char **ppout))openssl_sym(&err, "i2d_X509", true);
+
+ if (err)
+ goto on_error;
+
+ /* Add legacy functionality */
+ if (!OPENSSL_init_ssl) {
+ OPENSSL_init_ssl = OPENSSL_init_ssl__legacy;
+
+ if (!SSL_library_init ||
+ !SSL_load_error_strings ||
+ !CRYPTO_num_locks ||
+ !CRYPTO_set_locking_callback ||
+ !CRYPTO_THREADID_set_callback ||
+ !CRYPTO_THREADID_set_numeric) {
+ git_error_set(GIT_ERROR_SSL, "could not load legacy openssl initialization functions");
+ goto on_error;
+ }
+ }
+
+ if (!SSL_CTX_set_options)
+ SSL_CTX_set_options = SSL_CTX_set_options__legacy;
+
+ if (TLS_method)
+ SSLv23_method = TLS_method;
+
+ if (!BIO_meth_new) {
+ BIO_meth_new = BIO_meth_new__legacy;
+ BIO_meth_new = BIO_meth_new__legacy;
+ BIO_meth_free = BIO_meth_free__legacy;
+ BIO_meth_set_write = BIO_meth_set_write__legacy;
+ BIO_meth_set_read = BIO_meth_set_read__legacy;
+ BIO_meth_set_puts = BIO_meth_set_puts__legacy;
+ BIO_meth_set_gets = BIO_meth_set_gets__legacy;
+ BIO_meth_set_ctrl = BIO_meth_set_ctrl__legacy;
+ BIO_meth_set_create = BIO_meth_set_create__legacy;
+ BIO_meth_set_destroy = BIO_meth_set_destroy__legacy;
+ BIO_get_new_index = BIO_get_new_index__legacy;
+ BIO_set_data = BIO_set_data__legacy;
+ BIO_set_init = BIO_set_init__legacy;
+ BIO_get_data = BIO_get_data__legacy;
+ }
+
+ if (!ASN1_STRING_get0_data) {
+ if (!ASN1_STRING_data) {
+ git_error_set(GIT_ERROR_SSL, "could not load legacy openssl string function");
+ goto on_error;
+ }
+
+ ASN1_STRING_get0_data = ASN1_STRING_get0_data__legacy;
+ }
+
+ if ((!OPENSSL_sk_num && !sk_num) ||
+ (!OPENSSL_sk_value && !sk_value) ||
+ (!OPENSSL_sk_free && !sk_free)) {
+ git_error_set(GIT_ERROR_SSL, "could not load legacy openssl stack functions");
+ goto on_error;
+ }
+
+ if (git_runtime_shutdown_register(dynamic_shutdown) != 0)
+ goto on_error;
+
+ return 0;
+
+on_error:
+ dlclose(openssl_handle);
+ return -1;
+}
+
+
+int sk_GENERAL_NAME_num(const GENERAL_NAME *sk)
+{
+ if (OPENSSL_sk_num)
+ return OPENSSL_sk_num(sk);
+ else if (sk_num)
+ return sk_num(sk);
+
+ GIT_ASSERT_WITH_RETVAL(false, 0);
+ return 0;
+}
+
+GENERAL_NAME *sk_GENERAL_NAME_value(const GENERAL_NAME *sk, int i)
+{
+ if (OPENSSL_sk_value)
+ return OPENSSL_sk_value(sk, i);
+ else if (sk_value)
+ return sk_value(sk, i);
+
+ GIT_ASSERT_WITH_RETVAL(false, NULL);
+ return NULL;
+}
+
+void GENERAL_NAMES_free(GENERAL_NAME *sk)
+{
+ if (OPENSSL_sk_free)
+ OPENSSL_sk_free(sk);
+ else if (sk_free)
+ sk_free(sk);
+}
+
+#endif /* GIT_OPENSSL && GIT_OPENSSL_DYNAMIC */
diff --git a/src/streams/openssl_dynamic.h b/src/streams/openssl_dynamic.h
new file mode 100644
index 000000000..aed676901
--- /dev/null
+++ b/src/streams/openssl_dynamic.h
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#ifndef INCLUDE_streams_openssl_dynamic_h__
+#define INCLUDE_streams_openssl_dynamic_h__
+
+#ifdef GIT_OPENSSL_DYNAMIC
+
+# define BIO_CTRL_FLUSH 11
+
+# define BIO_TYPE_SOURCE_SINK 0x0400
+
+# define CRYPTO_LOCK 1
+
+# define GEN_DNS 2
+# define GEN_IPADD 7
+
+# define NID_commonName 13
+# define NID_subject_alt_name 85
+
+# define SSL_VERIFY_NONE 0x00
+
+# define SSL_CTRL_OPTIONS 32
+# define SSL_CTRL_MODE 33
+# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
+
+# define SSL_ERROR_NONE 0
+# define SSL_ERROR_SSL 1
+# define SSL_ERROR_WANT_READ 2
+# define SSL_ERROR_WANT_WRITE 3
+# define SSL_ERROR_WANT_X509_LOOKUP 4
+# define SSL_ERROR_SYSCALL 5
+# define SSL_ERROR_ZERO_RETURN 6
+# define SSL_ERROR_WANT_CONNECT 7
+# define SSL_ERROR_WANT_ACCEPT 8
+
+# define SSL_OP_NO_COMPRESSION 0x00020000L
+# define SSL_OP_NO_SSLv2 0x01000000L
+# define SSL_OP_NO_SSLv3 0x02000000L
+
+# define SSL_MODE_AUTO_RETRY 0x00000004L
+
+# define TLSEXT_NAMETYPE_host_name 0
+
+# define V_ASN1_UTF8STRING 12
+
+# define X509_V_OK 0
+
+/* Most of the OpenSSL types are mercifully opaque, so we can treat them like `void *` */
+typedef struct bio_st BIO;
+typedef struct bio_method_st BIO_METHOD;
+typedef void bio_info_cb;
+typedef void * CRYPTO_EX_DATA;
+typedef void CRYPTO_THREADID;
+typedef void GENERAL_NAMES;
+typedef void SSL;
+typedef void SSL_CTX;
+typedef void SSL_METHOD;
+typedef void X509;
+typedef void X509_NAME;
+typedef void X509_NAME_ENTRY;
+typedef void X509_STORE_CTX;
+
+typedef struct {
+ int length;
+ int type;
+ unsigned char *data;
+ long flags;
+} ASN1_STRING;
+
+typedef struct {
+ int type;
+ union {
+ char *ptr;
+ ASN1_STRING *ia5;
+ } d;
+} GENERAL_NAME;
+
+struct bio_st {
+ BIO_METHOD *method;
+ /* bio, mode, argp, argi, argl, ret */
+ long (*callback) (struct bio_st *, int, const char *, int, long, long);
+ char *cb_arg; /* first argument for the callback */
+ int init;
+ int shutdown;
+ int flags; /* extra storage */
+ int retry_reason;
+ int num;
+ void *ptr;
+ struct bio_st *next_bio; /* used by filter BIOs */
+ struct bio_st *prev_bio; /* used by filter BIOs */
+ int references;
+ unsigned long num_read;
+ unsigned long num_write;
+ CRYPTO_EX_DATA ex_data;
+};
+
+struct bio_method_st {
+ int type;
+ const char *name;
+ int (*bwrite) (BIO *, const char *, int);
+ int (*bread) (BIO *, char *, int);
+ int (*bputs) (BIO *, const char *);
+ int (*bgets) (BIO *, char *, int);
+ long (*ctrl) (BIO *, int, long, void *);
+ int (*create) (BIO *);
+ int (*destroy) (BIO *);
+ long (*callback_ctrl) (BIO *, int, bio_info_cb *);
+};
+
+extern unsigned char *(*ASN1_STRING_data)(ASN1_STRING *x);
+extern const unsigned char *(*ASN1_STRING_get0_data)(const ASN1_STRING *x);
+extern int (*ASN1_STRING_length)(const ASN1_STRING *x);
+extern int (*ASN1_STRING_to_UTF8)(unsigned char **out, const ASN1_STRING *in);
+extern int (*ASN1_STRING_type)(const ASN1_STRING *x);
+
+extern void *(*BIO_get_data)(BIO *a);
+extern int (*BIO_get_new_index)(void);
+extern int (*OPENSSL_init_ssl)(uint64_t opts, const void *settings);
+extern void (*BIO_meth_free)(BIO_METHOD *biom);
+extern int (*BIO_meth_set_create)(BIO_METHOD *biom, int (*create) (BIO *));
+extern int (*BIO_meth_set_ctrl)(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
+extern int (*BIO_meth_set_destroy)(BIO_METHOD *biom, int (*destroy) (BIO *));
+extern int (*BIO_meth_set_gets)(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
+extern int (*BIO_meth_set_puts)(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
+extern int (*BIO_meth_set_read)(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
+extern int (*BIO_meth_set_write)(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
+extern BIO_METHOD *(*BIO_meth_new)(int type, const char *name);
+extern BIO *(*BIO_new)(const BIO_METHOD *type);
+extern void (*BIO_set_data)(BIO *a, void *ptr);
+extern void (*BIO_set_init)(BIO *a, int init);
+
+extern void (*CRYPTO_free)(void *ptr, const char *file, int line);
+extern void *(*CRYPTO_malloc)(size_t num, const char *file, int line);
+extern int (*CRYPTO_num_locks)(void);
+extern void (*CRYPTO_set_locking_callback)(void (*func)(int mode, int type, const char *file, int line));
+extern int (*CRYPTO_THREADID_set_callback)(void (*func)(CRYPTO_THREADID *id));
+extern void (*CRYPTO_THREADID_set_numeric)(CRYPTO_THREADID *id, unsigned long val);
+
+extern char *(*ERR_error_string)(unsigned long e, char *buf);
+extern void (*ERR_error_string_n)(unsigned long e, char *buf, size_t len);
+extern unsigned long (*ERR_get_error)(void);
+
+# define OPENSSL_malloc(num) CRYPTO_malloc(num, __FILE__, __LINE__)
+# define OPENSSL_free(addr) CRYPTO_free(addr, __FILE__, __LINE__)
+
+extern int (*SSL_connect)(SSL *ssl);
+extern long (*SSL_ctrl)(SSL *ssl, int cmd, long arg, void *parg);
+extern void (*SSL_free)(SSL *ssl);
+extern int (*SSL_get_error)(SSL *ssl, int ret);
+extern X509 *(*SSL_get_peer_certificate)(const SSL *ssl);
+extern long (*SSL_get_verify_result)(const SSL *ssl);
+extern int (*SSL_library_init)(void);
+extern void (*SSL_load_error_strings)(void);
+extern SSL *(*SSL_new)(SSL_CTX *ctx);
+extern int (*SSL_read)(SSL *ssl, const void *buf, int num);
+extern void (*SSL_set_bio)(SSL *ssl, BIO *rbio, BIO *wbio);
+extern int (*SSL_shutdown)(SSL *ssl);
+extern int (*SSL_write)(SSL *ssl, const void *buf, int num);
+
+# define SSL_set_tlsext_host_name(s, name) SSL_ctrl((s), SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (char *)(name));
+
+extern long (*SSL_CTX_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg);
+extern void (*SSL_CTX_free)(SSL_CTX *ctx);
+extern SSL_CTX *(*SSL_CTX_new)(const SSL_METHOD *method);
+extern int (*SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str);
+extern int (*SSL_CTX_set_default_verify_paths)(SSL_CTX *ctx);
+extern long (*SSL_CTX_set_options)(SSL_CTX *ctx, long options);
+extern void (*SSL_CTX_set_verify)(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *));
+extern int (*SSL_CTX_load_verify_locations)(SSL_CTX *ctx, const char *CAfile, const char *CApath);
+
+# define SSL_CTX_set_mode(ctx, mode) SSL_CTX_ctrl((ctx), SSL_CTRL_MODE, (mode), NULL);
+
+extern const SSL_METHOD *(*SSLv23_method)(void);
+extern const SSL_METHOD *(*TLS_method)(void);
+
+extern ASN1_STRING *(*X509_NAME_ENTRY_get_data)(const X509_NAME_ENTRY *ne);
+extern X509_NAME_ENTRY *(*X509_NAME_get_entry)(X509_NAME *name, int loc);
+extern int (*X509_NAME_get_index_by_NID)(X509_NAME *name, int nid, int lastpos);
+extern void (*X509_free)(X509 *a);
+extern void *(*X509_get_ext_d2i)(const X509 *x, int nid, int *crit, int *idx);
+extern X509_NAME *(*X509_get_subject_name)(const X509 *x);
+
+extern int (*i2d_X509)(X509 *a, unsigned char **ppout);
+
+extern int (*OPENSSL_sk_num)(const void *sk);
+extern void *(*OPENSSL_sk_value)(const void *sk, int i);
+extern void (*OPENSSL_sk_free)(void *sk);
+
+extern int (*sk_num)(const void *sk);
+extern void *(*sk_value)(const void *sk, int i);
+extern void (*sk_free)(void *sk);
+
+extern int sk_GENERAL_NAME_num(const GENERAL_NAME *sk);
+extern GENERAL_NAME *sk_GENERAL_NAME_value(const GENERAL_NAME *sk, int i);
+extern void GENERAL_NAMES_free(GENERAL_NAME *sk);
+
+extern int git_openssl_stream_dynamic_init(void);
+
+#endif /* GIT_OPENSSL_DYNAMIC */
+
+#endif
diff --git a/src/streams/openssl_legacy.c b/src/streams/openssl_legacy.c
index 3f097be61..1bac75efa 100644
--- a/src/streams/openssl_legacy.c
+++ b/src/streams/openssl_legacy.c
@@ -8,16 +8,18 @@
#include "streams/openssl.h"
#include "streams/openssl_legacy.h"
-#if defined(GIT_OPENSSL) && defined(GIT_OPENSSL_LEGACY)
-
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/x509v3.h>
-#include <openssl/bio.h>
-
#include "runtime.h"
#include "git2/sys/openssl.h"
+#ifndef GIT_OPENSSL_DYNAMIC
+# include <openssl/ssl.h>
+# include <openssl/err.h>
+# include <openssl/x509v3.h>
+# include <openssl/bio.h>
+#endif
+
+#if defined(GIT_OPENSSL_LEGACY) || defined(GIT_OPENSSL_DYNAMIC)
+
/*
* OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
* which do not exist in previous versions. We define these inline functions so
@@ -25,16 +27,16 @@
* with ifdefs. We do the same for OPENSSL_init_ssl.
*/
-int OPENSSL_init_ssl(int opts, void *settings)
+int OPENSSL_init_ssl__legacy(uint64_t opts, const void *settings)
{
GIT_UNUSED(opts);
GIT_UNUSED(settings);
SSL_load_error_strings();
- OpenSSL_add_ssl_algorithms();
+ SSL_library_init();
return 0;
}
-BIO_METHOD* BIO_meth_new(int type, const char *name)
+BIO_METHOD* BIO_meth_new__legacy(int type, const char *name)
{
BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
if (!meth) {
@@ -47,85 +49,89 @@ BIO_METHOD* BIO_meth_new(int type, const char *name)
return meth;
}
-void BIO_meth_free(BIO_METHOD *biom)
+void BIO_meth_free__legacy(BIO_METHOD *biom)
{
git__free(biom);
}
-int BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
+int BIO_meth_set_write__legacy(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
{
biom->bwrite = write;
return 1;
}
-int BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
+int BIO_meth_set_read__legacy(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
{
biom->bread = read;
return 1;
}
-int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
+int BIO_meth_set_puts__legacy(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
{
biom->bputs = puts;
return 1;
}
-int BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
+int BIO_meth_set_gets__legacy(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
{
biom->bgets = gets;
return 1;
}
-int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
+int BIO_meth_set_ctrl__legacy(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
{
biom->ctrl = ctrl;
return 1;
}
-int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
+int BIO_meth_set_create__legacy(BIO_METHOD *biom, int (*create) (BIO *))
{
biom->create = create;
return 1;
}
-int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
+int BIO_meth_set_destroy__legacy(BIO_METHOD *biom, int (*destroy) (BIO *))
{
biom->destroy = destroy;
return 1;
}
-int BIO_get_new_index(void)
+int BIO_get_new_index__legacy(void)
{
/* This exists as of 1.1 so before we'd just have 0 */
return 0;
}
-void BIO_set_init(BIO *b, int init)
+void BIO_set_init__legacy(BIO *b, int init)
{
b->init = init;
}
-void BIO_set_data(BIO *a, void *ptr)
+void BIO_set_data__legacy(BIO *a, void *ptr)
{
a->ptr = ptr;
}
-void *BIO_get_data(BIO *a)
+void *BIO_get_data__legacy(BIO *a)
{
return a->ptr;
}
-const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
+const unsigned char *ASN1_STRING_get0_data__legacy(const ASN1_STRING *x)
{
return ASN1_STRING_data((ASN1_STRING *)x);
}
+long SSL_CTX_set_options__legacy(SSL_CTX *ctx, long op)
+{
+ return SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, op, NULL);
+}
+
# if defined(GIT_THREADS)
static git_mutex *openssl_locks;
-static void openssl_locking_function(
- int mode, int n, const char *file, int line)
+static void openssl_locking_function(int mode, int n, const char *file, int line)
{
int lock;
@@ -134,11 +140,10 @@ static void openssl_locking_function(
lock = mode & CRYPTO_LOCK;
- if (lock) {
+ if (lock)
(void)git_mutex_lock(&openssl_locks[n]);
- } else {
+ else
git_mutex_unlock(&openssl_locks[n]);
- }
}
static void shutdown_ssl_locking(void)
@@ -163,6 +168,20 @@ int git_openssl_set_locking(void)
{
int num_locks, i;
+#ifndef GIT_THREADS
+ git_error_set(GIT_ERROR_THREAD, "libgit2 was not built with threads");
+ return -1;
+#endif
+
+#ifdef GIT_OPENSSL_DYNAMIC
+ /*
+ * This function is required on legacy versions of OpenSSL; when building
+ * with dynamically-loaded OpenSSL, we detect whether we loaded it or not.
+ */
+ if (!CRYPTO_set_locking_callback)
+ return 0;
+#endif
+
CRYPTO_THREADID_set_callback(threadid_cb);
num_locks = CRYPTO_num_locks();
@@ -198,4 +217,4 @@ void git_openssl_free(void *mem)
}
#endif
-#endif /* GIT_OPENSSL && GIT_OPENSSL_LEGACY */
+#endif /* GIT_OPENSSL_LEGACY || GIT_OPENSSL_DYNAMIC */
diff --git a/src/streams/openssl_legacy.h b/src/streams/openssl_legacy.h
index 7ccc13838..1f74fd95a 100644
--- a/src/streams/openssl_legacy.h
+++ b/src/streams/openssl_legacy.h
@@ -7,7 +7,9 @@
#ifndef INCLUDE_streams_openssl_legacy_h__
#define INCLUDE_streams_openssl_legacy_h__
-#ifdef GIT_OPENSSL
+#include "streams/openssl_dynamic.h"
+
+#if defined(GIT_OPENSSL) && !defined(GIT_OPENSSL_DYNAMIC)
# include <openssl/ssl.h>
# include <openssl/err.h>
# include <openssl/x509v3.h>
@@ -19,23 +21,42 @@
# endif
#endif
-#ifdef GIT_OPENSSL_LEGACY
-
-extern int OPENSSL_init_ssl(int opts, void *settings);
-extern BIO_METHOD* BIO_meth_new(int type, const char *name);
-extern void BIO_meth_free(BIO_METHOD *biom);
-extern int BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
-extern int BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
-extern int BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
-extern int BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
-extern int BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
-extern int BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *));
-extern int BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *));
-extern int BIO_get_new_index(void);
-extern void BIO_set_data(BIO *a, void *ptr);
-extern void BIO_set_init(BIO *b, int init);
-extern void *BIO_get_data(BIO *a);
-extern const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
+#if defined(GIT_OPENSSL_LEGACY) && !defined(GIT_OPENSSL_DYNAMIC)
+# define OPENSSL_init_ssl OPENSSL_init_ssl__legacy
+# define BIO_meth_new BIO_meth_new__legacy
+# define BIO_meth_free BIO_meth_free__legacy
+# define BIO_meth_set_write BIO_meth_set_write__legacy
+# define BIO_meth_set_read BIO_meth_set_read__legacy
+# define BIO_meth_set_puts BIO_meth_set_puts__legacy
+# define BIO_meth_set_gets BIO_meth_set_gets__legacy
+# define BIO_meth_set_ctrl BIO_meth_set_ctrl__legacy
+# define BIO_meth_set_create BIO_meth_set_create__legacy
+# define BIO_meth_set_destroy BIO_meth_set_destroy__legacy
+# define BIO_get_new_index BIO_get_new_index__legacy
+# define BIO_set_data BIO_set_data__legacy
+# define BIO_set_init BIO_set_init__legacy
+# define BIO_get_data BIO_get_data__legacy
+# define ASN1_STRING_get0_data ASN1_STRING_get0_data__legacy
+#endif
+
+#if defined(GIT_OPENSSL_LEGACY) || defined(GIT_OPENSSL_DYNAMIC)
+
+extern int OPENSSL_init_ssl__legacy(uint64_t opts, const void *settings);
+extern BIO_METHOD* BIO_meth_new__legacy(int type, const char *name);
+extern void BIO_meth_free__legacy(BIO_METHOD *biom);
+extern int BIO_meth_set_write__legacy(BIO_METHOD *biom, int (*write) (BIO *, const char *, int));
+extern int BIO_meth_set_read__legacy(BIO_METHOD *biom, int (*read) (BIO *, char *, int));
+extern int BIO_meth_set_puts__legacy(BIO_METHOD *biom, int (*puts) (BIO *, const char *));
+extern int BIO_meth_set_gets__legacy(BIO_METHOD *biom, int (*gets) (BIO *, char *, int));
+extern int BIO_meth_set_ctrl__legacy(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *));
+extern int BIO_meth_set_create__legacy(BIO_METHOD *biom, int (*create) (BIO *));
+extern int BIO_meth_set_destroy__legacy(BIO_METHOD *biom, int (*destroy) (BIO *));
+extern int BIO_get_new_index__legacy(void);
+extern void BIO_set_data__legacy(BIO *a, void *ptr);
+extern void BIO_set_init__legacy(BIO *b, int init);
+extern void *BIO_get_data__legacy(BIO *a);
+extern const unsigned char *ASN1_STRING_get0_data__legacy(const ASN1_STRING *x);
+extern long SSL_CTX_set_options__legacy(SSL_CTX *ctx, long op);
#endif