Subject: [alpine-aports] [PATCH] [WIP] community/julia: update to 0.6.2

From: Drew DeVault <[email-masked]>
Date: Wed, 3 Jan 2018 22:29:24 -0500

---
This is necessary to get the libgit2 patch I submitted through. I noted
this as [WIP] because I'm able to compile this, but it fails in the
check() - however, I get the same errors when building the latest
version of Julia as well. CC'd the current maintainer of this package,
can you take a look?

 community/julia/APKBUILD                    |   12 +-
 community/julia/update-libgit2-0.26.0.patch | 5642 +++++++++++++++++++++++++++
 2 files changed, 5649 insertions(+), 5 deletions(-)
 create mode 100644 community/julia/update-libgit2-0.26.0.patch

diff --git a/community/julia/APKBUILD b/community/julia/APKBUILD
index 973a811f27..1e2a74c03b 100644
--- a/community/julia/APKBUILD
+++ b/community/julia/APKBUILD
@@ -2,9 +2,9 @@
 # Contributor: Shiz <[email-masked]>
 # Maintainer: Shiz <[email-masked]>
 pkgname=julia
-pkgver=0.6.0
+pkgver=0.6.2
 # Keep in sync with deps/libuv.version.
-_libuv_ver=52d72a52cc7ccd570929990f010ed16e2ec604c8
+_libuv_ver=d8ab1c6a33e77bf155facb54215dd8798e13825d
 _llvm_ver=3.9
 pkgrel=0
 pkgdesc="A high-level, high-performance dynamic language for technical computing"
@@ -63,6 +63,7 @@ source="https://github.com/JuliaLang/julia/releases/download/v$pkgver/$pkgname-$
 	test-disable-tests-using-fake_pty.patch
 	test-libgit2-skip-SSL_CERT_FILE.patch
 	test-repl-disable-22176-20482.patch
+    update-libgit2-0.26.0.patch
 	"
 builddir="$srcdir/$pkgname-$pkgver"
 ldpath="/usr/lib/julia"
@@ -171,8 +172,8 @@ dbg() {
 	mv "$pkgdir"/usr/lib/julia/*-debug.* "$subpkgdir"/usr/lib/julia/
 }
 
-sha512sums="da21b35eb2c682c0fb8720974a76759c51fe993f10e6af5ca4864fc7f0bb6c90d880b706eb798476c7228bae2db19ff0825add6a2abde2961f16a93a3050cb69  julia-0.6.0.tar.gz
-4bf9c8b16617691b70ea43c667ecc575d2a06b3d0c347b949d10360c012138585a13ecea5e18de81b1585a96cf7734b7cc3d6072490898f1d5531c702cf5afab  libuv-52d72a52cc7ccd570929990f010ed16e2ec604c8.tar.gz
+sha512sums="679050463ed5825d34c477bd44cd91cfecc7d1735a2f52cc70b509afd9883cb60902861643266ecac5ba6cbb03f8fcdd12fc2e87dc41b9ed0eef813fa40610f1  julia-0.6.2.tar.gz
+272e3cc7b1290ef19cc941c3b3e6dd39dba7dcb26f0aea8e667c48c56288aa9266020504e0cc90074f02881521b3352079416f564c7eb24ab444326a8f04ca64  libuv-d8ab1c6a33e77bf155facb54215dd8798e13825d.tar.gz
 43eaf66d9cb3748012b2dfd77da1b41f667c5c7602a56bea8186b796b215bde82d555d79ab053378c2222521396354dcce5cf23a78fa3b1456062c47771c8433  UnicodeData.txt
 0283c7b0ff7dd99ae79f6ddac63513ce7d58ba31de506a3fee07af9b8882ddc275d0f9cb002381ba1e304bcacf252612fa16b21b85667422477e6b945b725899  find-syslibs
 f812b05b7712975eaef0bf071dd2c1cd0b21c68b18d6a513878bb8fe877bfcadf9f4b9dd8cd27b6809378de5b250a010301e7a90169677d155ad2ba377e8b428  0001-hardened.patch
@@ -183,4 +184,5 @@ a66526aee8745875b254f0d27db78b10e76cd8489f4601c77b82674a31ee7a0cf417af8b24a520e0
 3f2a6cf439aaada90872b869972f17b506d2f39758f3e2407c3e5f6b28082e7797ed6f2d7e4bace56e02809fe94f879c2a34e22216aa19b08a452371b81e7462  fix-or-disable-broken-tests.patch
 be3eea9d7506796a48171d244e61e8ee3f69ee659aa65ee738a7ec08499566a014bd6ee21ba39ec97e74d734a8b45b7ec1f5a630a96a31a6d4e17b274107b640  test-disable-tests-using-fake_pty.patch
 a97a16e3b36c7c192c1133139c87b7b3a719cef645dd2435828b5b5468f4f9beb3bba0e02bb68935319dc150d0c4ccd4728c9eaedc9e2ddee2d823e881f36e2c  test-libgit2-skip-SSL_CERT_FILE.patch
-fc5eef406d84b60fdf1c837aa1f5bd0e7a205c311853d0ae8b2b237e2eb750d7da2152632d866d372174918a3953746620f2bf130596ab2b027ca389a6816edd  test-repl-disable-22176-20482.patch"
+fc5eef406d84b60fdf1c837aa1f5bd0e7a205c311853d0ae8b2b237e2eb750d7da2152632d866d372174918a3953746620f2bf130596ab2b027ca389a6816edd  test-repl-disable-22176-20482.patch
+fb9b4ea938284a31f6f062ecafc977f6c85a3550125857f6b2b138b84222b3cdeb4ed4739ac77e7c254644921e3ce203b83dc9bb62fbb96755ca2740ada68f77  update-libgit2-0.26.0.patch"
diff --git a/community/julia/update-libgit2-0.26.0.patch b/community/julia/update-libgit2-0.26.0.patch
new file mode 100644
index 0000000000..940d5314e4
--- /dev/null
+++ b/community/julia/update-libgit2-0.26.0.patch
@@ -0,0 +1,5642 @@
+From 158d65581dda29e6b9d85c6bc9ba612a09e73210 Mon Sep 17 00:00:00 2001
+From: Curtis Vogt <[email-masked]>
+Date: Fri, 23 Jun 2017 17:23:41 -0500
+Subject: [PATCH 1/2] Update to LibGit2 v0.26.0
+
+---
+ .../md5                                            |    1 +
+ .../sha512                                         |    1 +
+ .../md5                                            |    1 -
+ .../sha512                                         |    1 -
+ deps/libgit2.mk                                    |   28 +-
+ deps/libgit2.version                               |    4 +-
+ deps/patches/libgit2-gitconfig-symlink.patch       |   27 -
+ deps/patches/libgit2-mbedtls-fixup.patch           |   70 +
+ deps/patches/libgit2-mbedtls-verify.patch          |  147 +-
+ deps/patches/libgit2-mbedtls-writer-fix.patch      |   30 -
+ deps/patches/libgit2-mbedtls.patch                 | 4827 ++++++++++++++++++--
+ deps/patches/libgit2-remote-push-NULL.patch        |   26 -
+ 14 files changed, 4521 insertions(+), 711 deletions(-)
+ create mode 100644 deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/md5
+ create mode 100644 deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/sha512
+ delete mode 100644 deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5
+ delete mode 100644 deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512
+ delete mode 100644 deps/patches/libgit2-gitconfig-symlink.patch
+ create mode 100644 deps/patches/libgit2-mbedtls-fixup.patch
+ delete mode 100644 deps/patches/libgit2-mbedtls-writer-fix.patch
+ delete mode 100644 deps/patches/libgit2-remote-push-NULL.patch
+ 
+diff --git a/deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/md5 b/deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/md5
+new file mode 100644
+index 000000000000..f148bce28a5c
+--- /dev/null
++++ b/deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/md5
+@@ -0,0 +1 @@
++0d6fd3ed9265c6804349149b23ae6362
+diff --git a/deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/sha512 b/deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/sha512
+new file mode 100644
+index 000000000000..1e129704580c
+--- /dev/null
++++ b/deps/checksums/libgit2-15e119375018fba121cf58e02a9f17fe22df0df8.tar.gz/sha512
+@@ -0,0 +1 @@
++88a8a42bb8d18a5a722938404e048266d0899362ac89fdfedfa9f71aeb90408d8d98b4d9b9ea2ff46755d0a2cd8686ff04d31e85827566e1290a9536b8b36ac8
+diff --git a/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5 b/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5
+deleted file mode 100644
+index ccc33a35bb05..000000000000
+--- a/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/md5
++++ /dev/null
+@@ -1 +0,0 @@
+-fb1f1140f9b55fc8499caa960382fc03
+diff --git a/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512 b/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512
+deleted file mode 100644
+index cc5156e0c027..000000000000
+--- a/deps/checksums/libgit2-2fcb8705e584ca61f6c4657525c9d2713f6a39d2.tar.gz/sha512
++++ /dev/null
+@@ -1 +0,0 @@
+-2086269728e14c0ec38f322b01f89d4d98a31a395cab3937591826a232193f00ec07bafe938ad99d70c74cb695af26c7228513019bfe6fc06427229bd2e098cf
+diff --git a/deps/libgit2.mk b/deps/libgit2.mk
+index c98528e52ae8..d83d0864c344 100644
+--- a/deps/libgit2.mk
++++ b/deps/libgit2.mk
+@@ -37,7 +37,7 @@ LIBGIT2_OPTS += -DCURL_INCLUDE_DIRS=$(build_includedir) -DCURL_LIBRARIES="-L$(bu
+ endif
+ 
+ ifeq ($(OS),Linux)
+-LIBGIT2_OPTS += -DUSE_OPENSSL=OFF -DUSE_MBEDTLS=ON -DCMAKE_INSTALL_RPATH="\$$ORIGIN"
++LIBGIT2_OPTS += -DUSE_HTTPS=ON -DTLS_BACKEND="mbedTLS" -DCMAKE_INSTALL_RPATH="\$$ORIGIN"
+ endif
+ ifeq ($(OS),FreeBSD)
+ LIBGIT2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN"
+@@ -78,29 +78,14 @@ $(LIBGIT2_SRC_PATH)/libgit2-agent-nonfatal.patch-applied: $(LIBGIT2_SRC_PATH)/so
+ 		patch -p1 -f < $(SRCDIR)/patches/libgit2-agent-nonfatal.patch
+ 	echo 1 > $@
+ 
+-$(LIBGIT2_SRC_PATH)/libgit2-mbedtls-writer-fix.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-mbedtls.patch-applied
+-	cd $(LIBGIT2_SRC_PATH) && \
+-		patch -p1 -f < $(SRCDIR)/patches/libgit2-mbedtls-writer-fix.patch
+-	echo 1 > $@
+-
+-$(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-writer-fix.patch-applied
++$(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-agent-nonfatal.patch-applied
+ 	cd $(LIBGIT2_SRC_PATH) && \
+ 		patch -p1 -f < $(SRCDIR)/patches/libgit2-mbedtls-verify.patch
+ 	echo 1 > $@
+ 
+-$(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied
+-	cd $(LIBGIT2_SRC_PATH) && \
+-		patch -p1 -f < $(SRCDIR)/patches/libgit2-gitconfig-symlink.patch
+-	echo 1 > $@
+-
+-$(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied
+-	cd $(LIBGIT2_SRC_PATH) && \
+-		patch -p1 -f < $(SRCDIR)/patches/libgit2-free-config.patch
+-	echo 1 > $@
+-
+-$(LIBGIT2_SRC_PATH)/libgit2-remote-push-NULL.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied
++$(LIBGIT2_SRC_PATH)/libgit2-mbedtls-fixup.patch-applied: $(LIBGIT2_SRC_PATH)/source-extracted | $(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied
+ 	cd $(LIBGIT2_SRC_PATH) && \
+-		patch -p1 -f < $(SRCDIR)/patches/libgit2-remote-push-NULL.patch
++		patch -p1 -f < $(SRCDIR)/patches/libgit2-mbedtls-fixup.patch
+ 	echo 1 > $@
+ 
+ $(build_datarootdir)/julia/cert.pem: $(CERTFILE)
+@@ -111,11 +96,8 @@ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: \
+ 	$(LIBGIT2_SRC_PATH)/libgit2-mbedtls.patch-applied \
+ 	$(LIBGIT2_SRC_PATH)/libgit2-ssh.patch-applied \
+ 	$(LIBGIT2_SRC_PATH)/libgit2-agent-nonfatal.patch-applied \
+-	$(LIBGIT2_SRC_PATH)/libgit2-mbedtls-writer-fix.patch-applied \
+ 	$(LIBGIT2_SRC_PATH)/libgit2-mbedtls-verify.patch-applied \
+-	$(LIBGIT2_SRC_PATH)/libgit2-gitconfig-symlink.patch-applied \
+-	$(LIBGIT2_SRC_PATH)/libgit2-free-config.patch-applied \
+-	$(LIBGIT2_SRC_PATH)/libgit2-remote-push-NULL.patch-applied
++	$(LIBGIT2_SRC_PATH)/libgit2-mbedtls-fixup.patch-applied
+ 
+ ifneq ($(CERTFILE),)
+ $(BUILDDIR)/$(LIBGIT2_SRC_DIR)/build-configured: $(build_datarootdir)/julia/cert.pem
+diff --git a/deps/libgit2.version b/deps/libgit2.version
+index f5596b2fce3b..306384f5cd76 100644
+--- a/deps/libgit2.version
++++ b/deps/libgit2.version
+@@ -1,2 +1,2 @@
+-LIBGIT2_BRANCH=v0.25.1
+-LIBGIT2_SHA1=2fcb8705e584ca61f6c4657525c9d2713f6a39d2
++LIBGIT2_BRANCH=v0.26.0
++LIBGIT2_SHA1=15e119375018fba121cf58e02a9f17fe22df0df8
+diff --git a/deps/patches/libgit2-gitconfig-symlink.patch b/deps/patches/libgit2-gitconfig-symlink.patch
+deleted file mode 100644
+index bd4e983045be..000000000000
+--- a/deps/patches/libgit2-gitconfig-symlink.patch
++++ /dev/null
+@@ -1,27 +0,0 @@
+-From 86a8cd9f6a039889801b5bec865a4bc3deb30f47 Mon Sep 17 00:00:00 2001
+-From: Sven Strickroth2 <[email-masked]>
+-Date: Mon, 20 Mar 2017 11:21:00 +0100
+-Subject: [PATCH] filebuf: fix resolving absolute symlinks
+-
+-The symlink destination is always concatenated to the original path. Fix
+-this by using `git_buf_sets` instead of `git_buf_puts`.
+----
+- src/filebuf.c | 2 +-
+- 1 file changed, 1 insertion(+), 1 deletion(-)
+-
+-diff --git a/src/filebuf.c b/src/filebuf.c
+-index ef68b16f4..825b9c04c 100644
+---- a/src/filebuf.c
+-+++ b/src/filebuf.c
+-@@ -246,7 +246,7 @@ static int resolve_symlink(git_buf *out, const char *path)
+- 
+- 		root = git_path_root(target.ptr);
+- 		if (root >= 0) {
+--			if ((error = git_buf_puts(&curpath, target.ptr)) < 0)
+-+			if ((error = git_buf_sets(&curpath, target.ptr)) < 0)
+- 				goto cleanup;
+- 		} else {
+- 			git_buf dir = GIT_BUF_INIT;
+--- 
+-2.12.2
+-
+diff --git a/deps/patches/libgit2-mbedtls-fixup.patch b/deps/patches/libgit2-mbedtls-fixup.patch
+new file mode 100644
+index 000000000000..2ec6fbd7167a
+--- /dev/null
++++ b/deps/patches/libgit2-mbedtls-fixup.patch
+@@ -0,0 +1,70 @@
++commit de8721ae70dfae529fdb50224a47eadf6d29c574
++Author: Curtis Vogt <[email-masked]>
++Date:   Thu Jun 29 16:31:08 2017 -0500
++
++    Corrections to mbedtls support with LibGit2 0.26.0
++
++diff --git a/src/settings.c b/src/settings.c
++index 3a46f0d..4d976a0 100644
++--- a/src/settings.c
+++++ b/src/settings.c
++@@ -179,14 +179,18 @@ int git_libgit2_opts(int key, ...)
++ 			const char *path = va_arg(ap, const char *);
++ 			error = git_openssl_set_cert_file(file, path);
++ 		}
++-#elif GIT_MBEDTLS
+++#elif defined(GIT_MBEDTLS)
++ 		{
++ 			const char *file = va_arg(ap, const char *);
++ 			const char *path = va_arg(ap, const char *);
++-			if (file)
+++			if (file) {
++ 				error = git_mbedtls_set_cert_file(file, 0);
++-			if (error && path)
++-				error = git_mbedtls_set_cert_file(path, 0);
+++			} else if (path) {
+++				error = git_mbedtls_set_cert_file(path, 1);
+++			} else {
+++				giterr_set(GITERR_NET, "cannot set certificate locations: no file or path given");
+++				error = -1;
+++			}
++ 		}
++ #else
++ 		giterr_set(GITERR_NET, "cannot set certificate locations: OpenSSL or mbedTLS is not enabled");
++diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
++index e456ea8..b4eb991 100644
++--- a/src/streams/mbedtls.c
+++++ b/src/streams/mbedtls.c
++@@ -205,12 +205,12 @@ static int ssl_set_error(mbedtls_ssl_context *ssl, int error)
++ 		break;
++ 
++ 	case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
++-		giterr_set(GITERR_SSL, "SSL error: %x[%x] - %s", error, ssl->session_negotiate->verify_result, errbuf);
+++		giterr_set(GITERR_SSL, "SSL error: 0x%04x [%x] - %s", error, ssl->session_negotiate->verify_result, errbuf);
++ 		ret = GIT_ECERTIFICATE;
++ 		break;
++ 
++ 	default:
++-		giterr_set(GITERR_SSL, "SSL error: %x - %s", error, errbuf);
+++		giterr_set(GITERR_SSL, "SSL error: 0x%04x - %s", error, errbuf);
++ 	}
++ 
++ 	return ret;
++@@ -236,7 +236,7 @@ static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
++ 	if ((ret = mbedtls_ssl_get_verify_result(ssl)) != 0) {
++ 		char vrfy_buf[512];
++ 		mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "", ret);
++-		giterr_set(GITERR_SSL, "The SSL certificate is invalid: %x - %s", ret, vrfy_buf);
+++		giterr_set(GITERR_SSL, "The SSL certificate is invalid: 0x%04x - %s", ret, vrfy_buf);
++ 		return GIT_ECERTIFICATE;
++ 	}
++ 
++@@ -430,7 +430,7 @@ int git_mbedtls_set_cert_file(const char *path, int is_dir)
++ 		ret = mbedtls_x509_crt_parse_file(cacert, path);
++ 	}
++ 	// mbedtls_x509_crt_parse_path returns the number of invalid certs on success
++-	if (ret <= 0) {
+++	if (ret < 0) {
++ 		mbedtls_x509_crt_free(cacert);
++ 		git__free(cacert);
++ 		mbedtls_strerror( ret, errbuf, 512 );
+diff --git a/deps/patches/libgit2-mbedtls-verify.patch b/deps/patches/libgit2-mbedtls-verify.patch
+index 4c454c3adc4b..eb0b3854cbb0 100644
+--- a/deps/patches/libgit2-mbedtls-verify.patch
++++ b/deps/patches/libgit2-mbedtls-verify.patch
+@@ -1,99 +1,100 @@
+-diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c
+-index bcc2e8b..4706102 100644
+---- a/src/mbedtls_stream.c
+-+++ b/src/mbedtls_stream.c
+-@@ -221,82 +221,34 @@ static int ssl_teardown(mbedtls_ssl_context *ssl)
+-     return ret;
++commit eefe88eaf8c5c5b7c9a596da79e68dca3a3234d4
++Author: Curtis Vogt <[email-masked]>
++Date:   Thu Jun 29 16:30:53 2017 -0500
++
++    Use mbedtls certificate verification
++    
++    Letting mbedtls handle all certficate verification and removed the
++    custom alternative names and common name checking.
++
++diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
++index 0376ee4..e456ea8 100644
++--- a/src/streams/mbedtls.c
+++++ b/src/streams/mbedtls.c
++@@ -228,82 +228,19 @@ static int ssl_teardown(mbedtls_ssl_context *ssl)
++ 	return ret;
+  }
+  
+ -static int check_host_name(const char *name, const char *host)
+ -{
+--    if (!strcasecmp(name, host))
+--        return 0;
++-	if (!strcasecmp(name, host))
++-		return 0;
+ -
+--    if (gitno__match_host(name, host) < 0)
+--        return -1;
++-	if (gitno__match_host(name, host) < 0)
++-		return -1;
+ -
+--    return 0;
++-	return 0;
+ -}
+ -
+  static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
+  {
+--    const mbedtls_x509_crt *cert;
+--    const mbedtls_x509_sequence *alts;
+--    int ret, matched = -1;
+-+    mbedtls_x509_crt *cert;
+-+    uint32_t flags;
+-+    int ret = -1;
+-     size_t sn_size = 512;
+--    char subject_name[sn_size], alt_name[sn_size];
++-	const mbedtls_x509_crt *cert;
++-	const mbedtls_x509_sequence *alts;
++-	int ret, matched = -1;
++-	size_t sn_size = 512;
++-	char subject_name[sn_size], alt_name[sn_size];
+ -
+-+    char buf[sn_size];
+++	int ret = -1;
+++	(void)(host);  // Suppress unused parameter warning
+  
+-     if (( ret = mbedtls_ssl_get_verify_result(ssl) ) != 0) {
+--        char vrfy_buf[512];
+--        mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", ret );
+--        giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
+-+        mbedtls_x509_crt_verify_info(buf, sn_size, "  ! ", ret);
+-+        giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", buf);
+-         return GIT_ECERTIFICATE;
+-     }
++ 	if ((ret = mbedtls_ssl_get_verify_result(ssl)) != 0) {
++ 		char vrfy_buf[512];
++-		mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", ret );
++-		giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
+++		mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "", ret);
+++		giterr_set(GITERR_SSL, "The SSL certificate is invalid: %x - %s", ret, vrfy_buf);
++ 		return GIT_ECERTIFICATE;
++ 	}
+  
+--    cert = mbedtls_ssl_get_peer_cert(ssl);
+-+    cert = (mbedtls_x509_crt*) mbedtls_ssl_get_peer_cert(ssl);
+-     if (!cert) {
+-         giterr_set(GITERR_SSL, "the server did not provide a certificate");
+-         return -1;
+-     }
+- 
+--    /* Check the alternative names */
+--    alts = &cert->subject_alt_names;
+--    while (alts != NULL && matched != 1) {
+--        // Buffer is too small
+--        if( alts->buf.len >= sn_size )
+--            goto on_error;
++-	cert = mbedtls_ssl_get_peer_cert(ssl);
++-	if (!cert) {
++-		giterr_set(GITERR_SSL, "the server did not provide a certificate");
++-		return -1;
++-	}
+ -
+--        memcpy(alt_name, alts->buf.p, alts->buf.len);
+--        alt_name[alts->buf.len] = '\0';
++-	/* Check the alternative names */
++-	alts = &cert->subject_alt_names;
++-	while (alts != NULL && matched != 1) {
++-		// Buffer is too small
++-		if( alts->buf.len >= sn_size )
++-			goto on_error;
+ -
+--        if (!memchr(alt_name, '\0', alts->buf.len)) {
+--            if (check_host_name(alt_name, host) < 0)
+--                matched = 0;
+--            else
+--                matched = 1;
+--        }
++-		memcpy(alt_name, alts->buf.p, alts->buf.len);
++-		alt_name[alts->buf.len] = '\0';
+ -
+--        alts = alts->next;
+-+    if (mbedtls_x509_crt_verify(cert, git__ssl_conf->ca_chain, NULL, host, &flags, NULL, NULL) != 0) {
+-+        mbedtls_x509_crt_verify_info(buf, sn_size, "", flags);
+-+        buf[strlen(buf) - 1] = '\0';  // Remove trailing newline
+-+        giterr_set(GITERR_SSL, buf);
+-+        return GIT_ECERTIFICATE;
+-     }
+--    if (matched == 0)
+--        goto cert_fail_name;
++-		if (!memchr(alt_name, '\0', alts->buf.len)) {
++-			if (check_host_name(alt_name, host) < 0)
++-				matched = 0;
++-			else
++-				matched = 1;
++-		}
+ -
+--    if (matched == 1)
+--        return 0;
++-		alts = alts->next;
++-	}
++-	if (matched == 0)
++-		goto cert_fail_name;
+ -
+--    /* If no alternative names are available, check the common name */
+--    ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject);
+--    if (ret == 0)
+--        goto on_error;
+--    if (memchr(subject_name, '\0', ret))
+--        goto cert_fail_name;
++-	if (matched == 1)
++-		return 0;
+ -
+--    if (check_host_name(subject_name, host) < 0)
+--        goto cert_fail_name;
+- 
+-     return 0;
++-	/* If no alternative names are available, check the common name */
++-	ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject);
++-	if (ret == 0)
++-		goto on_error;
++-	if (memchr(subject_name, '\0', ret))
++-		goto cert_fail_name;
++-
++-	if (check_host_name(subject_name, host) < 0)
++-		goto cert_fail_name;
++-
++ 	return 0;
+ -
+ -on_error:
+--    return ssl_set_error(ssl, 0);
++-	return ssl_set_error(ssl, 0);
+ -
+ -cert_fail_name:
+--    giterr_set(GITERR_SSL, "hostname does not match certificate");
+--    return GIT_ECERTIFICATE;
++-	giterr_set(GITERR_SSL, "hostname does not match certificate");
++-	return GIT_ECERTIFICATE;
+  }
+  
+  typedef struct {
+diff --git a/deps/patches/libgit2-mbedtls-writer-fix.patch b/deps/patches/libgit2-mbedtls-writer-fix.patch
+deleted file mode 100644
+index d80a637a3996..000000000000
+--- a/deps/patches/libgit2-mbedtls-writer-fix.patch
++++ /dev/null
+@@ -1,30 +0,0 @@
+-diff -rup libgit2-211e117a0590583a720c53172406f34186c543bd/src/mbedtls_stream.c libgit2-211e117a0590583a720c53172406f34186c543bd-fix-write/src/mbedtls_stream.c
+---- libgit2-211e117a0590583a720c53172406f34186c543bd/src/mbedtls_stream.c   2016-10-24 17:10:21.000000000 -0400
+-+++ libgit2-211e117a0590583a720c53172406f34186c543bd-fix-write/src/mbedtls_stream.c 2016-10-24 17:04:26.000000000 -0400
+-@@ -368,16 +368,20 @@ static int mbedtls_set_proxy(git_stream 
+- 
+- ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t len, int flags)
+- {
+-+    size_t read = 0;
+-     mbedtls_stream *st = (mbedtls_stream *) stream;
+--    int ret;
+- 
+-     GIT_UNUSED(flags);
+- 
+--    if ((ret = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0) {
+--        return ssl_set_error(st->ssl, ret);
+--    }
+-+   do {
+-+       int error = mbedtls_ssl_write(st->ssl, (const unsigned char *)data + read, len - read);
+-+       if (error <= 0) {
+-+           return ssl_set_error(st->ssl, error);
+-+       }
+-+       read += error;
+-+   } while (read < len);
+- 
+--    return ret;
+-+    return read;
+- }
+- 
+- ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len)
+-
+diff --git a/deps/patches/libgit2-mbedtls.patch b/deps/patches/libgit2-mbedtls.patch
+index 955f165eab75..af12728cf855 100644
+--- a/deps/patches/libgit2-mbedtls.patch
++++ b/deps/patches/libgit2-mbedtls.patch
+@@ -1,66 +1,282 @@
++commit 4d69ea1172fec234e0f3c8cee8574e9e13bf825e
++Author: Etienne Samson <[email-masked]>
++Date:   Fri Jun 23 22:40:56 2017 +0000
++
++    mbedtls support for libgit2 v0.26.0
++    
++    See https://github.com/libgit2/libgit2/pull/4173
++    
++    cmake: simplify https support selection & tests
++    
++    Gather streams to src/streams
++    
++    Don't include OpenSSL from global.h so it doesn't namespace-leak
++    
++    Have clar exit immediately on initialization failure
++    
++    Generalize Travis' dependency installation
++    
++    Add USE_HTTPS as a CMake option
++    
++    It defaults to ON, e.g. "pick whatever default is appropriate for the platform".
++    It accepts one of SecureTransport, OpenSSL, WinHTTP, or OFF.
++    It errors if the backend library couldn't be found.
++    
++    mbedtls: initial support
++    
++    mbedtls: proper certificate verification
++    
++    mbedtls: use libmbedcrypto for hashing
++    
++    mbedtls: add global initialization
++    
++    mbedtls: default cipher list support
++    
++    mbedtls: load default CA certificates
++    
++    mbedtls: fix libgit2 hanging due to incomplete writes
++    
++    mbedtls: enable Travis CI tests
++    
++    mbedtls: use our own certificate validation
++    
++    Otherwise REQUIRED means that `git_stream_certificate` will always error.
++    We're doing the mbedtls check in verify_server_cert though.
++    
++    mbedtls: try all CA locations, stopping after any loaded
++    
++    WIP: distribution paths
++
++diff --git a/.travis.yml b/.travis.yml
++index af38252..e1be760 100644
++--- a/.travis.yml
+++++ b/.travis.yml
++@@ -45,11 +45,21 @@ matrix:
++        - VALGRIND=1
++          OPTIONS="-DBUILD_CLAR=ON -DBUILD_EXAMPLES=OFF -DDEBUG_POOL=ON -DCMAKE_BUILD_TYPE=Debug"
++      os: linux
+++   - compiler: gcc
+++     env:
+++         MBEDTLS=1
+++         OPTIONS="-DTHREADSAFE=ON -DCMAKE_BUILD_TYPE=Release -DUSE_TLS=mbedTLS -DMBEDTLS_ROOT_DIR=../mbedtls"
+++     os: linux
+++   - compiler: gcc
+++     env:
+++         MBEDTLS=1
+++         OPTIONS="-DTHREADSAFE=OFF -DBUILD_EXAMPLES=ON -DUSE_TLS=mbedTLS -DMBEDTLS_ROOT_DIR=../mbedtls"
+++     os: linux
++  allow_failures:
++    - env: COVERITY=1
++ 
++ install:
++-  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi
+++  - if [ -x "./script/install-deps-${TRAVIS_OS_NAME}.sh" ]; then ./script/install-deps-${TRAVIS_OS_NAME}.sh; fi
++ 
++ # Run the Build script and tests
++ script:
+ diff --git a/CMakeLists.txt b/CMakeLists.txt
+-index 4e1104f..8110489 100644
++index 4783e3e..5d7dbe3 100644
+ --- a/CMakeLists.txt
+ +++ b/CMakeLists.txt
+-@@ -113,6 +113,10 @@ IF (HAVE_STRUCT_STAT_NSEC OR WIN32)
+- 	OPTION( USE_NSEC		"Care about sub-second file mtimes and ctimes"	ON  )
++@@ -40,6 +40,7 @@ OPTION( LIBGIT2_FILENAME	"Name of the produced binary"			OFF )
++ OPTION( USE_SHA1DC			"Use SHA-1 with collision detection"	OFF )
++ OPTION( USE_ICONV			"Link with and use iconv library" 		OFF )
++ OPTION( USE_SSH				"Link with libssh to enable SSH support" ON )
+++OPTION( USE_HTTPS			"Enable HTTPS support"					ON )
++ OPTION( USE_GSSAPI			"Link with libgssapi for SPNEGO auth"   OFF )
++ OPTION( VALGRIND			"Configure build for valgrind"			OFF )
++ OPTION( CURL			"Use curl for HTTP if available" ON)
++@@ -89,10 +90,6 @@ IF(MSVC)
++ 	OPTION(MSVC_CRTDBG "Enable CRTDBG memory leak reporting" OFF)
+  ENDIF()
+  
+-+IF (NOT USE_OPENSSL)
+-+	OPTION( USE_MBEDTLS		"Link with and use mbedtls library"             OFF )
+-+ENDIF()
+-+
+- # This variable will contain the libraries we need to put into
+- # libgit2.pc's Requires.private. That is, what we're linking to or
+- # what someone who's statically linking us needs to link to.
+-@@ -283,6 +287,10 @@ ELSE ()
++-IF (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
++-	OPTION( USE_OPENSSL                     "Link with and use openssl library"             ON )
++-ENDIF()
++-
++ CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtim "sys/types.h;sys/stat.h"
++ 	HAVE_STRUCT_STAT_ST_MTIM LANGUAGE C)
++ CHECK_STRUCT_HAS_MEMBER ("struct stat" st_mtimespec "sys/types.h;sys/stat.h"
++@@ -208,21 +205,6 @@ STRING(REGEX REPLACE "^.*LIBGIT2_SOVERSION ([0-9]+)$" "\\1" LIBGIT2_SOVERSION "$
++ # Find required dependencies
++ INCLUDE_DIRECTORIES(src include)
++ 
++-IF (SECURITY_FOUND)
++-  # OS X 10.7 and older do not have some functions we use, fall back to OpenSSL there
++-  CHECK_LIBRARY_EXISTS("${SECURITY_DIRS}" SSLCreateContext "Security/SecureTransport.h" HAVE_NEWER_SECURITY)
++-  IF (HAVE_NEWER_SECURITY)
++-    MESSAGE("-- Found Security ${SECURITY_DIRS}")
++-    LIST(APPEND LIBGIT2_PC_LIBS "-framework Security")
++-  ELSE()
++-    MESSAGE("-- Security framework is too old, falling back to OpenSSL")
++-    SET(SECURITY_FOUND "NO")
++-    SET(SECURITY_DIRS "")
++-    SET(SECURITY_DIR "")
++-    SET(USE_OPENSSL "ON")
++-  ENDIF()
++-ENDIF()
++-
++ IF (COREFOUNDATION_FOUND)
++   MESSAGE("-- Found CoreFoundation ${COREFOUNDATION_DIRS}")
++   LIST(APPEND LIBGIT2_PC_LIBS "-framework CoreFoundation")
++@@ -280,10 +262,14 @@ ELSE ()
++ 		PKG_CHECK_MODULES(CURL libcurl)
++ 	ENDIF ()
++ 
++-	IF (NOT AMIGA AND USE_OPENSSL)
+++	IF (NOT AMIGA AND (USE_HTTPS STREQUAL "OpenSSL" OR USE_HTTPS STREQUAL "ON"))
+  		FIND_PACKAGE(OpenSSL)
+  	ENDIF ()
+  
+-+	IF (NOT AMIGA AND USE_MBEDTLS)
+++	IF (NOT AMIGA AND (USE_HTTPS STREQUAL "mbedTLS" OR USE_HTTPS STREQUAL "ON"))
+ +		FIND_PACKAGE(mbedTLS)
+ +	ENDIF ()
+ +
+  	IF (CURL_FOUND)
+  		ADD_DEFINITIONS(-DGIT_CURL)
+  		INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIRS})
+-@@ -316,6 +324,9 @@ ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin")
++@@ -293,6 +279,69 @@ ELSE ()
++ 	ENDIF()
++ ENDIF()
++ 
+++IF (USE_HTTPS STREQUAL "ON")
+++	IF (SECURITY_FOUND)
+++		# OS X 10.7 and older do not have some functions we use, fall back to OpenSSL there
+++		CHECK_LIBRARY_EXISTS("${SECURITY_DIRS}" SSLCreateContext "Security/SecureTransport.h" HAVE_NEWER_SECURITY)
+++		IF (HAVE_NEWER_SECURITY)
+++			MESSAGE("-- Found Security ${SECURITY_DIRS}")
+++			LIST(APPEND LIBGIT2_PC_LIBS "-framework Security")
+++			SET(HTTPS_BACKEND "SecureTransport")
+++		ELSE()
+++			MESSAGE("-- Security framework is too old, falling back to OpenSSL")
+++			SET(SECURITY_FOUND "NO")
+++			SET(SECURITY_DIRS "")
+++			SET(SECURITY_DIR "")
+++			SET(HTTPS_BACKEND "OpenSSL")
+++		ENDIF()
+++	ELSEIF(WINHTTP)
+++		SET(HTTPS_BACKEND "WinHTTP")
+++	ELSEIF(MBEDTLS_FOUND)
+++		SET(HTTPS_BACKEND "mbedTLS")
+++	ELSE()
+++		SET(HTTPS_BACKEND "OpenSSL")
+++	ENDIF()
+++ELSE()
+++	SET(HTTPS_BACKEND ${USE_HTTPS})
+++ENDIF()
+++
+++MESSAGE(STATUS "Using HTTPS backend ${HTTPS_BACKEND}")
+++
+++IF (HTTPS_BACKEND STREQUAL "SecureTransport")
+++	IF (NOT SECURITY_FOUND)
+++		MESSAGE(FATAL_ERROR "Asked for SecureTransport HTTPS backend, but it wasn't found")
+++	ENDIF()
+++
+++	ADD_DEFINITIONS(-DGIT_SECURE_TRANSPORT)
+++	INCLUDE_DIRECTORIES(${SECURITY_INCLUDE_DIR})
+++ELSEIF (HTTPS_BACKEND STREQUAL "OpenSSL")
+++	IF (NOT OPENSSL_FOUND)
+++		MESSAGE(FATAL_ERROR "Asked for OpenSSL HTTPS backend, but it wasn't found")
+++	ENDIF()
+++
+++	ADD_DEFINITIONS(-DGIT_OPENSSL)
+++	INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
+++	SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES})
+++ELSEIF (TLS_BACKEND STREQUAL "mbedTLS")
+++	IF (NOT MBEDTLS_FOUND)
+++		MESSAGE(FATAL_ERROR "Asked for mbedTLS backend, but it wasn't found")
+++	ENDIF()
+++
+++	ADD_DEFINITIONS(-DGIT_MBEDTLS)
+++	INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR})
+++	LINK_DIRECTORIES(${MBEDTLS_LIBRARY_DIR})
+++	SET(SSL_LIBRARIES ${MBEDTLS_LIBRARIES})
+++ELSEIF(HTTPS_BACKEND STREQUAL "WinHTTP")
+++ENDIF()
+++
+++IF (USE_HTTPS AND NOT HTTPS_BACKEND)
+++	MESSAGE(FATAL_ERROR "Asked for backend " ${HTTPS_BACKEND} " but it wasn't found")
+++ENDIF()
+++
+++IF (HTTPS_BACKEND)
+++	ADD_DEFINITIONS(-DGIT_HTTPS)
+++ENDIF()
+++
++ # Specify sha1 implementation
++ IF (USE_SHA1DC)
++ 	ADD_DEFINITIONS(-DGIT_SHA1_COLLISIONDETECT)
++@@ -303,15 +352,18 @@ IF (USE_SHA1DC)
++ ELSEIF (WIN32 AND NOT MINGW)
++ 	ADD_DEFINITIONS(-DGIT_SHA1_WIN32)
++ 	FILE(GLOB SRC_SHA1 src/hash/hash_win32.c)
++-ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+++ELSEIF (TLS_BACKEND MATCHES "SecureTransport")
++ 	ADD_DEFINITIONS(-DGIT_SHA1_COMMON_CRYPTO)
++-ELSEIF (OPENSSL_FOUND)
+++ELSEIF (TLS_BACKEND MATCHES "OpenSSL")
++ 	ADD_DEFINITIONS(-DGIT_SHA1_OPENSSL)
++ 	IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
++ 		LIST(APPEND LIBGIT2_PC_LIBS "-lssl")
+  	ELSE()
+  		SET(LIBGIT2_PC_REQUIRES "${LIBGIT2_PC_REQUIRES} openssl")
+  	ENDIF ()
+-+ELSEIF (MBEDTLS_FOUND AND NOT SHA1_TYPE STREQUAL "builtin")
+++ELSEIF (TLS_BACKEND STREQUAL "mbedTLS")
+ +	ADD_DEFINITIONS(-DMBEDTLS_SHA1)
+ +	FILE(GLOB SRC_SHA1 src/hash/hash_mbedtls.c)
+  ELSE()
+  	FILE(GLOB SRC_SHA1 src/hash/hash_generic.c)
+  ENDIF()
+-@@ -543,6 +554,11 @@ IF (OPENSSL_FOUND)
+-   SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES})
++@@ -543,21 +595,6 @@ ELSE()
++ 	# that uses CMAKE_CONFIGURATION_TYPES and not CMAKE_BUILD_TYPE
+  ENDIF()
+  
+-+IF (MBEDTLS_FOUND)
+-+  ADD_DEFINITIONS(-DGIT_MBEDTLS)
+-+  INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIR})
+-+  SET(SSL_LIBRARIES ${MBEDTLS_LIBRARIES})
+-+ENDIF()
+- 
+- 
++-IF (SECURITY_FOUND)
++-  ADD_DEFINITIONS(-DGIT_SECURE_TRANSPORT)
++-  ADD_DEFINITIONS(-DGIT_HTTPS)
++-  INCLUDE_DIRECTORIES(${SECURITY_INCLUDE_DIR})
++-ENDIF ()
++-
++-IF (OPENSSL_FOUND)
++-  ADD_DEFINITIONS(-DGIT_OPENSSL)
++-  ADD_DEFINITIONS(-DGIT_HTTPS)
++-  INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
++-  SET(SSL_LIBRARIES ${OPENSSL_LIBRARIES})
++-ENDIF()
++-
++-
++-
+  IF (THREADSAFE)
+-@@ -688,7 +704,7 @@ IF (BUILD_CLAR)
++ 	IF (NOT WIN32)
++ 		FIND_PACKAGE(Threads REQUIRED)
++@@ -595,7 +632,12 @@ ELSE()
++ 	ENDIF()
++ 	FILE(GLOB SRC_OS src/unix/*.c src/unix/*.h)
++ ENDIF()
++-FILE(GLOB SRC_GIT2 src/*.c src/*.h src/transports/*.c src/transports/*.h src/xdiff/*.c src/xdiff/*.h)
+++FILE(GLOB SRC_GIT2
+++	src/*.c src/*.h
+++	src/streams/*.c src/streams/*.h
+++	src/transports/*.c src/transports/*.h
+++	src/xdiff/*.c src/xdiff/*.h
+++)
++ 
++ # Determine architecture of the machine
++ IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
++@@ -703,7 +745,7 @@ IF (BUILD_CLAR)
+  	ENDIF ()
+  
+  	ENABLE_TESTING()
+ -	IF (WINHTTP OR OPENSSL_FOUND OR SECURITY_FOUND)
+-+	IF (WINHTTP OR OPENSSL_FOUND OR SECURITY_FOUND OR MBEDTLS_FOUND)
+- 		ADD_TEST(libgit2_clar libgit2_clar -ionline)
+++	IF (HAS_HTTPS_SUPPORT)
++ 		ADD_TEST(libgit2_clar libgit2_clar -ionline -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
+  	ELSE ()
+- 		ADD_TEST(libgit2_clar libgit2_clar -v)
++ 		ADD_TEST(libgit2_clar libgit2_clar -v -xclone::local::git_style_unc_paths -xclone::local::standard_unc_paths_are_written_git_style)
+ diff --git a/cmake/Modules/FindmbedTLS.cmake b/cmake/Modules/FindmbedTLS.cmake
+ new file mode 100644
+-index 0000000..2f4adbc
++index 0000000..9329755
+ --- /dev/null
+ +++ b/cmake/Modules/FindmbedTLS.cmake
+-@@ -0,0 +1,64 @@
++@@ -0,0 +1,93 @@
+ +# - Try to find mbedTLS
+ +# Once done this will define
+ +#
+@@ -72,17 +288,46 @@ index 0000000..2f4adbc
+ +#  MBEDTLS_LIBRARY - path to mbedTLS library
+ +#  MBEDX509_LIBRARY - path to mbedTLS X.509 library
+ +#  MBEDCRYPTO_LIBRARY - path to mbedTLS Crypto library
+++#
+++# Hint
+++#  MBEDTLS_ROOT_DIR can be pointed to a local mbedTLS installation.
+++
+++SET(_MBEDTLS_ROOT_HINTS
+++    ${MBEDTLS_ROOT_DIR}
+++    ENV MBEDTLS_ROOT_DIR
+++)
+++
+++SET(_MBEDTLS_ROOT_HINTS_AND_PATHS
+++    HINTS ${_MBEDTLS_ROOT_HINTS}
+++    PATHS ${_MBEDTLS_ROOT_PATHS}
+++)
+ +
+-+FIND_PATH(MBEDTLS_INCLUDE_DIR mbedtls/version.h)
+++FIND_PATH(MBEDTLS_INCLUDE_DIR
+++    NAMES mbedtls/version.h
+++    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+++    PATH_SUFFIXES include
+++)
+ +
+ +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARIES)
+ +    # Already in cache, be silent
+ +    SET(MBEDTLS_FIND_QUIETLY TRUE)
+ +ENDIF()
+ +
+-+FIND_LIBRARY(MBEDTLS_LIBRARY NAMES mbedtls libmbedtls libmbedx509)
+-+FIND_LIBRARY(MBEDX509_LIBRARY NAMES mbedx509 libmbedx509)
+-+FIND_LIBRARY(MBEDCRYPTO_LIBRARY NAMES mbedcrypto libmbedcrypto)
+++FIND_LIBRARY(MBEDTLS_LIBRARY
+++    NAMES mbedtls libmbedtls
+++    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+++    PATH_SUFFIXES library
+++)
+++FIND_LIBRARY(MBEDX509_LIBRARY
+++    NAMES mbedx509 libmbedx509
+++    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+++    PATH_SUFFIXES library
+++)
+++FIND_LIBRARY(MBEDCRYPTO_LIBRARY
+++    NAMES mbedcrypto libmbedcrypto
+++    ${_MBEDTLS_ROOT_HINTS_AND_PATHS}
+++    PATH_SUFFIXES library
+++)
+ +
+ +IF(MBEDTLS_INCLUDE_DIR AND MBEDTLS_LIBRARY AND MBEDX509_LIBRARY AND MBEDCRYPTO_LIBRARY)
+ +     SET(MBEDTLS_FOUND TRUE)
+@@ -125,68 +370,465 @@ index 0000000..2f4adbc
+ +    MBEDX509_LIBRARY
+ +    MBEDCRYPTO_LIBRARY
+ +)
++diff --git a/script/install-deps-linux.sh b/script/install-deps-linux.sh
++new file mode 100755
++index 0000000..94309b0
++--- /dev/null
+++++ b/script/install-deps-linux.sh
++@@ -0,0 +1,12 @@
+++#!/bin/sh
+++
+++echo "Installing dependencies"
+++if [ "$MBEDTLS" ]; then
+++  git clone https://github.com/ARMmbed/mbedtls.git ../mbedtls
+++  cd ../mbedtls
+++  git checkout mbedtls-2.4.2
+++  cmake -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DUSE_STATIC_MBEDTLS_LIBRARY=OFF .
+++  cmake --build .
+++
+++  echo "mbedTLS built in `pwd`"
+++fi
++diff --git a/src/curl_stream.c b/src/curl_stream.c
++deleted file mode 100644
++index 4e0455c..0000000
++--- a/src/curl_stream.c
+++++ /dev/null
++@@ -1,362 +0,0 @@
++-/*
++- * 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.
++- */
++-
++-#ifdef GIT_CURL
++-
++-#include <curl/curl.h>
++-
++-#include "stream.h"
++-#include "git2/transport.h"
++-#include "buffer.h"
++-#include "vector.h"
++-#include "proxy.h"
++-
++-/* This is for backwards compatibility with curl<7.45.0. */
++-#ifndef CURLINFO_ACTIVESOCKET
++-# define CURLINFO_ACTIVESOCKET CURLINFO_LASTSOCKET
++-# define GIT_CURL_BADSOCKET -1
++-# define git_activesocket_t long
++-#else
++-# define GIT_CURL_BADSOCKET CURL_SOCKET_BAD
++-# define git_activesocket_t curl_socket_t
++-#endif
++-
++-typedef struct {
++-	git_stream parent;
++-	CURL *handle;
++-	curl_socket_t socket;
++-	char curl_error[CURL_ERROR_SIZE + 1];
++-	git_cert_x509 cert_info;
++-	git_strarray cert_info_strings;
++-	git_proxy_options proxy;
++-	git_cred *proxy_cred;
++-} curl_stream;
++-
++-static int seterr_curl(curl_stream *s)
++-{
++-	giterr_set(GITERR_NET, "curl error: %s\n", s->curl_error);
++-	return -1;
++-}
++-
++-GIT_INLINE(int) error_no_credentials(void)
++-{
++-	giterr_set(GITERR_NET, "proxy authentication required, but no callback provided");
++-	return GIT_EAUTH;
++-}
++-
++-static int apply_proxy_creds(curl_stream *s)
++-{
++-	CURLcode res;
++-	git_cred_userpass_plaintext *userpass;
++-
++-	if (!s->proxy_cred)
++-		return GIT_ENOTFOUND;
++-
++-	userpass = (git_cred_userpass_plaintext *) s->proxy_cred;
++-	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXYUSERNAME, userpass->username)) != CURLE_OK)
++-		return seterr_curl(s);
++-	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXYPASSWORD, userpass->password)) != CURLE_OK)
++-		return seterr_curl(s);
++-
++-	return 0;
++-}
++-
++-static int ask_and_apply_proxy_creds(curl_stream *s)
++-{
++-	int error;
++-	git_proxy_options *opts = &s->proxy;
++-
++-	if (!opts->credentials)
++-		return error_no_credentials();
++-
++-	/* TODO: see if PROXYAUTH_AVAIL helps us here */
++-	git_cred_free(s->proxy_cred);
++-	s->proxy_cred = NULL;
++-	giterr_clear();
++-	error = opts->credentials(&s->proxy_cred, opts->url, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, opts->payload);
++-	if (error == GIT_PASSTHROUGH)
++-		return error_no_credentials();
++-	if (error < 0) {
++-		if (!giterr_last())
++-			giterr_set(GITERR_NET, "proxy authentication was aborted by the user");
++-		return error;
++-	}
++-
++-	if (s->proxy_cred->credtype != GIT_CREDTYPE_USERPASS_PLAINTEXT) {
++-		giterr_set(GITERR_NET, "credentials callback returned invalid credential type");
++-		return -1;
++-	}
++-
++-	return apply_proxy_creds(s);
++-}
++-
++-static int curls_connect(git_stream *stream)
++-{
++-	curl_stream *s = (curl_stream *) stream;
++-	git_activesocket_t sockextr;
++-	long connect_last = 0;
++-	int failed_cert = 0, error;
++-	bool retry_connect;
++-	CURLcode res;
++-
++-	/* Apply any credentials we've already established */
++-	error = apply_proxy_creds(s);
++-	if (error < 0 && error != GIT_ENOTFOUND)
++-		return seterr_curl(s);
++-
++-	do {
++-		retry_connect = 0;
++-		res = curl_easy_perform(s->handle);
++-
++-		curl_easy_getinfo(s->handle, CURLINFO_HTTP_CONNECTCODE, &connect_last);
++-
++-		/* HTTP 407 Proxy Authentication Required */
++-		if (connect_last == 407) {
++-			if ((error = ask_and_apply_proxy_creds(s)) < 0)
++-				return error;
++-
++-			retry_connect = true;
++-		}
++-	} while (retry_connect);
++-
++-	if (res != CURLE_OK && res != CURLE_PEER_FAILED_VERIFICATION)
++-		return seterr_curl(s);
++-	if (res == CURLE_PEER_FAILED_VERIFICATION)
++-		failed_cert = 1;
++-
++-	if ((res = curl_easy_getinfo(s->handle, CURLINFO_ACTIVESOCKET, &sockextr)) != CURLE_OK) {
++-		return seterr_curl(s);
++-	}
++-
++-	if (sockextr == GIT_CURL_BADSOCKET) {
++-		giterr_set(GITERR_NET, "curl socket is no longer valid");
++-		return -1;
++-	}
++-
++-	s->socket = sockextr;
++-
++-	if (s->parent.encrypted && failed_cert)
++-		return GIT_ECERTIFICATE;
++-
++-	return 0;
++-}
++-
++-static int curls_certificate(git_cert **out, git_stream *stream)
++-{
++-	int error;
++-	CURLcode res;
++-	struct curl_slist *slist;
++-	struct curl_certinfo *certinfo;
++-	git_vector strings = GIT_VECTOR_INIT;
++-	curl_stream *s = (curl_stream *) stream;
++-
++-	if ((res = curl_easy_getinfo(s->handle, CURLINFO_CERTINFO, &certinfo)) != CURLE_OK)
++-		return seterr_curl(s);
++-
++-	/* No information is available, can happen with SecureTransport */
++-	if (certinfo->num_of_certs == 0) {
++-		s->cert_info.parent.cert_type = GIT_CERT_NONE;
++-		s->cert_info.data             = NULL;
++-		s->cert_info.len              = 0;
++-		return 0;
++-	}
++-
++-	if ((error = git_vector_init(&strings, 8, NULL)) < 0)
++-		return error;
++-
++-	for (slist = certinfo->certinfo[0]; slist; slist = slist->next) {
++-		char *str = git__strdup(slist->data);
++-		GITERR_CHECK_ALLOC(str);
++-		git_vector_insert(&strings, str);
++-	}
++-
++-	/* Copy the contents of the vector into a strarray so we can expose them */
++-	s->cert_info_strings.strings = (char **) strings.contents;
++-	s->cert_info_strings.count   = strings.length;
++-
++-	s->cert_info.parent.cert_type = GIT_CERT_STRARRAY;
++-	s->cert_info.data             = &s->cert_info_strings;
++-	s->cert_info.len              = strings.length;
++-
++-	*out = &s->cert_info.parent;
++-
++-	return 0;
++-}
++-
++-static int curls_set_proxy(git_stream *stream, const git_proxy_options *proxy_opts)
++-{
++-	int error;
++-	CURLcode res;
++-	curl_stream *s = (curl_stream *) stream;
++-
++-	if ((error = git_proxy_options_dup(&s->proxy, proxy_opts)) < 0)
++-		return error;
++-
++-	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXY, s->proxy.url)) != CURLE_OK)
++-		return seterr_curl(s);
++-
++-	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY)) != CURLE_OK)
++-		return seterr_curl(s);
++-
++-	return 0;
++-}
++-
++-static int wait_for(curl_socket_t fd, bool reading)
++-{
++-	int ret;
++-	fd_set infd, outfd, errfd;
++-
++-	FD_ZERO(&infd);
++-	FD_ZERO(&outfd);
++-	FD_ZERO(&errfd);
++-
++-	assert(fd >= 0);
++-	FD_SET(fd, &errfd);
++-	if (reading)
++-		FD_SET(fd, &infd);
++-	else
++-		FD_SET(fd, &outfd);
++-
++-	if ((ret = select(fd + 1, &infd, &outfd, &errfd, NULL)) < 0) {
++-		giterr_set(GITERR_OS, "error in select");
++-		return -1;
++-	}
++-
++-	return 0;
++-}
++-
++-static ssize_t curls_write(git_stream *stream, const char *data, size_t len, int flags)
++-{
++-	int error;
++-	size_t off = 0, sent;
++-	CURLcode res;
++-	curl_stream *s = (curl_stream *) stream;
++-
++-	GIT_UNUSED(flags);
++-
++-	do {
++-		if ((error = wait_for(s->socket, false)) < 0)
++-			return error;
++-
++-		res = curl_easy_send(s->handle, data + off, len - off, &sent);
++-		if (res == CURLE_OK)
++-			off += sent;
++-	} while ((res == CURLE_OK || res == CURLE_AGAIN) && off < len);
++-
++-	if (res != CURLE_OK)
++-		return seterr_curl(s);
++-
++-	return len;
++-}
++-
++-static ssize_t curls_read(git_stream *stream, void *data, size_t len)
++-{
++-	int error;
++-	size_t read;
++-	CURLcode res;
++-	curl_stream *s = (curl_stream *) stream;
++-
++-	do {
++-		if ((error = wait_for(s->socket, true)) < 0)
++-			return error;
++-
++-		res = curl_easy_recv(s->handle, data, len, &read);
++-	} while (res == CURLE_AGAIN);
++-
++-	if (res != CURLE_OK)
++-		return seterr_curl(s);
++-
++-	return read;
++-}
++-
++-static int curls_close(git_stream *stream)
++-{
++-	curl_stream *s = (curl_stream *) stream;
++-
++-	if (!s->handle)
++-		return 0;
++-
++-	curl_easy_cleanup(s->handle);
++-	s->handle = NULL;
++-	s->socket = 0;
++-
++-	return 0;
++-}
++-
++-static void curls_free(git_stream *stream)
++-{
++-	curl_stream *s = (curl_stream *) stream;
++-
++-	curls_close(stream);
++-	git_strarray_free(&s->cert_info_strings);
++-	git__free(s);
++-}
++-
++-int git_curl_stream_new(git_stream **out, const char *host, const char *port)
++-{
++-	curl_stream *st;
++-	CURL *handle;
++-	int iport = 0, error;
++-
++-	st = git__calloc(1, sizeof(curl_stream));
++-	GITERR_CHECK_ALLOC(st);
++-
++-	handle = curl_easy_init();
++-	if (handle == NULL) {
++-		giterr_set(GITERR_NET, "failed to create curl handle");
++-		git__free(st);
++-		return -1;
++-	}
++-
++-	if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) {
++-		git__free(st);
++-		return error;
++-	}
++-
++-	curl_easy_setopt(handle, CURLOPT_URL, host);
++-	curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, st->curl_error);
++-	curl_easy_setopt(handle, CURLOPT_PORT, iport);
++-	curl_easy_setopt(handle, CURLOPT_CONNECT_ONLY, 1);
++-	curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 1);
++-	curl_easy_setopt(handle, CURLOPT_CERTINFO, 1);
++-	curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1);
++-	curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
++-
++-	/* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); */
++-
++-	st->parent.version = GIT_STREAM_VERSION;
++-	st->parent.encrypted = 0; /* we don't encrypt ourselves */
++-	st->parent.proxy_support = 1;
++-	st->parent.connect = curls_connect;
++-	st->parent.certificate = curls_certificate;
++-	st->parent.set_proxy = curls_set_proxy;
++-	st->parent.read = curls_read;
++-	st->parent.write = curls_write;
++-	st->parent.close = curls_close;
++-	st->parent.free = curls_free;
++-	st->handle = handle;
++-
++-	*out = (git_stream *) st;
++-	return 0;
++-}
++-
++-#else
++-
++-#include "stream.h"
++-
++-int git_curl_stream_new(git_stream **out, const char *host, const char *port)
++-{
++-	GIT_UNUSED(out);
++-	GIT_UNUSED(host);
++-	GIT_UNUSED(port);
++-
++-	giterr_set(GITERR_NET, "curl is not supported in this version");
++-	return -1;
++-}
++-
++-
++-#endif
++diff --git a/src/curl_stream.h b/src/curl_stream.h
++deleted file mode 100644
++index 283f0fe..0000000
++--- a/src/curl_stream.h
+++++ /dev/null
++@@ -1,14 +0,0 @@
++-/*
++- * 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.
++- */
++-#ifndef INCLUDE_curl_stream_h__
++-#define INCLUDE_curl_stream_h__
++-
++-#include "git2/sys/stream.h"
++-
++-extern int git_curl_stream_new(git_stream **out, const char *host, const char *port);
++-
++-#endif
+ diff --git a/src/global.c b/src/global.c
+-index e2ad8fe..c5b4269 100644
++index afa57e1..66f1d44 100644
+ --- a/src/global.c
+ +++ b/src/global.c
+-@@ -10,7 +10,11 @@
++@@ -10,7 +10,8 @@
+  #include "sysdir.h"
+  #include "filter.h"
+  #include "merge_driver.h"
+-+#ifdef GIT_OPENSSL
+- #include "openssl_stream.h"
+-+#elif GIT_MBEDTLS
+-+#include "mbedtls_stream.h"
+-+#endif
++-#include "openssl_stream.h"
+++#include "streams/mbedtls.h"
+++#include "streams/openssl.h"
+  #include "thread-utils.h"
+  #include "git2/global.h"
+  #include "transports/ssh.h"
+-@@ -61,8 +65,13 @@ static int init_common(void)
+- 		(ret = git_sysdir_global_init()) == 0 &&
++@@ -62,7 +63,8 @@ static int init_common(void)
+  		(ret = git_filter_global_init()) == 0 &&
+  		(ret = git_merge_driver_global_init()) == 0 &&
+--		(ret = git_transport_ssh_global_init()) == 0 &&
++ 		(ret = git_transport_ssh_global_init()) == 0 &&
+ -		(ret = git_openssl_stream_global_init()) == 0)
+-+		(ret = git_transport_ssh_global_init()) == 0
+-+#ifdef GIT_OPENSSL
+-+		&& (ret = git_openssl_stream_global_init()) == 0
+-+#elif GIT_MBEDTLS
+-+		&& (ret = git_mbedtls_stream_global_init()) == 0
+-+#endif
+-+		)
+++		(ret = git_openssl_stream_global_init()) == 0 &&
+++		(ret = git_mbedtls_stream_global_init()) == 0)
+  		ret = git_mwindow_global_init();
+  
+  	GIT_MEMORY_BARRIER;
+ diff --git a/src/global.h b/src/global.h
+-index 2199515..adadcd9 100644
++index 88f40aa..e4bbabf 100644
+ --- a/src/global.h
+ +++ b/src/global.h
+-@@ -23,6 +23,12 @@ typedef struct {
+- extern SSL_CTX *git__ssl_ctx;
+- #endif
++@@ -24,11 +24,6 @@ typedef struct {
++ 	git_thread *current_thread;
++ } git_global_st;
+  
+-+#ifdef GIT_MBEDTLS
+-+# include "mbedtls/platform.h"
+-+# include "mbedtls/ssl.h"
+-+extern mbedtls_ssl_config *git__ssl_conf;
+-+#endif
+-+
++-#ifdef GIT_OPENSSL
++-# include <openssl/ssl.h>
++-extern SSL_CTX *git__ssl_ctx;
++-#endif
++-
+  git_global_st *git__global_state(void);
+  
+  extern git_mutex git__mwindow_mutex;
+ diff --git a/src/hash.h b/src/hash.h
+-index 0bc02a8..958d23b 100644
++index 0db0339..cba4462 100644
+ --- a/src/hash.h
+ +++ b/src/hash.h
+-@@ -20,6 +20,8 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx);
+- # include "hash/hash_common_crypto.h"
+- #elif defined(OPENSSL_SHA1)
++@@ -24,6 +24,8 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx);
+  # include "hash/hash_openssl.h"
++ #elif defined(GIT_SHA1_WIN32)
++ # include "hash/hash_win32.h"
+ +#elif defined(MBEDTLS_SHA1)
+ +# include "hash/hash_mbedtls.h"
+- #elif defined(WIN32_SHA1)
+- # include "hash/hash_win32.h"
+  #else
++ # include "hash/hash_generic.h"
++ #endif
+ diff --git a/src/hash/hash_mbedtls.c b/src/hash/hash_mbedtls.c
+ new file mode 100644
+ index 0000000..a19d763
+@@ -233,7 +875,7 @@ index 0000000..a19d763
+ +}
+ diff --git a/src/hash/hash_mbedtls.h b/src/hash/hash_mbedtls.h
+ new file mode 100644
+-index 0000000..e50d295
++index 0000000..24196c5
+ --- /dev/null
+ +++ b/src/hash/hash_mbedtls.h
+ @@ -0,0 +1,20 @@
+@@ -257,13 +899,1803 @@ index 0000000..e50d295
+ +#define git_hash_ctx_init(ctx) git_hash_init(ctx)
+ +
+ +#endif /* INCLUDE_hash_mbedtld_h__ */
+-\ No newline at end of file
+-diff --git a/src/mbedtls_stream.c b/src/mbedtls_stream.c
++diff --git a/src/openssl_stream.c b/src/openssl_stream.c
++deleted file mode 100644
++index 759c501..0000000
++--- a/src/openssl_stream.c
+++++ /dev/null
++@@ -1,656 +0,0 @@
++-/*
++- * 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.
++- */
++-
++-#ifdef GIT_OPENSSL
++-
++-#include <ctype.h>
++-
++-#include "global.h"
++-#include "posix.h"
++-#include "stream.h"
++-#include "socket_stream.h"
++-#include "openssl_stream.h"
++-#include "netops.h"
++-#include "git2/transport.h"
++-#include "git2/sys/openssl.h"
++-
++-#ifdef GIT_CURL
++-# include "curl_stream.h"
++-#endif
++-
++-#ifndef GIT_WIN32
++-# include <sys/types.h>
++-# include <sys/socket.h>
++-# include <netinet/in.h>
++-#endif
++-
++-#include <openssl/ssl.h>
++-#include <openssl/err.h>
++-#include <openssl/x509v3.h>
++-#include <openssl/bio.h>
++-
++-SSL_CTX *git__ssl_ctx;
++-
++-#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
++-
++-#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
++-
++-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[i]);
++-	git__free(openssl_locks);
++-}
++-
++-#endif /* GIT_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L */
++-
++-static BIO_METHOD *git_stream_bio_method;
++-static int init_bio_method(void);
++-
++-/**
++- * This function aims to clean-up the SSL context which
++- * we allocated.
++- */
++-static void shutdown_ssl(void)
++-{
++-	if (git_stream_bio_method) {
++-		BIO_meth_free(git_stream_bio_method);
++-		git_stream_bio_method = NULL;
++-	}
++-
++-	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;
++-	const char *ciphers = git_libgit2__ssl_ciphers();
++-
++-	/* Older OpenSSL and MacOS OpenSSL doesn't have this */
++-#ifdef SSL_OP_NO_COMPRESSION
++-	ssl_opts |= SSL_OP_NO_COMPRESSION;
++-#endif
++-
++-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
++-	SSL_load_error_strings();
++-	OpenSSL_add_ssl_algorithms();
++-#else
++-	OPENSSL_init_ssl(0, NULL);
++-#endif
++-
++-	/*
++-	 * 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;
++-	}
++-
++-	if (!ciphers) {
++-		ciphers = GIT_SSL_DEFAULT_CIPHERS;
++-	}
++-
++-	if(!SSL_CTX_set_cipher_list(git__ssl_ctx, ciphers)) {
++-		SSL_CTX_free(git__ssl_ctx);
++-		git__ssl_ctx = NULL;
++-		return -1;
++-	}
++-
++-	if (init_bio_method() < 0) {
++-		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)
++-{
++-#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
++-	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;
++-#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
++-	return 0;
++-#else
++-	giterr_set(GITERR_THREAD, "libgit2 was not built with threads");
++-	return -1;
++-#endif
++-}
++-
++-
++-static int bio_create(BIO *b)
++-{
++-	BIO_set_init(b, 1);
++-	BIO_set_data(b, NULL);
++-
++-	return 1;
++-}
++-
++-static int bio_destroy(BIO *b)
++-{
++-	if (!b)
++-		return 0;
++-
++-	BIO_set_data(b, NULL);
++-
++-	return 1;
++-}
++-
++-static int bio_read(BIO *b, char *buf, int len)
++-{
++-	git_stream *io = (git_stream *) BIO_get_data(b);
++-
++-	return (int) git_stream_read(io, buf, len);
++-}
++-
++-static int bio_write(BIO *b, const char *buf, int len)
++-{
++-	git_stream *io = (git_stream *) BIO_get_data(b);
++-
++-	return (int) git_stream_write(io, buf, len, 0);
++-}
++-
++-static long bio_ctrl(BIO *b, int cmd, long num, void *ptr)
++-{
++-	GIT_UNUSED(b);
++-	GIT_UNUSED(num);
++-	GIT_UNUSED(ptr);
++-
++-	if (cmd == BIO_CTRL_FLUSH)
++-		return 1;
++-
++-	return 0;
++-}
++-
++-static int bio_gets(BIO *b, char *buf, int len)
++-{
++-	GIT_UNUSED(b);
++-	GIT_UNUSED(buf);
++-	GIT_UNUSED(len);
++-	return -1;
++-}
++-
++-static int bio_puts(BIO *b, const char *str)
++-{
++-	return bio_write(b, str, strlen(str));
++-}
++-
++-static int init_bio_method(void)
++-{
++-	/* Set up the BIO_METHOD we use for wrapping our own stream implementations */
++-	git_stream_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "git_stream");
++-	GITERR_CHECK_ALLOC(git_stream_bio_method);
++-
++-	BIO_meth_set_write(git_stream_bio_method, bio_write);
++-	BIO_meth_set_read(git_stream_bio_method, bio_read);
++-	BIO_meth_set_puts(git_stream_bio_method, bio_puts);
++-	BIO_meth_set_gets(git_stream_bio_method, bio_gets);
++-	BIO_meth_set_ctrl(git_stream_bio_method, bio_ctrl);
++-	BIO_meth_set_create(git_stream_bio_method, bio_create);
++-	BIO_meth_set_destroy(git_stream_bio_method, bio_destroy);
++-
++-	return 0;
++-}
++-
++-static int ssl_set_error(SSL *ssl, int error)
++-{
++-	int err;
++-	unsigned long e;
++-
++-	err = SSL_get_error(ssl, error);
++-
++-	assert(err != SSL_ERROR_WANT_READ);
++-	assert(err != SSL_ERROR_WANT_WRITE);
++-
++-	switch (err) {
++-	case SSL_ERROR_WANT_CONNECT:
++-	case SSL_ERROR_WANT_ACCEPT:
++-		giterr_set(GITERR_NET, "SSL error: connection failure");
++-		break;
++-	case SSL_ERROR_WANT_X509_LOOKUP:
++-		giterr_set(GITERR_NET, "SSL error: x509 error");
++-		break;
++-	case SSL_ERROR_SYSCALL:
++-		e = ERR_get_error();
++-		if (e > 0) {
++-			giterr_set(GITERR_NET, "SSL error: %s",
++-					ERR_error_string(e, NULL));
++-			break;
++-		} else if (error < 0) {
++-			giterr_set(GITERR_OS, "SSL error: syscall failure");
++-			break;
++-		}
++-		giterr_set(GITERR_NET, "SSL error: received early EOF");
++-		return GIT_EEOF;
++-		break;
++-	case SSL_ERROR_SSL:
++-		e = ERR_get_error();
++-		giterr_set(GITERR_NET, "SSL error: %s",
++-				ERR_error_string(e, NULL));
++-		break;
++-	case SSL_ERROR_NONE:
++-	case SSL_ERROR_ZERO_RETURN:
++-	default:
++-		giterr_set(GITERR_NET, "SSL error: unknown error");
++-		break;
++-	}
++-	return -1;
++-}
++-
++-static int ssl_teardown(SSL *ssl)
++-{
++-	int ret;
++-
++-	ret = SSL_shutdown(ssl);
++-	if (ret < 0)
++-		ret = ssl_set_error(ssl, ret);
++-	else
++-		ret = 0;
++-
++-	return ret;
++-}
++-
++-static int check_host_name(const char *name, const char *host)
++-{
++-	if (!strcasecmp(name, host))
++-		return 0;
++-
++-	if (gitno__match_host(name, host) < 0)
++-		return -1;
++-
++-	return 0;
++-}
++-
++-static int verify_server_cert(SSL *ssl, const char *host)
++-{
++-	X509 *cert;
++-	X509_NAME *peer_name;
++-	ASN1_STRING *str;
++-	unsigned char *peer_cn = NULL;
++-	int matched = -1, type = GEN_DNS;
++-	GENERAL_NAMES *alts;
++-	struct in6_addr addr6;
++-	struct in_addr addr4;
++-	void *addr;
++-	int i = -1,j;
++-
++-	if (SSL_get_verify_result(ssl) != X509_V_OK) {
++-		giterr_set(GITERR_SSL, "the SSL certificate is invalid");
++-		return GIT_ECERTIFICATE;
++-	}
++-
++-	/* Try to parse the host as an IP address to see if it is */
++-	if (p_inet_pton(AF_INET, host, &addr4)) {
++-		type = GEN_IPADD;
++-		addr = &addr4;
++-	} else {
++-		if(p_inet_pton(AF_INET6, host, &addr6)) {
++-			type = GEN_IPADD;
++-			addr = &addr6;
++-		}
++-	}
++-
++-
++-	cert = SSL_get_peer_certificate(ssl);
++-	if (!cert) {
++-		giterr_set(GITERR_SSL, "the server did not provide a certificate");
++-		return -1;
++-	}
++-
++-	/* Check the alternative names */
++-	alts = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
++-	if (alts) {
++-		int num;
++-
++-		num = sk_GENERAL_NAME_num(alts);
++-		for (i = 0; i < num && matched != 1; i++) {
++-			const GENERAL_NAME *gn = sk_GENERAL_NAME_value(alts, i);
++-			const char *name = (char *) ASN1_STRING_get0_data(gn->d.ia5);
++-			size_t namelen = (size_t) ASN1_STRING_length(gn->d.ia5);
++-
++-			/* Skip any names of a type we're not looking for */
++-			if (gn->type != type)
++-				continue;
++-
++-			if (type == GEN_DNS) {
++-				/* If it contains embedded NULs, don't even try */
++-				if (memchr(name, '\0', namelen))
++-					continue;
++-
++-				if (check_host_name(name, host) < 0)
++-					matched = 0;
++-				else
++-					matched = 1;
++-			} else if (type == GEN_IPADD) {
++-				/* Here name isn't so much a name but a binary representation of the IP */
++-				matched = !!memcmp(name, addr, namelen);
++-			}
++-		}
++-	}
++-	GENERAL_NAMES_free(alts);
++-
++-	if (matched == 0)
++-		goto cert_fail_name;
++-
++-	if (matched == 1)
++-		return 0;
++-
++-	/* If no alternative names are available, check the common name */
++-	peer_name = X509_get_subject_name(cert);
++-	if (peer_name == NULL)
++-		goto on_error;
++-
++-	if (peer_name) {
++-		/* Get the index of the last CN entry */
++-		while ((j = X509_NAME_get_index_by_NID(peer_name, NID_commonName, i)) >= 0)
++-			i = j;
++-	}
++-
++-	if (i < 0)
++-		goto on_error;
++-
++-	str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(peer_name, i));
++-	if (str == NULL)
++-		goto on_error;
++-
++-	/* Work around a bug in OpenSSL whereby ASN1_STRING_to_UTF8 fails if it's already in utf-8 */
++-	if (ASN1_STRING_type(str) == V_ASN1_UTF8STRING) {
++-		int size = ASN1_STRING_length(str);
++-
++-		if (size > 0) {
++-			peer_cn = OPENSSL_malloc(size + 1);
++-			GITERR_CHECK_ALLOC(peer_cn);
++-			memcpy(peer_cn, ASN1_STRING_get0_data(str), size);
++-			peer_cn[size] = '\0';
++-		} else {
++-			goto cert_fail_name;
++-		}
++-	} else {
++-		int size = ASN1_STRING_to_UTF8(&peer_cn, str);
++-		GITERR_CHECK_ALLOC(peer_cn);
++-		if (memchr(peer_cn, '\0', size))
++-			goto cert_fail_name;
++-	}
++-
++-	if (check_host_name((char *)peer_cn, host) < 0)
++-		goto cert_fail_name;
++-
++-	OPENSSL_free(peer_cn);
++-
++-	return 0;
++-
++-on_error:
++-	OPENSSL_free(peer_cn);
++-	return ssl_set_error(ssl, 0);
++-
++-cert_fail_name:
++-	OPENSSL_free(peer_cn);
++-	giterr_set(GITERR_SSL, "hostname does not match certificate");
++-	return GIT_ECERTIFICATE;
++-}
++-
++-typedef struct {
++-	git_stream parent;
++-	git_stream *io;
++-	bool connected;
++-	char *host;
++-	SSL *ssl;
++-	git_cert_x509 cert_info;
++-} openssl_stream;
++-
++-int openssl_close(git_stream *stream);
++-
++-int openssl_connect(git_stream *stream)
++-{
++-	int ret;
++-	BIO *bio;
++-	openssl_stream *st = (openssl_stream *) stream;
++-
++-	if ((ret = git_stream_connect(st->io)) < 0)
++-		return ret;
++-
++-	st->connected = true;
++-
++-	bio = BIO_new(git_stream_bio_method);
++-	GITERR_CHECK_ALLOC(bio);
++-
++-	BIO_set_data(bio, st->io);
++-	SSL_set_bio(st->ssl, bio, bio);
++-
++-	/* specify the host in case SNI is needed */
++-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
++-	SSL_set_tlsext_host_name(st->ssl, st->host);
++-#endif
++-
++-	if ((ret = SSL_connect(st->ssl)) <= 0)
++-		return ssl_set_error(st->ssl, ret);
++-
++-	return verify_server_cert(st->ssl, st->host);
++-}
++-
++-int openssl_certificate(git_cert **out, git_stream *stream)
++-{
++-	openssl_stream *st = (openssl_stream *) stream;
++-	int len;
++-	X509 *cert = SSL_get_peer_certificate(st->ssl);
++-	unsigned char *guard, *encoded_cert;
++-
++-	/* Retrieve the length of the certificate first */
++-	len = i2d_X509(cert, NULL);
++-	if (len < 0) {
++-		giterr_set(GITERR_NET, "failed to retrieve certificate information");
++-		return -1;
++-	}
++-
++-	encoded_cert = git__malloc(len);
++-	GITERR_CHECK_ALLOC(encoded_cert);
++-	/* i2d_X509 makes 'guard' point to just after the data */
++-	guard = encoded_cert;
++-
++-	len = i2d_X509(cert, &guard);
++-	if (len < 0) {
++-		git__free(encoded_cert);
++-		giterr_set(GITERR_NET, "failed to retrieve certificate information");
++-		return -1;
++-	}
++-
++-	st->cert_info.parent.cert_type = GIT_CERT_X509;
++-	st->cert_info.data = encoded_cert;
++-	st->cert_info.len = len;
++-
++-	*out = &st->cert_info.parent;
++-
++-	return 0;
++-}
++-
++-static int openssl_set_proxy(git_stream *stream, const git_proxy_options *proxy_opts)
++-{
++-	openssl_stream *st = (openssl_stream *) stream;
++-
++-	return git_stream_set_proxy(st->io, proxy_opts);
++-}
++-
++-ssize_t openssl_write(git_stream *stream, const char *data, size_t len, int flags)
++-{
++-	openssl_stream *st = (openssl_stream *) stream;
++-	int ret;
++-
++-	GIT_UNUSED(flags);
++-
++-	if ((ret = SSL_write(st->ssl, data, len)) <= 0) {
++-		return ssl_set_error(st->ssl, ret);
++-	}
++-
++-	return ret;
++-}
++-
++-ssize_t openssl_read(git_stream *stream, void *data, size_t len)
++-{
++-	openssl_stream *st = (openssl_stream *) stream;
++-	int ret;
++-
++-	if ((ret = SSL_read(st->ssl, data, len)) <= 0)
++-		return ssl_set_error(st->ssl, ret);
++-
++-	return ret;
++-}
++-
++-int openssl_close(git_stream *stream)
++-{
++-	openssl_stream *st = (openssl_stream *) stream;
++-	int ret;
++-
++-	if (st->connected && (ret = ssl_teardown(st->ssl)) < 0)
++-		return -1;
++-
++-	st->connected = false;
++-
++-	return git_stream_close(st->io);
++-}
++-
++-void openssl_free(git_stream *stream)
++-{
++-	openssl_stream *st = (openssl_stream *) stream;
++-
++-	SSL_free(st->ssl);
++-	git__free(st->host);
++-	git__free(st->cert_info.data);
++-	git_stream_free(st->io);
++-	git__free(st);
++-}
++-
++-int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
++-{
++-	int error;
++-	openssl_stream *st;
++-
++-	st = git__calloc(1, sizeof(openssl_stream));
++-	GITERR_CHECK_ALLOC(st);
++-
++-	st->io = NULL;
++-#ifdef GIT_CURL
++-	error = git_curl_stream_new(&st->io, host, port);
++-#else
++-	error = git_socket_stream_new(&st->io, host, port);
++-#endif
++-
++-	if (error < 0)
++-		goto out_err;
++-
++-	st->ssl = SSL_new(git__ssl_ctx);
++-	if (st->ssl == NULL) {
++-		giterr_set(GITERR_SSL, "failed to create ssl object");
++-		error = -1;
++-		goto out_err;
++-	}
++-
++-	st->host = git__strdup(host);
++-	GITERR_CHECK_ALLOC(st->host);
++-
++-	st->parent.version = GIT_STREAM_VERSION;
++-	st->parent.encrypted = 1;
++-	st->parent.proxy_support = git_stream_supports_proxy(st->io);
++-	st->parent.connect = openssl_connect;
++-	st->parent.certificate = openssl_certificate;
++-	st->parent.set_proxy = openssl_set_proxy;
++-	st->parent.read = openssl_read;
++-	st->parent.write = openssl_write;
++-	st->parent.close = openssl_close;
++-	st->parent.free = openssl_free;
++-
++-	*out = (git_stream *) st;
++-	return 0;
++-
++-out_err:
++-	git_stream_free(st->io);
++-	git__free(st);
++-
++-	return error;
++-}
++-
++-#else
++-
++-#include "stream.h"
++-#include "git2/sys/openssl.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);
++-	GIT_UNUSED(host);
++-	GIT_UNUSED(port);
++-
++-	giterr_set(GITERR_SSL, "openssl is not supported in this version");
++-	return -1;
++-}
++-
++-#endif
++diff --git a/src/openssl_stream.h b/src/openssl_stream.h
++deleted file mode 100644
++index f5e59da..0000000
++--- a/src/openssl_stream.h
+++++ /dev/null
++@@ -1,122 +0,0 @@
++-/*
++- * 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.
++- */
++-#ifndef INCLUDE_openssl_stream_h__
++-#define INCLUDE_openssl_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);
++-
++-/*
++- * 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
++- * we can program against the interface instead of littering the implementation
++- * with ifdefs.
++- */
++-#ifdef GIT_OPENSSL
++-# include <openssl/ssl.h>
++-# include <openssl/err.h>
++-# include <openssl/x509v3.h>
++-# include <openssl/bio.h>
++-
++-
++-
++-# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
++-
++-GIT_INLINE(BIO_METHOD*) BIO_meth_new(int type, const char *name)
++-{
++-	BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
++-	if (!meth) {
++-		return NULL;
++-	}
++-
++-	meth->type = type;
++-	meth->name = name;
++-
++-	return meth;
++-}
++-
++-GIT_INLINE(void) BIO_meth_free(BIO_METHOD *biom)
++-{
++-	git__free(biom);
++-}
++-
++-GIT_INLINE(int) BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
++-{
++-	biom->bwrite = write;
++-	return 1;
++-}
++-
++-GIT_INLINE(int) BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
++-{
++-	biom->bread = read;
++-	return 1;
++-}
++-
++-GIT_INLINE(int) BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
++-{
++-	biom->bputs = puts;
++-	return 1;
++-}
++-
++-GIT_INLINE(int) BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
++-
++-{
++-	biom->bgets = gets;
++-	return 1;
++-}
++-
++-GIT_INLINE(int) BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
++-{
++-	biom->ctrl = ctrl;
++-	return 1;
++-}
++-
++-GIT_INLINE(int) BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
++-{
++-	biom->create = create;
++-	return 1;
++-}
++-
++-GIT_INLINE(int) BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
++-{
++-	biom->destroy = destroy;
++-	return 1;
++-}
++-
++-GIT_INLINE(int) BIO_get_new_index(void)
++-{
++-	/* This exists as of 1.1 so before we'd just have 0 */
++-	return 0;
++-}
++-
++-GIT_INLINE(void) BIO_set_init(BIO *b, int init)
++-{
++-	b->init = init;
++-}
++-
++-GIT_INLINE(void) BIO_set_data(BIO *a, void *ptr)
++-{
++-	a->ptr = ptr;
++-}
++-
++-GIT_INLINE(void*) BIO_get_data(BIO *a)
++-{
++-	return a->ptr;
++-}
++-
++-GIT_INLINE(const unsigned char *) ASN1_STRING_get0_data(const ASN1_STRING *x)
++-{
++-	return ASN1_STRING_data((ASN1_STRING *)x);
++-}
++-
++-# endif // OpenSSL < 1.1
++-#endif // GIT_OPENSSL
++-
++-#endif
++diff --git a/src/settings.c b/src/settings.c
++index 52b861b..3a46f0d 100644
++--- a/src/settings.c
+++++ b/src/settings.c
++@@ -9,6 +9,10 @@
++ # include <openssl/err.h>
++ #endif
++ 
+++#ifdef GIT_MBEDTLS
+++# include <mbedtls/error.h>
+++#endif
+++
++ #include <git2.h>
++ #include "common.h"
++ #include "sysdir.h"
++@@ -18,6 +22,8 @@
++ #include "odb.h"
++ #include "refs.h"
++ #include "transports/smart.h"
+++#include "streams/openssl.h"
+++#include "streams/mbedtls.h"
++ 
++ void git_libgit2_version(int *major, int *minor, int *rev)
++ {
++@@ -171,14 +177,19 @@ int git_libgit2_opts(int key, ...)
++ 		{
++ 			const char *file = va_arg(ap, const char *);
++ 			const char *path = va_arg(ap, const char *);
++-			if (!SSL_CTX_load_verify_locations(git__ssl_ctx, file, path)) {
++-				giterr_set(GITERR_NET, "SSL error: %s",
++-					ERR_error_string(ERR_get_error(), NULL));
++-				error = -1;
++-			}
+++			error = git_openssl_set_cert_file(file, path);
+++		}
+++#elif GIT_MBEDTLS
+++		{
+++			const char *file = va_arg(ap, const char *);
+++			const char *path = va_arg(ap, const char *);
+++			if (file)
+++				error = git_mbedtls_set_cert_file(file, 0);
+++			if (error && path)
+++				error = git_mbedtls_set_cert_file(path, 0);
++ 		}
++ #else
++-		giterr_set(GITERR_NET, "cannot set certificate locations: OpenSSL is not enabled");
+++		giterr_set(GITERR_NET, "cannot set certificate locations: OpenSSL or mbedTLS is not enabled");
++ 		error = -1;
++ #endif
++ 		break;
++diff --git a/src/socket_stream.c b/src/socket_stream.c
++deleted file mode 100644
++index c0a1684..0000000
++--- a/src/socket_stream.c
+++++ /dev/null
++@@ -1,210 +0,0 @@
++-/*
++- * 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 "common.h"
++-#include "posix.h"
++-#include "netops.h"
++-#include "stream.h"
++-#include "socket_stream.h"
++-
++-#ifndef _WIN32
++-#	include <sys/types.h>
++-#	include <sys/socket.h>
++-#	include <sys/select.h>
++-#	include <sys/time.h>
++-#	include <netdb.h>
++-#	include <netinet/in.h>
++-#       include <arpa/inet.h>
++-#else
++-#	include <winsock2.h>
++-#	include <ws2tcpip.h>
++-#	ifdef _MSC_VER
++-#		pragma comment(lib, "ws2_32")
++-#	endif
++-#endif
++-
++-#ifdef GIT_WIN32
++-static void net_set_error(const char *str)
++-{
++-	int error = WSAGetLastError();
++-	char * win32_error = git_win32_get_error_message(error);
++-
++-	if (win32_error) {
++-		giterr_set(GITERR_NET, "%s: %s", str, win32_error);
++-		git__free(win32_error);
++-	} else {
++-		giterr_set(GITERR_NET, str);
++-	}
++-}
++-#else
++-static void net_set_error(const char *str)
++-{
++-	giterr_set(GITERR_NET, "%s: %s", str, strerror(errno));
++-}
++-#endif
++-
++-static int close_socket(GIT_SOCKET s)
++-{
++-	if (s == INVALID_SOCKET)
++-		return 0;
++-
++-#ifdef GIT_WIN32
++-	if (SOCKET_ERROR == closesocket(s))
++-		return -1;
++-
++-	if (0 != WSACleanup()) {
++-		giterr_set(GITERR_OS, "winsock cleanup failed");
++-		return -1;
++-	}
++-
++-	return 0;
++-#else
++-	return close(s);
++-#endif
++-
++-}
++-
++-int socket_connect(git_stream *stream)
++-{
++-	struct addrinfo *info = NULL, *p;
++-	struct addrinfo hints;
++-	git_socket_stream *st = (git_socket_stream *) stream;
++-	GIT_SOCKET s = INVALID_SOCKET;
++-	int ret;
++-
++-#ifdef GIT_WIN32
++-	/* on win32, the WSA context needs to be initialized
++-	 * before any socket calls can be performed */
++-	WSADATA wsd;
++-
++-	if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
++-		giterr_set(GITERR_OS, "winsock init failed");
++-		return -1;
++-	}
++-
++-	if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2) {
++-		WSACleanup();
++-		giterr_set(GITERR_OS, "winsock init failed");
++-		return -1;
++-	}
++-#endif
++-
++-	memset(&hints, 0x0, sizeof(struct addrinfo));
++-	hints.ai_socktype = SOCK_STREAM;
++-	hints.ai_family = AF_UNSPEC;
++-
++-	if ((ret = p_getaddrinfo(st->host, st->port, &hints, &info)) != 0) {
++-		giterr_set(GITERR_NET,
++-			   "failed to resolve address for %s: %s", st->host, p_gai_strerror(ret));
++-		return -1;
++-	}
++-
++-	for (p = info; p != NULL; p = p->ai_next) {
++-		s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
++-
++-		if (s == INVALID_SOCKET)
++-			continue;
++-
++-		if (connect(s, p->ai_addr, (socklen_t)p->ai_addrlen) == 0)
++-			break;
++-
++-		/* If we can't connect, try the next one */
++-		close_socket(s);
++-		s = INVALID_SOCKET;
++-	}
++-
++-	/* Oops, we couldn't connect to any address */
++-	if (s == INVALID_SOCKET && p == NULL) {
++-		giterr_set(GITERR_OS, "failed to connect to %s", st->host);
++-		p_freeaddrinfo(info);
++-		return -1;
++-	}
++-
++-	st->s = s;
++-	p_freeaddrinfo(info);
++-	return 0;
++-}
++-
++-ssize_t socket_write(git_stream *stream, const char *data, size_t len, int flags)
++-{
++-	ssize_t ret;
++-	size_t off = 0;
++-	git_socket_stream *st = (git_socket_stream *) stream;
++-
++-	while (off < len) {
++-		errno = 0;
++-		ret = p_send(st->s, data + off, len - off, flags);
++-		if (ret < 0) {
++-			net_set_error("Error sending data");
++-			return -1;
++-		}
++-
++-		off += ret;
++-	}
++-
++-	return off;
++-}
++-
++-ssize_t socket_read(git_stream *stream, void *data, size_t len)
++-{
++-	ssize_t ret;
++-	git_socket_stream *st = (git_socket_stream *) stream;
++-
++-	if ((ret = p_recv(st->s, data, len, 0)) < 0)
++-		net_set_error("Error receiving socket data");
++-
++-	return ret;
++-}
++-
++-int socket_close(git_stream *stream)
++-{
++-	git_socket_stream *st = (git_socket_stream *) stream;
++-	int error;
++-
++-	error = close_socket(st->s);
++-	st->s = INVALID_SOCKET;
++-
++-	return error;
++-}
++-
++-void socket_free(git_stream *stream)
++-{
++-	git_socket_stream *st = (git_socket_stream *) stream;
++-
++-	git__free(st->host);
++-	git__free(st->port);
++-	git__free(st);
++-}
++-
++-int git_socket_stream_new(git_stream **out, const char *host, const char *port)
++-{
++-	git_socket_stream *st;
++-
++-	assert(out && host);
++-
++-	st = git__calloc(1, sizeof(git_socket_stream));
++-	GITERR_CHECK_ALLOC(st);
++-
++-	st->host = git__strdup(host);
++-	GITERR_CHECK_ALLOC(st->host);
++-
++-	if (port) {
++-		st->port = git__strdup(port);
++-		GITERR_CHECK_ALLOC(st->port);
++-	}
++-
++-	st->parent.version = GIT_STREAM_VERSION;
++-	st->parent.connect = socket_connect;
++-	st->parent.write = socket_write;
++-	st->parent.read = socket_read;
++-	st->parent.close = socket_close;
++-	st->parent.free = socket_free;
++-	st->s = INVALID_SOCKET;
++-
++-	*out = (git_stream *) st;
++-	return 0;
++-}
++diff --git a/src/socket_stream.h b/src/socket_stream.h
++deleted file mode 100644
++index 8e9949f..0000000
++--- a/src/socket_stream.h
+++++ /dev/null
++@@ -1,21 +0,0 @@
++-/*
++- * 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.
++- */
++-#ifndef INCLUDE_socket_stream_h__
++-#define INCLUDE_socket_stream_h__
++-
++-#include "netops.h"
++-
++-typedef struct {
++-	git_stream parent;
++-	char *host;
++-	char *port;
++-	GIT_SOCKET s;
++-} git_socket_stream;
++-
++-extern int git_socket_stream_new(git_stream **out, const char *host, const char *port);
++-
++-#endif
++diff --git a/src/stransport_stream.c b/src/stransport_stream.c
++deleted file mode 100644
++index 50ed945..0000000
++--- a/src/stransport_stream.c
+++++ /dev/null
++@@ -1,294 +0,0 @@
++-/*
++- * 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.
++- */
++-
++-#ifdef GIT_SECURE_TRANSPORT
++-
++-#include <CoreFoundation/CoreFoundation.h>
++-#include <Security/SecureTransport.h>
++-#include <Security/SecCertificate.h>
++-
++-#include "git2/transport.h"
++-
++-#include "socket_stream.h"
++-#include "curl_stream.h"
++-
++-static int stransport_error(OSStatus ret)
++-{
++-	CFStringRef message;
++-
++-	if (ret == noErr || ret == errSSLClosedGraceful) {
++-		giterr_clear();
++-		return 0;
++-	}
++-
++-#if !TARGET_OS_IPHONE
++-	message = SecCopyErrorMessageString(ret, NULL);
++-	GITERR_CHECK_ALLOC(message);
++-
++-	giterr_set(GITERR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
++-	CFRelease(message);
++-#else
++-    giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
++-    GIT_UNUSED(message);
++-#endif
++-
++-	return -1;
++-}
++-
++-typedef struct {
++-	git_stream parent;
++-	git_stream *io;
++-	SSLContextRef ctx;
++-	CFDataRef der_data;
++-	git_cert_x509 cert_info;
++-} stransport_stream;
++-
++-static int stransport_connect(git_stream *stream)
++-{
++-	stransport_stream *st = (stransport_stream *) stream;
++-	int error;
++-	SecTrustRef trust = NULL;
++-	SecTrustResultType sec_res;
++-	OSStatus ret;
++-
++-	if ((error = git_stream_connect(st->io)) < 0)
++-		return error;
++-
++-	ret = SSLHandshake(st->ctx);
++-	if (ret != errSSLServerAuthCompleted) {
++-		giterr_set(GITERR_SSL, "unexpected return value from ssl handshake %d", ret);
++-		return -1;
++-	}
++-
++-	if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
++-		goto on_error;
++-
++-	if (!trust)
++-		return GIT_ECERTIFICATE;
++-
++-	if ((ret = SecTrustEvaluate(trust, &sec_res)) != noErr)
++-		goto on_error;
++-
++-	CFRelease(trust);
++-
++-	if (sec_res == kSecTrustResultInvalid || sec_res == kSecTrustResultOtherError) {
++-		giterr_set(GITERR_SSL, "internal security trust error");
++-		return -1;
++-	}
++-
++-	if (sec_res == kSecTrustResultDeny || sec_res == kSecTrustResultRecoverableTrustFailure ||
++-	    sec_res == kSecTrustResultFatalTrustFailure)
++-		return GIT_ECERTIFICATE;
++-
++-	return 0;
++-
++-on_error:
++-	if (trust)
++-		CFRelease(trust);
++-
++-	return stransport_error(ret);
++-}
++-
++-static int stransport_certificate(git_cert **out, git_stream *stream)
++-{
++-	stransport_stream *st = (stransport_stream *) stream;
++-	SecTrustRef trust = NULL;
++-	SecCertificateRef sec_cert;
++-	OSStatus ret;
++-
++-	if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
++-		return stransport_error(ret);
++-
++-	sec_cert = SecTrustGetCertificateAtIndex(trust, 0);
++-	st->der_data = SecCertificateCopyData(sec_cert);
++-	CFRelease(trust);
++-
++-	if (st->der_data == NULL) {
++-		giterr_set(GITERR_SSL, "retrieved invalid certificate data");
++-		return -1;
++-	}
++-
++-	st->cert_info.parent.cert_type = GIT_CERT_X509;
++-	st->cert_info.data = (void *) CFDataGetBytePtr(st->der_data);
++-	st->cert_info.len = CFDataGetLength(st->der_data);
++-
++-	*out = (git_cert *)&st->cert_info;
++-	return 0;
++-}
++-
++-static int stransport_set_proxy(
++-	git_stream *stream,
++-	const git_proxy_options *proxy_opts)
++-{
++-	stransport_stream *st = (stransport_stream *) stream;
++-
++-	return git_stream_set_proxy(st->io, proxy_opts);
++-}
++-
++-/*
++- * Contrary to typical network IO callbacks, Secure Transport write callback is
++- * expected to write *all* passed data, not just as much as it can, and any
++- * other case would be considered a failure.
++- *
++- * This behavior is actually not specified in the Apple documentation, but is
++- * required for things to work correctly (and incidentally, that's also how
++- * Apple implements it in its projects at opensource.apple.com).
++- *
++- * Libgit2 streams happen to already have this very behavior so this is just
++- * passthrough.
++- */
++-static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len)
++-{
++-	git_stream *io = (git_stream *) conn;
++-
++-	if (git_stream_write(io, data, *len, 0) < 0) {
++-		return -36; /* "ioErr" from MacErrors.h which is not available on iOS */
++-	}
++-
++-	return noErr;
++-}
++-
++-static ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int flags)
++-{
++-	stransport_stream *st = (stransport_stream *) stream;
++-	size_t data_len, processed;
++-	OSStatus ret;
++-
++-	GIT_UNUSED(flags);
++-
++-	data_len = len;
++-	if ((ret = SSLWrite(st->ctx, data, data_len, &processed)) != noErr)
++-		return stransport_error(ret);
++-
++-	return processed;
++-}
++-
++-/*
++- * Contrary to typical network IO callbacks, Secure Transport read callback is
++- * expected to read *exactly* the requested number of bytes, not just as much
++- * as it can, and any other case would be considered a failure.
++- *
++- * This behavior is actually not specified in the Apple documentation, but is
++- * required for things to work correctly (and incidentally, that's also how
++- * Apple implements it in its projects at opensource.apple.com).
++- */
++-static OSStatus read_cb(SSLConnectionRef conn, void *data, size_t *len)
++-{
++-	git_stream *io = (git_stream *) conn;
++-	OSStatus error = noErr;
++-	size_t off = 0;
++-	ssize_t ret;
++-
++-	do {
++-		ret = git_stream_read(io, data + off, *len - off);
++-		if (ret < 0) {
++-			error = -36; /* "ioErr" from MacErrors.h which is not available on iOS */
++-			break;
++-		}
++-		if (ret == 0) {
++-			error = errSSLClosedGraceful;
++-			break;
++-		}
++-
++-		off += ret;
++-	} while (off < *len);
++-
++-	*len = off;
++-	return error;
++-}
++-
++-static ssize_t stransport_read(git_stream *stream, void *data, size_t len)
++-{
++-	stransport_stream *st = (stransport_stream *) stream;
++-	size_t processed;
++-	OSStatus ret;
++-
++-	if ((ret = SSLRead(st->ctx, data, len, &processed)) != noErr)
++-		return stransport_error(ret);
++-
++-	return processed;
++-}
++-
++-static int stransport_close(git_stream *stream)
++-{
++-	stransport_stream *st = (stransport_stream *) stream;
++-	OSStatus ret;
++-
++-	ret = SSLClose(st->ctx);
++-	if (ret != noErr && ret != errSSLClosedGraceful)
++-		return stransport_error(ret);
++-
++-	return git_stream_close(st->io);
++-}
++-
++-static void stransport_free(git_stream *stream)
++-{
++-	stransport_stream *st = (stransport_stream *) stream;
++-
++-	git_stream_free(st->io);
++-	CFRelease(st->ctx);
++-	if (st->der_data)
++-		CFRelease(st->der_data);
++-	git__free(st);
++-}
++-
++-int git_stransport_stream_new(git_stream **out, const char *host, const char *port)
++-{
++-	stransport_stream *st;
++-	int error;
++-	OSStatus ret;
++-
++-	assert(out && host);
++-
++-	st = git__calloc(1, sizeof(stransport_stream));
++-	GITERR_CHECK_ALLOC(st);
++-
++-#ifdef GIT_CURL
++-	error = git_curl_stream_new(&st->io, host, port);
++-#else
++-	error = git_socket_stream_new(&st->io, host, port);
++-#endif
++-
++-	if (error < 0){
++-		git__free(st);
++-		return error;
++-	}
++-
++-	st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
++-	if (!st->ctx) {
++-		giterr_set(GITERR_NET, "failed to create SSL context");
++-		git__free(st);
++-		return -1;
++-	}
++-
++-	if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr ||
++-	    (ret = SSLSetConnection(st->ctx, st->io)) != noErr ||
++-	    (ret = SSLSetSessionOption(st->ctx, kSSLSessionOptionBreakOnServerAuth, true)) != noErr ||
++-	    (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr ||
++-	    (ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr ||
++-	    (ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) {
++-		CFRelease(st->ctx);
++-		git__free(st);
++-		return stransport_error(ret);
++-	}
++-
++-	st->parent.version = GIT_STREAM_VERSION;
++-	st->parent.encrypted = 1;
++-	st->parent.proxy_support = git_stream_supports_proxy(st->io);
++-	st->parent.connect = stransport_connect;
++-	st->parent.certificate = stransport_certificate;
++-	st->parent.set_proxy = stransport_set_proxy;
++-	st->parent.read = stransport_read;
++-	st->parent.write = stransport_write;
++-	st->parent.close = stransport_close;
++-	st->parent.free = stransport_free;
++-
++-	*out = (git_stream *) st;
++-	return 0;
++-}
++-
++-#endif
++diff --git a/src/stransport_stream.h b/src/stransport_stream.h
++deleted file mode 100644
++index 714f902..0000000
++--- a/src/stransport_stream.h
+++++ /dev/null
++@@ -1,14 +0,0 @@
++-/*
++- * 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.
++- */
++-#ifndef INCLUDE_stransport_stream_h__
++-#define INCLUDE_stransport_stream_h__
++-
++-#include "git2/sys/stream.h"
++-
++-extern int git_stransport_stream_new(git_stream **out, const char *host, const char *port);
++-
++-#endif
++diff --git a/src/streams/curl.c b/src/streams/curl.c
++new file mode 100644
++index 0000000..4e0455c
++--- /dev/null
+++++ b/src/streams/curl.c
++@@ -0,0 +1,362 @@
+++/*
+++ * 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.
+++ */
+++
+++#ifdef GIT_CURL
+++
+++#include <curl/curl.h>
+++
+++#include "stream.h"
+++#include "git2/transport.h"
+++#include "buffer.h"
+++#include "vector.h"
+++#include "proxy.h"
+++
+++/* This is for backwards compatibility with curl<7.45.0. */
+++#ifndef CURLINFO_ACTIVESOCKET
+++# define CURLINFO_ACTIVESOCKET CURLINFO_LASTSOCKET
+++# define GIT_CURL_BADSOCKET -1
+++# define git_activesocket_t long
+++#else
+++# define GIT_CURL_BADSOCKET CURL_SOCKET_BAD
+++# define git_activesocket_t curl_socket_t
+++#endif
+++
+++typedef struct {
+++	git_stream parent;
+++	CURL *handle;
+++	curl_socket_t socket;
+++	char curl_error[CURL_ERROR_SIZE + 1];
+++	git_cert_x509 cert_info;
+++	git_strarray cert_info_strings;
+++	git_proxy_options proxy;
+++	git_cred *proxy_cred;
+++} curl_stream;
+++
+++static int seterr_curl(curl_stream *s)
+++{
+++	giterr_set(GITERR_NET, "curl error: %s\n", s->curl_error);
+++	return -1;
+++}
+++
+++GIT_INLINE(int) error_no_credentials(void)
+++{
+++	giterr_set(GITERR_NET, "proxy authentication required, but no callback provided");
+++	return GIT_EAUTH;
+++}
+++
+++static int apply_proxy_creds(curl_stream *s)
+++{
+++	CURLcode res;
+++	git_cred_userpass_plaintext *userpass;
+++
+++	if (!s->proxy_cred)
+++		return GIT_ENOTFOUND;
+++
+++	userpass = (git_cred_userpass_plaintext *) s->proxy_cred;
+++	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXYUSERNAME, userpass->username)) != CURLE_OK)
+++		return seterr_curl(s);
+++	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXYPASSWORD, userpass->password)) != CURLE_OK)
+++		return seterr_curl(s);
+++
+++	return 0;
+++}
+++
+++static int ask_and_apply_proxy_creds(curl_stream *s)
+++{
+++	int error;
+++	git_proxy_options *opts = &s->proxy;
+++
+++	if (!opts->credentials)
+++		return error_no_credentials();
+++
+++	/* TODO: see if PROXYAUTH_AVAIL helps us here */
+++	git_cred_free(s->proxy_cred);
+++	s->proxy_cred = NULL;
+++	giterr_clear();
+++	error = opts->credentials(&s->proxy_cred, opts->url, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, opts->payload);
+++	if (error == GIT_PASSTHROUGH)
+++		return error_no_credentials();
+++	if (error < 0) {
+++		if (!giterr_last())
+++			giterr_set(GITERR_NET, "proxy authentication was aborted by the user");
+++		return error;
+++	}
+++
+++	if (s->proxy_cred->credtype != GIT_CREDTYPE_USERPASS_PLAINTEXT) {
+++		giterr_set(GITERR_NET, "credentials callback returned invalid credential type");
+++		return -1;
+++	}
+++
+++	return apply_proxy_creds(s);
+++}
+++
+++static int curls_connect(git_stream *stream)
+++{
+++	curl_stream *s = (curl_stream *) stream;
+++	git_activesocket_t sockextr;
+++	long connect_last = 0;
+++	int failed_cert = 0, error;
+++	bool retry_connect;
+++	CURLcode res;
+++
+++	/* Apply any credentials we've already established */
+++	error = apply_proxy_creds(s);
+++	if (error < 0 && error != GIT_ENOTFOUND)
+++		return seterr_curl(s);
+++
+++	do {
+++		retry_connect = 0;
+++		res = curl_easy_perform(s->handle);
+++
+++		curl_easy_getinfo(s->handle, CURLINFO_HTTP_CONNECTCODE, &connect_last);
+++
+++		/* HTTP 407 Proxy Authentication Required */
+++		if (connect_last == 407) {
+++			if ((error = ask_and_apply_proxy_creds(s)) < 0)
+++				return error;
+++
+++			retry_connect = true;
+++		}
+++	} while (retry_connect);
+++
+++	if (res != CURLE_OK && res != CURLE_PEER_FAILED_VERIFICATION)
+++		return seterr_curl(s);
+++	if (res == CURLE_PEER_FAILED_VERIFICATION)
+++		failed_cert = 1;
+++
+++	if ((res = curl_easy_getinfo(s->handle, CURLINFO_ACTIVESOCKET, &sockextr)) != CURLE_OK) {
+++		return seterr_curl(s);
+++	}
+++
+++	if (sockextr == GIT_CURL_BADSOCKET) {
+++		giterr_set(GITERR_NET, "curl socket is no longer valid");
+++		return -1;
+++	}
+++
+++	s->socket = sockextr;
+++
+++	if (s->parent.encrypted && failed_cert)
+++		return GIT_ECERTIFICATE;
+++
+++	return 0;
+++}
+++
+++static int curls_certificate(git_cert **out, git_stream *stream)
+++{
+++	int error;
+++	CURLcode res;
+++	struct curl_slist *slist;
+++	struct curl_certinfo *certinfo;
+++	git_vector strings = GIT_VECTOR_INIT;
+++	curl_stream *s = (curl_stream *) stream;
+++
+++	if ((res = curl_easy_getinfo(s->handle, CURLINFO_CERTINFO, &certinfo)) != CURLE_OK)
+++		return seterr_curl(s);
+++
+++	/* No information is available, can happen with SecureTransport */
+++	if (certinfo->num_of_certs == 0) {
+++		s->cert_info.parent.cert_type = GIT_CERT_NONE;
+++		s->cert_info.data             = NULL;
+++		s->cert_info.len              = 0;
+++		return 0;
+++	}
+++
+++	if ((error = git_vector_init(&strings, 8, NULL)) < 0)
+++		return error;
+++
+++	for (slist = certinfo->certinfo[0]; slist; slist = slist->next) {
+++		char *str = git__strdup(slist->data);
+++		GITERR_CHECK_ALLOC(str);
+++		git_vector_insert(&strings, str);
+++	}
+++
+++	/* Copy the contents of the vector into a strarray so we can expose them */
+++	s->cert_info_strings.strings = (char **) strings.contents;
+++	s->cert_info_strings.count   = strings.length;
+++
+++	s->cert_info.parent.cert_type = GIT_CERT_STRARRAY;
+++	s->cert_info.data             = &s->cert_info_strings;
+++	s->cert_info.len              = strings.length;
+++
+++	*out = &s->cert_info.parent;
+++
+++	return 0;
+++}
+++
+++static int curls_set_proxy(git_stream *stream, const git_proxy_options *proxy_opts)
+++{
+++	int error;
+++	CURLcode res;
+++	curl_stream *s = (curl_stream *) stream;
+++
+++	if ((error = git_proxy_options_dup(&s->proxy, proxy_opts)) < 0)
+++		return error;
+++
+++	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXY, s->proxy.url)) != CURLE_OK)
+++		return seterr_curl(s);
+++
+++	if ((res = curl_easy_setopt(s->handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY)) != CURLE_OK)
+++		return seterr_curl(s);
+++
+++	return 0;
+++}
+++
+++static int wait_for(curl_socket_t fd, bool reading)
+++{
+++	int ret;
+++	fd_set infd, outfd, errfd;
+++
+++	FD_ZERO(&infd);
+++	FD_ZERO(&outfd);
+++	FD_ZERO(&errfd);
+++
+++	assert(fd >= 0);
+++	FD_SET(fd, &errfd);
+++	if (reading)
+++		FD_SET(fd, &infd);
+++	else
+++		FD_SET(fd, &outfd);
+++
+++	if ((ret = select(fd + 1, &infd, &outfd, &errfd, NULL)) < 0) {
+++		giterr_set(GITERR_OS, "error in select");
+++		return -1;
+++	}
+++
+++	return 0;
+++}
+++
+++static ssize_t curls_write(git_stream *stream, const char *data, size_t len, int flags)
+++{
+++	int error;
+++	size_t off = 0, sent;
+++	CURLcode res;
+++	curl_stream *s = (curl_stream *) stream;
+++
+++	GIT_UNUSED(flags);
+++
+++	do {
+++		if ((error = wait_for(s->socket, false)) < 0)
+++			return error;
+++
+++		res = curl_easy_send(s->handle, data + off, len - off, &sent);
+++		if (res == CURLE_OK)
+++			off += sent;
+++	} while ((res == CURLE_OK || res == CURLE_AGAIN) && off < len);
+++
+++	if (res != CURLE_OK)
+++		return seterr_curl(s);
+++
+++	return len;
+++}
+++
+++static ssize_t curls_read(git_stream *stream, void *data, size_t len)
+++{
+++	int error;
+++	size_t read;
+++	CURLcode res;
+++	curl_stream *s = (curl_stream *) stream;
+++
+++	do {
+++		if ((error = wait_for(s->socket, true)) < 0)
+++			return error;
+++
+++		res = curl_easy_recv(s->handle, data, len, &read);
+++	} while (res == CURLE_AGAIN);
+++
+++	if (res != CURLE_OK)
+++		return seterr_curl(s);
+++
+++	return read;
+++}
+++
+++static int curls_close(git_stream *stream)
+++{
+++	curl_stream *s = (curl_stream *) stream;
+++
+++	if (!s->handle)
+++		return 0;
+++
+++	curl_easy_cleanup(s->handle);
+++	s->handle = NULL;
+++	s->socket = 0;
+++
+++	return 0;
+++}
+++
+++static void curls_free(git_stream *stream)
+++{
+++	curl_stream *s = (curl_stream *) stream;
+++
+++	curls_close(stream);
+++	git_strarray_free(&s->cert_info_strings);
+++	git__free(s);
+++}
+++
+++int git_curl_stream_new(git_stream **out, const char *host, const char *port)
+++{
+++	curl_stream *st;
+++	CURL *handle;
+++	int iport = 0, error;
+++
+++	st = git__calloc(1, sizeof(curl_stream));
+++	GITERR_CHECK_ALLOC(st);
+++
+++	handle = curl_easy_init();
+++	if (handle == NULL) {
+++		giterr_set(GITERR_NET, "failed to create curl handle");
+++		git__free(st);
+++		return -1;
+++	}
+++
+++	if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) {
+++		git__free(st);
+++		return error;
+++	}
+++
+++	curl_easy_setopt(handle, CURLOPT_URL, host);
+++	curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, st->curl_error);
+++	curl_easy_setopt(handle, CURLOPT_PORT, iport);
+++	curl_easy_setopt(handle, CURLOPT_CONNECT_ONLY, 1);
+++	curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 1);
+++	curl_easy_setopt(handle, CURLOPT_CERTINFO, 1);
+++	curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1);
+++	curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+++
+++	/* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); */
+++
+++	st->parent.version = GIT_STREAM_VERSION;
+++	st->parent.encrypted = 0; /* we don't encrypt ourselves */
+++	st->parent.proxy_support = 1;
+++	st->parent.connect = curls_connect;
+++	st->parent.certificate = curls_certificate;
+++	st->parent.set_proxy = curls_set_proxy;
+++	st->parent.read = curls_read;
+++	st->parent.write = curls_write;
+++	st->parent.close = curls_close;
+++	st->parent.free = curls_free;
+++	st->handle = handle;
+++
+++	*out = (git_stream *) st;
+++	return 0;
+++}
+++
+++#else
+++
+++#include "stream.h"
+++
+++int git_curl_stream_new(git_stream **out, const char *host, const char *port)
+++{
+++	GIT_UNUSED(out);
+++	GIT_UNUSED(host);
+++	GIT_UNUSED(port);
+++
+++	giterr_set(GITERR_NET, "curl is not supported in this version");
+++	return -1;
+++}
+++
+++
+++#endif
++diff --git a/src/streams/curl.h b/src/streams/curl.h
++new file mode 100644
++index 0000000..283f0fe
++--- /dev/null
+++++ b/src/streams/curl.h
++@@ -0,0 +1,14 @@
+++/*
+++ * 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.
+++ */
+++#ifndef INCLUDE_curl_stream_h__
+++#define INCLUDE_curl_stream_h__
+++
+++#include "git2/sys/stream.h"
+++
+++extern int git_curl_stream_new(git_stream **out, const char *host, const char *port);
+++
+++#endif
++diff --git a/src/streams/mbedtls.c b/src/streams/mbedtls.c
+ new file mode 100644
+-index 0000000..98ff808
++index 0000000..0376ee4
+ --- /dev/null
+-+++ b/src/mbedtls_stream.c
+-@@ -0,0 +1,483 @@
+++++ b/src/streams/mbedtls.c
++@@ -0,0 +1,538 @@
+ +/*
+ + * Copyright (C) the libgit2 contributors. All rights reserved.
+ + *
+@@ -277,26 +2709,26 @@ index 0000000..98ff808
+ +
+ +#include "global.h"
+ +#include "stream.h"
+-+#include "socket_stream.h"
+++#include "streams/socket.h"
+++#include "netops.h"
+ +#include "git2/transport.h"
+++#include "util.h"
+ +
+ +#ifdef GIT_CURL
+-+# include "curl_stream.h"
+++# include "streams/curl.h"
+ +#endif
+ +
+-+#include "mbedtls/config.h"
+-+#include <mbedtls/x509.h>
+-+#include <mbedtls/x509_crt.h>
+++#include <mbedtls/config.h>
+++#include <mbedtls/ssl.h>
+ +#include <mbedtls/error.h>
+-+#include "mbedtls/net.h"
+-+#include "mbedtls/debug.h"
+-+#include "mbedtls/entropy.h"
+-+#include "mbedtls/ctr_drbg.h"
+-+#include "mbedtls/error.h"
+-+#include "mbedtls/certs.h"
+++#include <mbedtls/entropy.h>
+++#include <mbedtls/ctr_drbg.h>
+ +
+ +#ifndef OPENSSLDIR
+-+# define OPENSSLDIR              "/usr/lib/ssl"
+++//# define OPENSSLDIR
+++# define OPENSSLDIR              "/etc/ssl" // Debian
+++//# define OPENSSLDIR              "/usr/lib/ssl" //Ubuntu
+++//# define OPENSSLDIR              "/usr/local/etc/openssl" // mostly-Darwin
+ +#endif
+ +#define X509_CERT_DIR            OPENSSLDIR "/certs"
+ +#define X509_CERT_FILE           OPENSSLDIR "/cert.pem"
+@@ -306,7 +2738,8 @@ index 0000000..98ff808
+ +mbedtls_ssl_config *git__ssl_conf;
+ +mbedtls_entropy_context *mbedtls_entropy;
+ +
+-+#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
+++#define GIT_SSL_DEFAULT_CIPHERS "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256:TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-DSS-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-DSS-WITH-AES-256-GCM-SHA384:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256:TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384:TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA:TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA:TLS-DHE-RSA-WITH-AES-256-CBC-SHA:TLS-DHE-DSS-WITH-AES-128-CBC-SHA256:TLS-DHE-DSS-WITH-AES-256-CBC-SHA256:TLS-DHE-DSS-WITH-AES-128-CBC-SHA:TLS-DHE-DSS-WITH-AES-256-CBC-SHA:TLS-RSA-WITH-AES-128-GCM-SHA256:TLS-RSA-WITH-AES-256-GCM-SHA384:TLS-RSA-WITH-AES-128-C
 BC-SHA256:TLS-RSA-WITH-AES-256-CBC-SHA256:TLS-RSA-WITH-AES-128-CBC-SHA:TLS-RSA-WITH-AES-256-CBC-SHA"
+++#define GIT_SSL_DEFAULT_CIPHERS_COUNT 30
+ +
+ +/**
+ + * This function aims to clean-up the SSL context which
+@@ -314,565 +2747,1985 @@ index 0000000..98ff808
+ + */
+ +static void shutdown_ssl(void)
+ +{
+-+    if (git__ssl_conf) {
+-+        mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
+-+        git__free(git__ssl_conf->ca_chain);
+-+        mbedtls_ctr_drbg_free(git__ssl_conf->p_rng);
+-+        git__free(git__ssl_conf->p_rng);
+-+        mbedtls_ssl_config_free(git__ssl_conf);
+-+        git__free(git__ssl_conf);
+-+        git__ssl_conf = NULL;
+-+    }
+-+    if (mbedtls_entropy) {
+-+        mbedtls_entropy_free(mbedtls_entropy);
+-+        git__free(mbedtls_entropy);
+-+        mbedtls_entropy = NULL;
+-+    }
+++	if (git__ssl_conf) {
+++		mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
+++		git__free(git__ssl_conf->ca_chain);
+++		mbedtls_ctr_drbg_free(git__ssl_conf->p_rng);
+++		git__free(git__ssl_conf->p_rng);
+++		mbedtls_ssl_config_free(git__ssl_conf);
+++		git__free(git__ssl_conf);
+++		git__ssl_conf = NULL;
+++	}
+++	if (mbedtls_entropy) {
+++		mbedtls_entropy_free(mbedtls_entropy);
+++		git__free(mbedtls_entropy);
+++		mbedtls_entropy = NULL;
+++	}
+ +}
+ +
+++int git_mbedtls_set_cert_file(const char *path, int is_dir);
+++
+ +int git_mbedtls_stream_global_init(void)
+ +{
+-+    int ret, isdir;
+-+    char *crtpath;
+-+    struct stat statbuf;
+-+    // const int *cipherids;
+-+    // const char *ciphers = git_libgit2__ssl_ciphers();
+-+
+-+    mbedtls_ctr_drbg_context *ctr_drbg;
+-+
+-+    mbedtls_entropy = git__malloc(sizeof(mbedtls_entropy_context));
+-+    mbedtls_entropy_init(mbedtls_entropy);
+-+
+-+    // Seeding the random number generator
+-+    ctr_drbg = git__malloc(sizeof(mbedtls_ctr_drbg_context));
+-+    mbedtls_ctr_drbg_init(ctr_drbg);
+-+    if (mbedtls_ctr_drbg_seed(ctr_drbg,
+-+                mbedtls_entropy_func,
+-+                mbedtls_entropy, NULL, 0) != 0) {
+-+        mbedtls_ctr_drbg_free(ctr_drbg);
+-+        mbedtls_entropy_free(mbedtls_entropy);
+-+        git__free(ctr_drbg);
+-+        git__free(mbedtls_entropy);
+-+        return -1;
+-+    }
+-+
+-+    // configure TLSv1
+-+    git__ssl_conf = git__malloc(sizeof(mbedtls_ssl_config));
+-+    mbedtls_ssl_config_init(git__ssl_conf);
+-+    if ( mbedtls_ssl_config_defaults(git__ssl_conf,
+-+                MBEDTLS_SSL_IS_CLIENT,
+-+                MBEDTLS_SSL_TRANSPORT_STREAM,
+-+                MBEDTLS_SSL_PRESET_DEFAULT ) != 0) {
+-+        mbedtls_ctr_drbg_free(ctr_drbg);
+-+        git__free(ctr_drbg);
+-+        mbedtls_ssl_config_free(git__ssl_conf);
+-+        git__free(git__ssl_conf);
+-+        git__ssl_conf = NULL;
+-+        return -1;
+-+    }
+-+
+-+    mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED);
+-+    mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);
+-+
+-+    // find locations for which CA certificates
+-+    isdir = 0;
+-+    crtpath = getenv(X509_CERT_FILE_EVP);
+-+    ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode) ? 0 : 1;
+-+    if (ret) {
+-+        isdir = 1;
+-+        crtpath = getenv(X509_CERT_DIR_EVP);
+-+        ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode) ? 0 : 1;
+-+    }
+-+    if (ret) {
+-+        isdir = 0;
+-+        crtpath = X509_CERT_FILE;
+-+        ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode) ? 0 : 1;
+-+    }
+-+    if (ret) {
+-+        isdir = 1;
+-+        crtpath = X509_CERT_DIR;
+-+        ret = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode) ? 0 : 1;
+-+    }
+-+
+-+    // cannot find CA certificates
+-+    if (ret) {
+-+        mbedtls_ctr_drbg_free(ctr_drbg);
+-+        git__free(ctr_drbg);
+-+        mbedtls_ssl_config_free(git__ssl_conf);
+-+        git__free(git__ssl_conf);
+-+        git__ssl_conf = NULL;
+-+        return -1;
+-+    } else {
+-+        // set root certificates
+-+        mbedtls_x509_crt *cacert = git__malloc(sizeof(mbedtls_x509_crt));
+-+        mbedtls_x509_crt_init(cacert);
+-+        if (isdir)
+-+            ret = mbedtls_x509_crt_parse_path(cacert, crtpath);
+-+        else
+-+            ret = mbedtls_x509_crt_parse_file(cacert, crtpath);
+-+
+-+        if (ret) {
+-+            giterr_set(GITERR_SSL, "failed to load CA certificates: %d", ret);
+-+            mbedtls_x509_crt_free(cacert);
+-+            git__free(cacert);
+-+            mbedtls_ctr_drbg_free(ctr_drbg);
+-+            git__free(ctr_drbg);
+-+            mbedtls_ssl_config_free(git__ssl_conf);
+-+            git__free(git__ssl_conf);
+-+            git__ssl_conf = NULL;
+-+            return -1;
+-+        } else {
+-+            mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
+-+        }
+-+    }
+-+
+-+    // set the list of allowed ciphersuites
+-+    // if (!ciphers) {
+-+    //     cipherids = mbedtls_ssl_list_ciphersuites();
+-+    // }
+-+    // mbedtls_ssl_conf_ciphersuites(git__ssl_conf, cipherids);
+-+
+-+    git__on_shutdown(shutdown_ssl);
+++	int found = -1, loaded = 0;
+++	char *crtpath;
+++	struct stat statbuf;
+++	mbedtls_ctr_drbg_context *ctr_drbg = NULL;
+ +
+-+    return 0;
+++	int *ciphers_list = NULL;
+++	int ciphers_known = 0;
+++	char *cipher_name = NULL;
+++	char *cipher_string = NULL;
+++	char *cipher_string_tmp = NULL;
+++
+++	mbedtls_x509_crt *cacert = NULL;
+++
+++	git__ssl_conf = git__malloc(sizeof(mbedtls_ssl_config));
+++	mbedtls_ssl_config_init(git__ssl_conf);
+++	if (mbedtls_ssl_config_defaults(git__ssl_conf,
+++									MBEDTLS_SSL_IS_CLIENT,
+++									MBEDTLS_SSL_TRANSPORT_STREAM,
+++									MBEDTLS_SSL_PRESET_DEFAULT) != 0) {
+++		giterr_set(GITERR_SSL, "failed to initialize mbedTLS");
+++		goto cleanup;
+++	}
+++
+++	// configure TLSv1
+++	mbedtls_ssl_conf_min_version(git__ssl_conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0);
+++	// verify_server_cert is responsible for making the check.
+++	// OPTIONAL because REQUIRED drops the certificate as soon as the check
+++	// is made, so we can never see the certificate and override it.
+++	mbedtls_ssl_conf_authmode(git__ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
+++
+++	// set the list of allowed ciphersuites
+++	ciphers_list = calloc(GIT_SSL_DEFAULT_CIPHERS_COUNT, sizeof(int));
+++	ciphers_known = 0;
+++	cipher_string = cipher_string_tmp = git__strdup(GIT_SSL_DEFAULT_CIPHERS);
+++	while ((cipher_name = git__strtok(&cipher_string_tmp, ":")) != NULL) {
+++		int cipherid = mbedtls_ssl_get_ciphersuite_id(cipher_name);
+++		if (cipherid == 0) continue;
+++
+++		ciphers_list[ciphers_known++] = cipherid;
+++	}
+++	git__free(cipher_string);
+++
+++	if (!ciphers_known) {
+++		giterr_set(GITERR_SSL, "no cipher could be enabled");
+++		goto cleanup;
+++	}
+++	mbedtls_ssl_conf_ciphersuites(git__ssl_conf, ciphers_list);
+++
+++	// Seeding the random number generator
+++	mbedtls_entropy = git__malloc(sizeof(mbedtls_entropy_context));
+++	mbedtls_entropy_init(mbedtls_entropy);
+++
+++	ctr_drbg = git__malloc(sizeof(mbedtls_ctr_drbg_context));
+++	mbedtls_ctr_drbg_init(ctr_drbg);
+++	if (mbedtls_ctr_drbg_seed(ctr_drbg,
+++							  mbedtls_entropy_func,
+++							  mbedtls_entropy, NULL, 0) != 0) {
+++		giterr_set(GITERR_SSL, "failed to initialize mbedTLS entropy pool");
+++		goto cleanup;
+++	}
+++
+++	mbedtls_ssl_conf_rng(git__ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);
+++
+++	// find locations for which CA certificates
+++	{
+++		crtpath = getenv(X509_CERT_FILE_EVP);
+++		found = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode);
+++		if (found)
+++			loaded = (git_mbedtls_set_cert_file(crtpath, 0) == 0);
+++	}
+++	if (!loaded) {
+++		crtpath = getenv(X509_CERT_DIR_EVP);
+++		found = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode);
+++		if (found)
+++			loaded = (git_mbedtls_set_cert_file(crtpath, 1) == 0);
+++	}
+++	if (!loaded) {
+++		crtpath = X509_CERT_FILE;
+++		found = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode);
+++		if (found)
+++			loaded = (git_mbedtls_set_cert_file(crtpath, 0) == 0);
+++	}
+++	if (!loaded) {
+++		crtpath = X509_CERT_DIR;
+++		found = crtpath != NULL && stat(crtpath, &statbuf) == 0 && S_ISDIR(statbuf.st_mode);
+++		if (found)
+++			loaded = (git_mbedtls_set_cert_file(crtpath, 1) == 0);
+++	}
+++
+++	git__on_shutdown(shutdown_ssl);
+++
+++	return 0;
+++
+++cleanup:
+++	mbedtls_x509_crt_free(cacert);
+++	git__free(cacert);
+++	mbedtls_ctr_drbg_free(ctr_drbg);
+++	git__free(ctr_drbg);
+++	mbedtls_ssl_config_free(git__ssl_conf);
+++	git__free(git__ssl_conf);
+++	git__ssl_conf = NULL;
+++
+++	return -1;
+ +}
+ +
+++mbedtls_ssl_config *git__ssl_conf;
+++
+ +static int bio_read(void *b, unsigned char *buf, size_t len)
+ +{
+-+    git_stream *io = (git_stream *) b;
+-+    return (int) git_stream_read(io, buf, len);
+++	git_stream *io = (git_stream *) b;
+++	return (int) git_stream_read(io, buf, len);
+ +}
+ +
+ +static int bio_write(void *b, const unsigned char *buf, size_t len)
+ +{
+-+    git_stream *io = (git_stream *) b;
+-+    return (int) git_stream_write(io, (const char *)buf, len, 0);
+++	git_stream *io = (git_stream *) b;
+++	return (int) git_stream_write(io, (const char *)buf, len, 0);
+ +}
+ +
+ +static int ssl_set_error(mbedtls_ssl_context *ssl, int error)
+ +{
+-+    char errbuf[512];
+-+    int ret = -1;
+++	char errbuf[512];
+++	int ret = -1;
+++
+++	assert(error != MBEDTLS_ERR_SSL_WANT_READ);
+++	assert(error != MBEDTLS_ERR_SSL_WANT_WRITE);
+++
+++	if (error != 0)
+++		mbedtls_strerror( error, errbuf, 512 );
+ +
+-+    assert(error != MBEDTLS_ERR_SSL_WANT_READ);
+-+    assert(error != MBEDTLS_ERR_SSL_WANT_WRITE);
+++	switch(error){
+++		case 0:
+++		giterr_set(GITERR_SSL, "SSL error: unknown error");
+++		break;
+ +
+-+    if (error != 0)
+-+        mbedtls_strerror( error, errbuf, 512 );
+++	case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
+++		giterr_set(GITERR_SSL, "SSL error: %x[%x] - %s", error, ssl->session_negotiate->verify_result, errbuf);
+++		ret = GIT_ECERTIFICATE;
+++		break;
+ +
+-+    switch(error){
+-+    case 0:
+-+        giterr_set(GITERR_SSL, "SSL error: unknown error");
+-+        break;
+-+    case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
+-+        giterr_set(GITERR_SSL, "SSL error: %x[%x] - %s", error, ssl->session_negotiate->verify_result, errbuf);
+-+        ret = GIT_ECERTIFICATE;
+-+        break;
+-+    default:
+-+        giterr_set(GITERR_SSL, "SSL error: %x - %s", error, errbuf);
+-+    }
+++	default:
+++		giterr_set(GITERR_SSL, "SSL error: %x - %s", error, errbuf);
+++	}
+ +
+-+    return ret;
+++	return ret;
+ +}
+ +
+ +static int ssl_teardown(mbedtls_ssl_context *ssl)
+ +{
+-+    int ret = 0;
+++	int ret = 0;
+ +
+-+    ret = mbedtls_ssl_close_notify(ssl);
+-+    if (ret < 0)
+-+        ret = ssl_set_error(ssl, ret);
+++	ret = mbedtls_ssl_close_notify(ssl);
+++	if (ret < 0)
+++		ret = ssl_set_error(ssl, ret);
+ +
+-+    mbedtls_ssl_free(ssl);
+-+    return ret;
+++	mbedtls_ssl_free(ssl);
+++	return ret;
+ +}
+ +
+ +static int check_host_name(const char *name, const char *host)
+ +{
+-+    if (!strcasecmp(name, host))
+-+        return 0;
+++	if (!strcasecmp(name, host))
+++		return 0;
+ +
+-+    if (gitno__match_host(name, host) < 0)
+-+        return -1;
+++	if (gitno__match_host(name, host) < 0)
+++		return -1;
+ +
+-+    return 0;
+++	return 0;
+ +}
+ +
+ +static int verify_server_cert(mbedtls_ssl_context *ssl, const char *host)
+ +{
+-+    const mbedtls_x509_crt *cert;
+-+    const mbedtls_x509_sequence *alts;
+-+    int ret, matched = -1;
+-+    size_t sn_size = 512;
+-+    char subject_name[sn_size], alt_name[sn_size];
+-+
+-+
+-+    if (( ret = mbedtls_ssl_get_verify_result(ssl) ) != 0) {
+-+        char vrfy_buf[512];
+-+        mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", ret );
+-+        giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
+-+        return GIT_ECERTIFICATE;
+-+    }
+-+
+-+    cert = mbedtls_ssl_get_peer_cert(ssl);
+-+    if (!cert) {
+-+        giterr_set(GITERR_SSL, "the server did not provide a certificate");
+-+        return -1;
+-+    }
+-+
+-+    /* Check the alternative names */
+-+    alts = &cert->subject_alt_names;
+-+    while (alts != NULL && matched != 1) {
+-+        // Buffer is too small
+-+        if( alts->buf.len >= sn_size )
+-+            goto on_error;
+-+
+-+        memcpy(alt_name, alts->buf.p, alts->buf.len);
+-+        alt_name[alts->buf.len] = '\0';
+-+
+-+        if (!memchr(alt_name, '\0', alts->buf.len)) {
+-+            if (check_host_name(alt_name, host) < 0)
+-+                matched = 0;
+-+            else
+-+                matched = 1;
+-+        }
+-+
+-+        alts = alts->next;
+-+    }
+-+    if (matched == 0)
+-+        goto cert_fail_name;
+-+
+-+    if (matched == 1)
+-+        return 0;
+-+
+-+    /* If no alternative names are available, check the common name */
+-+    ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject);
+-+    if (ret == 0)
+-+        goto on_error;
+-+    if (memchr(subject_name, '\0', ret))
+-+        goto cert_fail_name;
+-+
+-+    if (check_host_name(subject_name, host) < 0)
+-+        goto cert_fail_name;
+++	const mbedtls_x509_crt *cert;
+++	const mbedtls_x509_sequence *alts;
+++	int ret, matched = -1;
+++	size_t sn_size = 512;
+++	char subject_name[sn_size], alt_name[sn_size];
+ +
+-+    return 0;
+++
+++	if ((ret = mbedtls_ssl_get_verify_result(ssl)) != 0) {
+++		char vrfy_buf[512];
+++		mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", ret );
+++		giterr_set(GITERR_SSL, "The SSL certificate is invalid: %s", vrfy_buf);
+++		return GIT_ECERTIFICATE;
+++	}
+++
+++	cert = mbedtls_ssl_get_peer_cert(ssl);
+++	if (!cert) {
+++		giterr_set(GITERR_SSL, "the server did not provide a certificate");
+++		return -1;
+++	}
+++
+++	/* Check the alternative names */
+++	alts = &cert->subject_alt_names;
+++	while (alts != NULL && matched != 1) {
+++		// Buffer is too small
+++		if( alts->buf.len >= sn_size )
+++			goto on_error;
+++
+++		memcpy(alt_name, alts->buf.p, alts->buf.len);
+++		alt_name[alts->buf.len] = '\0';
+++
+++		if (!memchr(alt_name, '\0', alts->buf.len)) {
+++			if (check_host_name(alt_name, host) < 0)
+++				matched = 0;
+++			else
+++				matched = 1;
+++		}
+++
+++		alts = alts->next;
+++	}
+++	if (matched == 0)
+++		goto cert_fail_name;
+++
+++	if (matched == 1)
+++		return 0;
+++
+++	/* If no alternative names are available, check the common name */
+++	ret = mbedtls_x509_dn_gets(subject_name, sn_size, &cert->subject);
+++	if (ret == 0)
+++		goto on_error;
+++	if (memchr(subject_name, '\0', ret))
+++		goto cert_fail_name;
+++
+++	if (check_host_name(subject_name, host) < 0)
+++		goto cert_fail_name;
+++
+++	return 0;
+ +
+ +on_error:
+-+    return ssl_set_error(ssl, 0);
+++	return ssl_set_error(ssl, 0);
+ +
+ +cert_fail_name:
+-+    giterr_set(GITERR_SSL, "hostname does not match certificate");
+-+    return GIT_ECERTIFICATE;
+++	giterr_set(GITERR_SSL, "hostname does not match certificate");
+++	return GIT_ECERTIFICATE;
+ +}
+ +
+ +typedef struct {
+-+    git_stream parent;
+-+    git_stream *io;
+-+    bool connected;
+-+    char *host;
+-+    mbedtls_ssl_context *ssl;
+-+    git_cert_x509 cert_info;
+++	git_stream parent;
+++	git_stream *io;
+++	bool connected;
+++	char *host;
+++	mbedtls_ssl_context *ssl;
+++	git_cert_x509 cert_info;
+ +} mbedtls_stream;
+ +
+ +
+ +int mbedtls_connect(git_stream *stream)
+ +{
+-+    int ret;
+-+    mbedtls_stream *st = (mbedtls_stream *) stream;
+++	int ret;
+++	mbedtls_stream *st = (mbedtls_stream *) stream;
+ +
+-+    if ((ret = git_stream_connect(st->io)) < 0)
+-+        return ret;
+++	if ((ret = git_stream_connect(st->io)) < 0)
+++		return ret;
+ +
+-+    st->connected = true;
+++	st->connected = true;
+ +
+-+    mbedtls_ssl_set_hostname(st->ssl, st->host);
+++	mbedtls_ssl_set_hostname(st->ssl, st->host);
+ +
+-+    mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);
+++	mbedtls_ssl_set_bio(st->ssl, st->io, bio_write, bio_read, NULL);
+ +
+-+    if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0)
+-+        return ssl_set_error(st->ssl, ret);
+++	if ((ret = mbedtls_ssl_handshake(st->ssl)) != 0)
+++		return ssl_set_error(st->ssl, ret);
+ +
+-+    return verify_server_cert(st->ssl, st->host);
+++	return verify_server_cert(st->ssl, st->host);
+ +}
+ +
+ +int mbedtls_certificate(git_cert **out, git_stream *stream)
+ +{
+-+    unsigned char *encoded_cert;
+-+    mbedtls_stream *st = (mbedtls_stream *) stream;
+++	unsigned char *encoded_cert;
+++	mbedtls_stream *st = (mbedtls_stream *) stream;
+ +
+-+    const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(st->ssl);
+-+    if (!cert) {
+-+        giterr_set(GITERR_SSL, "the server did not provide a certificate");
+-+        return -1;
+-+    }
+++	const mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(st->ssl);
+++	if (!cert) {
+++		giterr_set(GITERR_SSL, "the server did not provide a certificate");
+++		return -1;
+++	}
+ +
+-+    /* Retrieve the length of the certificate first */
+-+    if (cert->raw.len == 0) {
+-+        giterr_set(GITERR_NET, "failed to retrieve certificate information");
+-+        return -1;
+-+    }
+++	/* Retrieve the length of the certificate first */
+++	if (cert->raw.len == 0) {
+++		giterr_set(GITERR_NET, "failed to retrieve certificate information");
+++		return -1;
+++	}
+ +
+-+    encoded_cert = git__malloc(cert->raw.len);
+-+    GITERR_CHECK_ALLOC(encoded_cert);
+-+    memcpy(encoded_cert, cert->raw.p, cert->raw.len);
+++	encoded_cert = git__malloc(cert->raw.len);
+++	GITERR_CHECK_ALLOC(encoded_cert);
+++	memcpy(encoded_cert, cert->raw.p, cert->raw.len);
+ +
+-+    st->cert_info.parent.cert_type = GIT_CERT_X509;
+-+    st->cert_info.data = encoded_cert;
+-+    st->cert_info.len = cert->raw.len;
+++	st->cert_info.parent.cert_type = GIT_CERT_X509;
+++	st->cert_info.data = encoded_cert;
+++	st->cert_info.len = cert->raw.len;
+ +
+-+    *out = &st->cert_info.parent;
+++	*out = &st->cert_info.parent;
+ +
+-+    return 0;
+++	return 0;
+ +}
+ +
+-+static int mbedtls_set_proxy(git_stream *stream, const char *proxy_url)
+++static int mbedtls_set_proxy(git_stream *stream, const git_proxy_options *proxy_options)
+ +{
+-+    mbedtls_stream *st = (mbedtls_stream *) stream;
+++	mbedtls_stream *st = (mbedtls_stream *) stream;
+ +
+-+    return git_stream_set_proxy(st->io, proxy_url);
+++	return git_stream_set_proxy(st->io, proxy_options);
+ +}
+ +
+ +ssize_t mbedtls_stream_write(git_stream *stream, const char *data, size_t len, int flags)
+ +{
+-+    mbedtls_stream *st = (mbedtls_stream *) stream;
+-+    int ret;
+++	size_t read = 0;
+++	mbedtls_stream *st = (mbedtls_stream *) stream;
+ +
+-+    GIT_UNUSED(flags);
+++	GIT_UNUSED(flags);
+ +
+-+    if ((ret = mbedtls_ssl_write(st->ssl, (const unsigned char *)data, len)) <= 0) {
+-+        return ssl_set_error(st->ssl, ret);
+-+    }
+++	do {
+++		int error = mbedtls_ssl_write(st->ssl, (const unsigned char *)data + read, len - read);
+++		if (error <= 0) {
+++			return ssl_set_error(st->ssl, error);
+++		}
+++		read += error;
+++	} while (read < len);
+ +
+-+    return ret;
+++	return read;
+ +}
+ +
+ +ssize_t mbedtls_stream_read(git_stream *stream, void *data, size_t len)
+ +{
+-+    mbedtls_stream *st = (mbedtls_stream *) stream;
+-+    int ret;
+++	mbedtls_stream *st = (mbedtls_stream *) stream;
+++	int ret;
+ +
+-+    if ((ret = mbedtls_ssl_read(st->ssl, (unsigned char *)data, len)) <= 0)
+-+        ssl_set_error(st->ssl, ret);
+++	if ((ret = mbedtls_ssl_read(st->ssl, (unsigned char *)data, len)) <= 0)
+++		ssl_set_error(st->ssl, ret);
+ +
+-+    return ret;
+++	return ret;
+ +}
+ +
+ +int mbedtls_stream_close(git_stream *stream)
+ +{
+-+    mbedtls_stream *st = (mbedtls_stream *) stream;
+-+    int ret = 0;
+++	mbedtls_stream *st = (mbedtls_stream *) stream;
+++	int ret = 0;
+ +
+-+    if (st->connected && (ret = ssl_teardown(st->ssl)) != 0)
+-+        return -1;
+++	if (st->connected && (ret = ssl_teardown(st->ssl)) != 0)
+++		return -1;
+ +
+-+    st->connected = false;
+++	st->connected = false;
+ +
+-+    return git_stream_close(st->io);
+++	return git_stream_close(st->io);
+ +}
+ +
+ +void mbedtls_stream_free(git_stream *stream)
+ +{
+-+    mbedtls_stream *st = (mbedtls_stream *) stream;
+++	mbedtls_stream *st = (mbedtls_stream *) stream;
+ +
+-+    git__free(st->host);
+-+    git__free(st->cert_info.data);
+-+    git_stream_free(st->io);
+-+    git__free(st->ssl);
+-+    git__free(st);
+++	git__free(st->host);
+++	git__free(st->cert_info.data);
+++	git_stream_free(st->io);
+++	git__free(st->ssl);
+++	git__free(st);
+ +}
+ +
+ +int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
+ +{
+-+    int error;
+-+    mbedtls_stream *st;
+++	int error;
+++	mbedtls_stream *st;
+ +
+-+    st = git__calloc(1, sizeof(mbedtls_stream));
+-+    GITERR_CHECK_ALLOC(st);
+++	st = git__calloc(1, sizeof(mbedtls_stream));
+++	GITERR_CHECK_ALLOC(st);
+ +
+ +#ifdef GIT_CURL
+-+    error = git_curl_stream_new(&st->io, host, port);
+++	error = git_curl_stream_new(&st->io, host, port);
+ +#else
+-+    error = git_socket_stream_new(&st->io, host, port);
+++	error = git_socket_stream_new(&st->io, host, port);
+ +#endif
+ +
+-+    if (error < 0)
+-+        return error;
+-+
+-+    st->ssl = git__malloc(sizeof(mbedtls_ssl_context));
+-+    GITERR_CHECK_ALLOC(st->ssl);
+-+    mbedtls_ssl_init(st->ssl);
+-+    if( (error = mbedtls_ssl_setup(st->ssl, git__ssl_conf)) != 0 ) {
+-+        mbedtls_ssl_free(st->ssl);
+-+        giterr_set(GITERR_SSL, "failed to create ssl object");
+-+        return -1;
+-+    }
+-+
+-+    st->host = git__strdup(host);
+-+    GITERR_CHECK_ALLOC(st->host);
+-+
+-+    st->parent.version = GIT_STREAM_VERSION;
+-+    st->parent.encrypted = 1;
+-+    st->parent.proxy_support = git_stream_supports_proxy(st->io);
+-+    st->parent.connect = mbedtls_connect;
+-+    st->parent.certificate = mbedtls_certificate;
+-+    st->parent.set_proxy = mbedtls_set_proxy;
+-+    st->parent.read = mbedtls_stream_read;
+-+    st->parent.write = mbedtls_stream_write;
+-+    st->parent.close = mbedtls_stream_close;
+-+    st->parent.free = mbedtls_stream_free;
+-+
+-+    *out = (git_stream *) st;
+-+    return 0;
+-+}
+++	if (error < 0)
+++		goto out_err;
+ +
+-+#else
+++	st->ssl = git__malloc(sizeof(mbedtls_ssl_context));
+++	GITERR_CHECK_ALLOC(st->ssl);
+++	mbedtls_ssl_init(st->ssl);
+++	if (mbedtls_ssl_setup(st->ssl, git__ssl_conf)) {
+++		giterr_set(GITERR_SSL, "failed to create ssl object");
+++		error = -1;
+++		goto out_err;
+++	}
+ +
+-+#include "stream.h"
+-+#include "git2/sys/openssl.h"
+++	st->host = git__strdup(host);
+++	GITERR_CHECK_ALLOC(st->host);
+++
+++	st->parent.version = GIT_STREAM_VERSION;
+++	st->parent.encrypted = 1;
+++	st->parent.proxy_support = git_stream_supports_proxy(st->io);
+++	st->parent.connect = mbedtls_connect;
+++	st->parent.certificate = mbedtls_certificate;
+++	st->parent.set_proxy = mbedtls_set_proxy;
+++	st->parent.read = mbedtls_stream_read;
+++	st->parent.write = mbedtls_stream_write;
+++	st->parent.close = mbedtls_stream_close;
+++	st->parent.free = mbedtls_stream_free;
+++
+++	*out = (git_stream *) st;
+++	return 0;
+++
+++out_err:
+++	mbedtls_ssl_free(st->ssl);
+++	git_stream_free(st->io);
+++	git__free(st);
+++
+++	return error;
+++}
+++
+++int git_mbedtls_set_cert_file(const char *path, int is_dir)
+++{
+++	int ret = 0;
+++	char errbuf[512];
+++	mbedtls_x509_crt *cacert;
+++
+++	assert(path != NULL);
+++
+++	cacert = git__malloc(sizeof(mbedtls_x509_crt));
+++	mbedtls_x509_crt_init(cacert);
+++	if (is_dir) {
+++		ret = mbedtls_x509_crt_parse_path(cacert, path);
+++	} else {
+++		ret = mbedtls_x509_crt_parse_file(cacert, path);
+++	}
+++	// mbedtls_x509_crt_parse_path returns the number of invalid certs on success
+++	if (ret <= 0) {
+++		mbedtls_x509_crt_free(cacert);
+++		git__free(cacert);
+++		mbedtls_strerror( ret, errbuf, 512 );
+++		giterr_set(GITERR_SSL, "failed to load CA certificates : %s (%d)", errbuf, ret);
+++		return -1;
+++	}
+++
+++	mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
+++	git__free(git__ssl_conf->ca_chain);
+++	mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
+++
+++	return 0;
+++}
+++
+++#else
+++
+++#include "stream.h"
+ +
+ +int git_mbedtls_stream_global_init(void)
+ +{
+-+    return 0;
+++	return 0;
+++}
+++
+++int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
+++{
+++	GIT_UNUSED(out);
+++	GIT_UNUSED(host);
+++	GIT_UNUSED(port);
+++
+++	giterr_set(GITERR_SSL, "mbedTLS is not supported in this version");
+++	return -1;
+++}
+++
+++int git_mbedtls_set_cert_file(const char *path, int is_dir)
+++{
+++	GIT_UNUSED(is_dir);
+++
+++	giterr_set(GITERR_SSL, "mbedTLS is not supported in this version");
+++	return -1;
+++}
+++
+++#endif
++diff --git a/src/streams/mbedtls.h b/src/streams/mbedtls.h
++new file mode 100644
++index 0000000..7501397
++--- /dev/null
+++++ b/src/streams/mbedtls.h
++@@ -0,0 +1,18 @@
+++/*
+++ * 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.
+++ */
+++#ifndef INCLUDE_mbedtls_stream_h__
+++#define INCLUDE_mbedtls_stream_h__
+++
+++#include "git2/sys/stream.h"
+++
+++extern int git_mbedtls_stream_global_init(void);
+++
+++extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
+++
+++extern int git_mbedtls_set_cert_file(const char *path, int is_dir);
+++
+++#endif
++diff --git a/src/streams/openssl.c b/src/streams/openssl.c
++new file mode 100644
++index 0000000..8668b78
++--- /dev/null
+++++ b/src/streams/openssl.c
++@@ -0,0 +1,675 @@
+++/*
+++ * 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.
+++ */
+++
+++#ifdef GIT_OPENSSL
+++
+++#include <ctype.h>
+++
+++#include "global.h"
+++#include "posix.h"
+++#include "stream.h"
+++#include "streams/socket.h"
+++#include "streams/openssl.h"
+++#include "netops.h"
+++#include "git2/transport.h"
+++#include "git2/sys/openssl.h"
+++
+++#ifdef GIT_CURL
+++# include "streams/curl.h"
+++#endif
+++
+++#ifndef GIT_WIN32
+++# include <sys/types.h>
+++# include <sys/socket.h>
+++# include <netinet/in.h>
+++#endif
+++
+++#include <openssl/ssl.h>
+++#include <openssl/err.h>
+++#include <openssl/x509v3.h>
+++#include <openssl/bio.h>
+++
+++SSL_CTX *git__ssl_ctx;
+++
+++#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
+++
+++#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
+++
+++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[i]);
+++	git__free(openssl_locks);
+++}
+++
+++#endif /* GIT_THREADS && OPENSSL_VERSION_NUMBER < 0x10100000L */
+++
+++static BIO_METHOD *git_stream_bio_method;
+++static int init_bio_method(void);
+++
+++/**
+++ * This function aims to clean-up the SSL context which
+++ * we allocated.
+++ */
+++static void shutdown_ssl(void)
+++{
+++	if (git_stream_bio_method) {
+++		BIO_meth_free(git_stream_bio_method);
+++		git_stream_bio_method = NULL;
+++	}
+++
+++	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;
+++	const char *ciphers = git_libgit2__ssl_ciphers();
+++
+++	/* Older OpenSSL and MacOS OpenSSL doesn't have this */
+++#ifdef SSL_OP_NO_COMPRESSION
+++	ssl_opts |= SSL_OP_NO_COMPRESSION;
+++#endif
+++
+++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+++	SSL_load_error_strings();
+++	OpenSSL_add_ssl_algorithms();
+++#else
+++	OPENSSL_init_ssl(0, NULL);
+++#endif
+++
+++	/*
+++	 * 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;
+++	}
+++
+++	if (!ciphers) {
+++		ciphers = GIT_SSL_DEFAULT_CIPHERS;
+++	}
+++
+++	if(!SSL_CTX_set_cipher_list(git__ssl_ctx, ciphers)) {
+++		SSL_CTX_free(git__ssl_ctx);
+++		git__ssl_ctx = NULL;
+++		return -1;
+++	}
+++
+++	if (init_bio_method() < 0) {
+++		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)
+++{
+++#if defined(GIT_THREADS) && OPENSSL_VERSION_NUMBER < 0x10100000L
+++	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;
+++#elif OPENSSL_VERSION_NUMBER >= 0x10100000L
+++	return 0;
+++#else
+++	giterr_set(GITERR_THREAD, "libgit2 was not built with threads");
+++	return -1;
+++#endif
+++}
+++
+++
+++static int bio_create(BIO *b)
+++{
+++	BIO_set_init(b, 1);
+++	BIO_set_data(b, NULL);
+++
+++	return 1;
+++}
+++
+++static int bio_destroy(BIO *b)
+++{
+++	if (!b)
+++		return 0;
+++
+++	BIO_set_data(b, NULL);
+++
+++	return 1;
+++}
+++
+++static int bio_read(BIO *b, char *buf, int len)
+++{
+++	git_stream *io = (git_stream *) BIO_get_data(b);
+++
+++	return (int) git_stream_read(io, buf, len);
+++}
+++
+++static int bio_write(BIO *b, const char *buf, int len)
+++{
+++	git_stream *io = (git_stream *) BIO_get_data(b);
+++
+++	return (int) git_stream_write(io, buf, len, 0);
+++}
+++
+++static long bio_ctrl(BIO *b, int cmd, long num, void *ptr)
+++{
+++	GIT_UNUSED(b);
+++	GIT_UNUSED(num);
+++	GIT_UNUSED(ptr);
+++
+++	if (cmd == BIO_CTRL_FLUSH)
+++		return 1;
+++
+++	return 0;
+++}
+++
+++static int bio_gets(BIO *b, char *buf, int len)
+++{
+++	GIT_UNUSED(b);
+++	GIT_UNUSED(buf);
+++	GIT_UNUSED(len);
+++	return -1;
+++}
+++
+++static int bio_puts(BIO *b, const char *str)
+++{
+++	return bio_write(b, str, strlen(str));
+++}
+++
+++static int init_bio_method(void)
+++{
+++	/* Set up the BIO_METHOD we use for wrapping our own stream implementations */
+++	git_stream_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "git_stream");
+++	GITERR_CHECK_ALLOC(git_stream_bio_method);
+++
+++	BIO_meth_set_write(git_stream_bio_method, bio_write);
+++	BIO_meth_set_read(git_stream_bio_method, bio_read);
+++	BIO_meth_set_puts(git_stream_bio_method, bio_puts);
+++	BIO_meth_set_gets(git_stream_bio_method, bio_gets);
+++	BIO_meth_set_ctrl(git_stream_bio_method, bio_ctrl);
+++	BIO_meth_set_create(git_stream_bio_method, bio_create);
+++	BIO_meth_set_destroy(git_stream_bio_method, bio_destroy);
+++
+++	return 0;
+++}
+++
+++static int ssl_set_error(SSL *ssl, int error)
+++{
+++	int err;
+++	unsigned long e;
+++
+++	err = SSL_get_error(ssl, error);
+++
+++	assert(err != SSL_ERROR_WANT_READ);
+++	assert(err != SSL_ERROR_WANT_WRITE);
+++
+++	switch (err) {
+++	case SSL_ERROR_WANT_CONNECT:
+++	case SSL_ERROR_WANT_ACCEPT:
+++		giterr_set(GITERR_NET, "SSL error: connection failure");
+++		break;
+++	case SSL_ERROR_WANT_X509_LOOKUP:
+++		giterr_set(GITERR_NET, "SSL error: x509 error");
+++		break;
+++	case SSL_ERROR_SYSCALL:
+++		e = ERR_get_error();
+++		if (e > 0) {
+++			giterr_set(GITERR_NET, "SSL error: %s",
+++					ERR_error_string(e, NULL));
+++			break;
+++		} else if (error < 0) {
+++			giterr_set(GITERR_OS, "SSL error: syscall failure");
+++			break;
+++		}
+++		giterr_set(GITERR_NET, "SSL error: received early EOF");
+++		return GIT_EEOF;
+++		break;
+++	case SSL_ERROR_SSL:
+++		e = ERR_get_error();
+++		giterr_set(GITERR_NET, "SSL error: %s",
+++				ERR_error_string(e, NULL));
+++		break;
+++	case SSL_ERROR_NONE:
+++	case SSL_ERROR_ZERO_RETURN:
+++	default:
+++		giterr_set(GITERR_NET, "SSL error: unknown error");
+++		break;
+++	}
+++	return -1;
+++}
+++
+++static int ssl_teardown(SSL *ssl)
+++{
+++	int ret;
+++
+++	ret = SSL_shutdown(ssl);
+++	if (ret < 0)
+++		ret = ssl_set_error(ssl, ret);
+++	else
+++		ret = 0;
+++
+++	return ret;
+++}
+++
+++static int check_host_name(const char *name, const char *host)
+++{
+++	if (!strcasecmp(name, host))
+++		return 0;
+++
+++	if (gitno__match_host(name, host) < 0)
+++		return -1;
+++
+++	return 0;
+++}
+++
+++static int verify_server_cert(SSL *ssl, const char *host)
+++{
+++	X509 *cert;
+++	X509_NAME *peer_name;
+++	ASN1_STRING *str;
+++	unsigned char *peer_cn = NULL;
+++	int matched = -1, type = GEN_DNS;
+++	GENERAL_NAMES *alts;
+++	struct in6_addr addr6;
+++	struct in_addr addr4;
+++	void *addr;
+++	int i = -1,j;
+++
+++	if (SSL_get_verify_result(ssl) != X509_V_OK) {
+++		giterr_set(GITERR_SSL, "the SSL certificate is invalid");
+++		return GIT_ECERTIFICATE;
+++	}
+++
+++	/* Try to parse the host as an IP address to see if it is */
+++	if (p_inet_pton(AF_INET, host, &addr4)) {
+++		type = GEN_IPADD;
+++		addr = &addr4;
+++	} else {
+++		if(p_inet_pton(AF_INET6, host, &addr6)) {
+++			type = GEN_IPADD;
+++			addr = &addr6;
+++		}
+++	}
+++
+++
+++	cert = SSL_get_peer_certificate(ssl);
+++	if (!cert) {
+++		giterr_set(GITERR_SSL, "the server did not provide a certificate");
+++		return -1;
+++	}
+++
+++	/* Check the alternative names */
+++	alts = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
+++	if (alts) {
+++		int num;
+++
+++		num = sk_GENERAL_NAME_num(alts);
+++		for (i = 0; i < num && matched != 1; i++) {
+++			const GENERAL_NAME *gn = sk_GENERAL_NAME_value(alts, i);
+++			const char *name = (char *) ASN1_STRING_get0_data(gn->d.ia5);
+++			size_t namelen = (size_t) ASN1_STRING_length(gn->d.ia5);
+++
+++			/* Skip any names of a type we're not looking for */
+++			if (gn->type != type)
+++				continue;
+++
+++			if (type == GEN_DNS) {
+++				/* If it contains embedded NULs, don't even try */
+++				if (memchr(name, '\0', namelen))
+++					continue;
+++
+++				if (check_host_name(name, host) < 0)
+++					matched = 0;
+++				else
+++					matched = 1;
+++			} else if (type == GEN_IPADD) {
+++				/* Here name isn't so much a name but a binary representation of the IP */
+++				matched = !!memcmp(name, addr, namelen);
+++			}
+++		}
+++	}
+++	GENERAL_NAMES_free(alts);
+++
+++	if (matched == 0)
+++		goto cert_fail_name;
+++
+++	if (matched == 1)
+++		return 0;
+++
+++	/* If no alternative names are available, check the common name */
+++	peer_name = X509_get_subject_name(cert);
+++	if (peer_name == NULL)
+++		goto on_error;
+++
+++	if (peer_name) {
+++		/* Get the index of the last CN entry */
+++		while ((j = X509_NAME_get_index_by_NID(peer_name, NID_commonName, i)) >= 0)
+++			i = j;
+++	}
+++
+++	if (i < 0)
+++		goto on_error;
+++
+++	str = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(peer_name, i));
+++	if (str == NULL)
+++		goto on_error;
+++
+++	/* Work around a bug in OpenSSL whereby ASN1_STRING_to_UTF8 fails if it's already in utf-8 */
+++	if (ASN1_STRING_type(str) == V_ASN1_UTF8STRING) {
+++		int size = ASN1_STRING_length(str);
+++
+++		if (size > 0) {
+++			peer_cn = OPENSSL_malloc(size + 1);
+++			GITERR_CHECK_ALLOC(peer_cn);
+++			memcpy(peer_cn, ASN1_STRING_get0_data(str), size);
+++			peer_cn[size] = '\0';
+++		} else {
+++			goto cert_fail_name;
+++		}
+++	} else {
+++		int size = ASN1_STRING_to_UTF8(&peer_cn, str);
+++		GITERR_CHECK_ALLOC(peer_cn);
+++		if (memchr(peer_cn, '\0', size))
+++			goto cert_fail_name;
+++	}
+++
+++	if (check_host_name((char *)peer_cn, host) < 0)
+++		goto cert_fail_name;
+++
+++	OPENSSL_free(peer_cn);
+++
+++	return 0;
+++
+++on_error:
+++	OPENSSL_free(peer_cn);
+++	return ssl_set_error(ssl, 0);
+++
+++cert_fail_name:
+++	OPENSSL_free(peer_cn);
+++	giterr_set(GITERR_SSL, "hostname does not match certificate");
+++	return GIT_ECERTIFICATE;
+++}
+++
+++typedef struct {
+++	git_stream parent;
+++	git_stream *io;
+++	bool connected;
+++	char *host;
+++	SSL *ssl;
+++	git_cert_x509 cert_info;
+++} openssl_stream;
+++
+++int openssl_close(git_stream *stream);
+++
+++int openssl_connect(git_stream *stream)
+++{
+++	int ret;
+++	BIO *bio;
+++	openssl_stream *st = (openssl_stream *) stream;
+++
+++	if ((ret = git_stream_connect(st->io)) < 0)
+++		return ret;
+++
+++	st->connected = true;
+++
+++	bio = BIO_new(git_stream_bio_method);
+++	GITERR_CHECK_ALLOC(bio);
+++
+++	BIO_set_data(bio, st->io);
+++	SSL_set_bio(st->ssl, bio, bio);
+++
+++	/* specify the host in case SNI is needed */
+++#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+++	SSL_set_tlsext_host_name(st->ssl, st->host);
+++#endif
+++
+++	if ((ret = SSL_connect(st->ssl)) <= 0)
+++		return ssl_set_error(st->ssl, ret);
+++
+++	return verify_server_cert(st->ssl, st->host);
+++}
+++
+++int openssl_certificate(git_cert **out, git_stream *stream)
+++{
+++	openssl_stream *st = (openssl_stream *) stream;
+++	int len;
+++	X509 *cert = SSL_get_peer_certificate(st->ssl);
+++	unsigned char *guard, *encoded_cert;
+++
+++	/* Retrieve the length of the certificate first */
+++	len = i2d_X509(cert, NULL);
+++	if (len < 0) {
+++		giterr_set(GITERR_NET, "failed to retrieve certificate information");
+++		return -1;
+++	}
+++
+++	encoded_cert = git__malloc(len);
+++	GITERR_CHECK_ALLOC(encoded_cert);
+++	/* i2d_X509 makes 'guard' point to just after the data */
+++	guard = encoded_cert;
+++
+++	len = i2d_X509(cert, &guard);
+++	if (len < 0) {
+++		git__free(encoded_cert);
+++		giterr_set(GITERR_NET, "failed to retrieve certificate information");
+++		return -1;
+++	}
+++
+++	st->cert_info.parent.cert_type = GIT_CERT_X509;
+++	st->cert_info.data = encoded_cert;
+++	st->cert_info.len = len;
+++
+++	*out = &st->cert_info.parent;
+++
+++	return 0;
+++}
+++
+++static int openssl_set_proxy(git_stream *stream, const git_proxy_options *proxy_opts)
+++{
+++	openssl_stream *st = (openssl_stream *) stream;
+++
+++	return git_stream_set_proxy(st->io, proxy_opts);
+++}
+++
+++ssize_t openssl_write(git_stream *stream, const char *data, size_t len, int flags)
+++{
+++	openssl_stream *st = (openssl_stream *) stream;
+++	int ret;
+++
+++	GIT_UNUSED(flags);
+++
+++	if ((ret = SSL_write(st->ssl, data, len)) <= 0) {
+++		return ssl_set_error(st->ssl, ret);
+++	}
+++
+++	return ret;
+++}
+++
+++ssize_t openssl_read(git_stream *stream, void *data, size_t len)
+++{
+++	openssl_stream *st = (openssl_stream *) stream;
+++	int ret;
+++
+++	if ((ret = SSL_read(st->ssl, data, len)) <= 0)
+++		return ssl_set_error(st->ssl, ret);
+++
+++	return ret;
+++}
+++
+++int openssl_close(git_stream *stream)
+++{
+++	openssl_stream *st = (openssl_stream *) stream;
+++	int ret;
+++
+++	if (st->connected && (ret = ssl_teardown(st->ssl)) < 0)
+++		return -1;
+++
+++	st->connected = false;
+++
+++	return git_stream_close(st->io);
+++}
+++
+++void openssl_free(git_stream *stream)
+++{
+++	openssl_stream *st = (openssl_stream *) stream;
+++
+++	SSL_free(st->ssl);
+++	git__free(st->host);
+++	git__free(st->cert_info.data);
+++	git_stream_free(st->io);
+++	git__free(st);
+++}
+++
+++int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
+++{
+++	int error;
+++	openssl_stream *st;
+++
+++	st = git__calloc(1, sizeof(openssl_stream));
+++	GITERR_CHECK_ALLOC(st);
+++
+++	st->io = NULL;
+++#ifdef GIT_CURL
+++	error = git_curl_stream_new(&st->io, host, port);
+++#else
+++	error = git_socket_stream_new(&st->io, host, port);
+++#endif
+++
+++	if (error < 0)
+++		goto out_err;
+++
+++	st->ssl = SSL_new(git__ssl_ctx);
+++	if (st->ssl == NULL) {
+++		giterr_set(GITERR_SSL, "failed to create ssl object");
+++		error = -1;
+++		goto out_err;
+++	}
+++
+++	st->host = git__strdup(host);
+++	GITERR_CHECK_ALLOC(st->host);
+++
+++	st->parent.version = GIT_STREAM_VERSION;
+++	st->parent.encrypted = 1;
+++	st->parent.proxy_support = git_stream_supports_proxy(st->io);
+++	st->parent.connect = openssl_connect;
+++	st->parent.certificate = openssl_certificate;
+++	st->parent.set_proxy = openssl_set_proxy;
+++	st->parent.read = openssl_read;
+++	st->parent.write = openssl_write;
+++	st->parent.close = openssl_close;
+++	st->parent.free = openssl_free;
+++
+++	*out = (git_stream *) st;
+++	return 0;
+++
+++out_err:
+++	git_stream_free(st->io);
+++	git__free(st);
+++
+++	return error;
+++}
+++
+++int git_openssl_set_cert_file(const char *file, const char *path)
+++{
+++	if (SSL_CTX_load_verify_locations(git__ssl_ctx, file, path) == 0) {
+++		giterr_set(GITERR_SSL, "SSL error: %s",
+++				   ERR_error_string(ERR_get_error(), NULL));
+++		return -1;
+++	}
+++	return 0;
+++}
+++
+++#else
+++
+++#include "stream.h"
+++#include "git2/sys/openssl.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);
+++	GIT_UNUSED(host);
+++	GIT_UNUSED(port);
+++
+++	giterr_set(GITERR_SSL, "openssl is not supported in this version");
+++	return -1;
+++}
+++
+++int git_openssl_set_ca_location(const char *file, const char *path)
+++{
+++	GIT_UNUSED(file);
+++	GIT_UNUSED(path);
+++
+++	giterr_set(GITERR_SSL, "openssl is not supported in this version");
+++	return -1;
+++}
+++
+++#endif
++diff --git a/src/streams/openssl.h b/src/streams/openssl.h
++new file mode 100644
++index 0000000..8c7a84d
++--- /dev/null
+++++ b/src/streams/openssl.h
++@@ -0,0 +1,124 @@
+++/*
+++ * 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.
+++ */
+++#ifndef INCLUDE_openssl_stream_h__
+++#define INCLUDE_openssl_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_set_cert_file(const char *file, const char *path);
+++
+++/*
+++ * 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
+++ * we can program against the interface instead of littering the implementation
+++ * with ifdefs.
+++ */
+++#ifdef GIT_OPENSSL
+++# include <openssl/ssl.h>
+++# include <openssl/err.h>
+++# include <openssl/x509v3.h>
+++# include <openssl/bio.h>
+++
+++
+++
+++# if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+++
+++GIT_INLINE(BIO_METHOD*) BIO_meth_new(int type, const char *name)
+++{
+++	BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
+++	if (!meth) {
+++		return NULL;
+++	}
+++
+++	meth->type = type;
+++	meth->name = name;
+++
+++	return meth;
+++}
+++
+++GIT_INLINE(void) BIO_meth_free(BIO_METHOD *biom)
+++{
+++	git__free(biom);
+++}
+++
+++GIT_INLINE(int) BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
+++{
+++	biom->bwrite = write;
+++	return 1;
+++}
+++
+++GIT_INLINE(int) BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
+++{
+++	biom->bread = read;
+++	return 1;
+++}
+++
+++GIT_INLINE(int) BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
+++{
+++	biom->bputs = puts;
+++	return 1;
+++}
+++
+++GIT_INLINE(int) BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
+++
+++{
+++	biom->bgets = gets;
+++	return 1;
+ +}
+ +
+-+int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port)
+++GIT_INLINE(int) BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
+++{
+++	biom->ctrl = ctrl;
+++	return 1;
+++}
+++
+++GIT_INLINE(int) BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
+++{
+++	biom->create = create;
+++	return 1;
+++}
+++
+++GIT_INLINE(int) BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
+++{
+++	biom->destroy = destroy;
+++	return 1;
+++}
+++
+++GIT_INLINE(int) BIO_get_new_index(void)
+++{
+++	/* This exists as of 1.1 so before we'd just have 0 */
+++	return 0;
+++}
+++
+++GIT_INLINE(void) BIO_set_init(BIO *b, int init)
+++{
+++	b->init = init;
+++}
+++
+++GIT_INLINE(void) BIO_set_data(BIO *a, void *ptr)
+++{
+++	a->ptr = ptr;
+++}
+++
+++GIT_INLINE(void*) BIO_get_data(BIO *a)
+++{
+++	return a->ptr;
+++}
+++
+++GIT_INLINE(const unsigned char *) ASN1_STRING_get0_data(const ASN1_STRING *x)
+++{
+++	return ASN1_STRING_data((ASN1_STRING *)x);
+++}
+++
+++# endif // OpenSSL < 1.1
+++#endif // GIT_OPENSSL
+++
+++#endif
++diff --git a/src/streams/socket.c b/src/streams/socket.c
++new file mode 100644
++index 0000000..1150b40
++--- /dev/null
+++++ b/src/streams/socket.c
++@@ -0,0 +1,210 @@
+++/*
+++ * 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 "common.h"
+++#include "posix.h"
+++#include "netops.h"
+++#include "stream.h"
+++#include "streams/socket.h"
+++
+++#ifndef _WIN32
+++#	include <sys/types.h>
+++#	include <sys/socket.h>
+++#	include <sys/select.h>
+++#	include <sys/time.h>
+++#	include <netdb.h>
+++#	include <netinet/in.h>
+++#       include <arpa/inet.h>
+++#else
+++#	include <winsock2.h>
+++#	include <ws2tcpip.h>
+++#	ifdef _MSC_VER
+++#		pragma comment(lib, "ws2_32")
+++#	endif
+++#endif
+++
+++#ifdef GIT_WIN32
+++static void net_set_error(const char *str)
+++{
+++	int error = WSAGetLastError();
+++	char * win32_error = git_win32_get_error_message(error);
+++
+++	if (win32_error) {
+++		giterr_set(GITERR_NET, "%s: %s", str, win32_error);
+++		git__free(win32_error);
+++	} else {
+++		giterr_set(GITERR_NET, str);
+++	}
+++}
+++#else
+++static void net_set_error(const char *str)
+ +{
+-+    GIT_UNUSED(out);
+-+    GIT_UNUSED(host);
+-+    GIT_UNUSED(port);
+++	giterr_set(GITERR_NET, "%s: %s", str, strerror(errno));
+++}
+++#endif
+++
+++static int close_socket(GIT_SOCKET s)
+++{
+++	if (s == INVALID_SOCKET)
+++		return 0;
+++
+++#ifdef GIT_WIN32
+++	if (SOCKET_ERROR == closesocket(s))
+++		return -1;
+++
+++	if (0 != WSACleanup()) {
+++		giterr_set(GITERR_OS, "winsock cleanup failed");
+++		return -1;
+++	}
+++
+++	return 0;
+++#else
+++	return close(s);
+++#endif
+ +
+-+    giterr_set(GITERR_SSL, "mbedTLS is not supported in this version");
+-+    return -1;
+ +}
+ +
+++int socket_connect(git_stream *stream)
+++{
+++	struct addrinfo *info = NULL, *p;
+++	struct addrinfo hints;
+++	git_socket_stream *st = (git_socket_stream *) stream;
+++	GIT_SOCKET s = INVALID_SOCKET;
+++	int ret;
+++
+++#ifdef GIT_WIN32
+++	/* on win32, the WSA context needs to be initialized
+++	 * before any socket calls can be performed */
+++	WSADATA wsd;
+++
+++	if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
+++		giterr_set(GITERR_OS, "winsock init failed");
+++		return -1;
+++	}
+++
+++	if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2) {
+++		WSACleanup();
+++		giterr_set(GITERR_OS, "winsock init failed");
+++		return -1;
+++	}
+ +#endif
+ +
+-diff --git a/src/mbedtls_stream.h b/src/mbedtls_stream.h
+++	memset(&hints, 0x0, sizeof(struct addrinfo));
+++	hints.ai_socktype = SOCK_STREAM;
+++	hints.ai_family = AF_UNSPEC;
+++
+++	if ((ret = p_getaddrinfo(st->host, st->port, &hints, &info)) != 0) {
+++		giterr_set(GITERR_NET,
+++			   "failed to resolve address for %s: %s", st->host, p_gai_strerror(ret));
+++		return -1;
+++	}
+++
+++	for (p = info; p != NULL; p = p->ai_next) {
+++		s = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+++
+++		if (s == INVALID_SOCKET)
+++			continue;
+++
+++		if (connect(s, p->ai_addr, (socklen_t)p->ai_addrlen) == 0)
+++			break;
+++
+++		/* If we can't connect, try the next one */
+++		close_socket(s);
+++		s = INVALID_SOCKET;
+++	}
+++
+++	/* Oops, we couldn't connect to any address */
+++	if (s == INVALID_SOCKET && p == NULL) {
+++		giterr_set(GITERR_OS, "failed to connect to %s", st->host);
+++		p_freeaddrinfo(info);
+++		return -1;
+++	}
+++
+++	st->s = s;
+++	p_freeaddrinfo(info);
+++	return 0;
+++}
+++
+++ssize_t socket_write(git_stream *stream, const char *data, size_t len, int flags)
+++{
+++	ssize_t ret;
+++	size_t off = 0;
+++	git_socket_stream *st = (git_socket_stream *) stream;
+++
+++	while (off < len) {
+++		errno = 0;
+++		ret = p_send(st->s, data + off, len - off, flags);
+++		if (ret < 0) {
+++			net_set_error("Error sending data");
+++			return -1;
+++		}
+++
+++		off += ret;
+++	}
+++
+++	return off;
+++}
+++
+++ssize_t socket_read(git_stream *stream, void *data, size_t len)
+++{
+++	ssize_t ret;
+++	git_socket_stream *st = (git_socket_stream *) stream;
+++
+++	if ((ret = p_recv(st->s, data, len, 0)) < 0)
+++		net_set_error("Error receiving socket data");
+++
+++	return ret;
+++}
+++
+++int socket_close(git_stream *stream)
+++{
+++	git_socket_stream *st = (git_socket_stream *) stream;
+++	int error;
+++
+++	error = close_socket(st->s);
+++	st->s = INVALID_SOCKET;
+++
+++	return error;
+++}
+++
+++void socket_free(git_stream *stream)
+++{
+++	git_socket_stream *st = (git_socket_stream *) stream;
+++
+++	git__free(st->host);
+++	git__free(st->port);
+++	git__free(st);
+++}
+++
+++int git_socket_stream_new(git_stream **out, const char *host, const char *port)
+++{
+++	git_socket_stream *st;
+++
+++	assert(out && host);
+++
+++	st = git__calloc(1, sizeof(git_socket_stream));
+++	GITERR_CHECK_ALLOC(st);
+++
+++	st->host = git__strdup(host);
+++	GITERR_CHECK_ALLOC(st->host);
+++
+++	if (port) {
+++		st->port = git__strdup(port);
+++		GITERR_CHECK_ALLOC(st->port);
+++	}
+++
+++	st->parent.version = GIT_STREAM_VERSION;
+++	st->parent.connect = socket_connect;
+++	st->parent.write = socket_write;
+++	st->parent.read = socket_read;
+++	st->parent.close = socket_close;
+++	st->parent.free = socket_free;
+++	st->s = INVALID_SOCKET;
+++
+++	*out = (git_stream *) st;
+++	return 0;
+++}
++diff --git a/src/streams/socket.h b/src/streams/socket.h
+ new file mode 100644
+-index 0000000..5cb1071
++index 0000000..8e9949f
+ --- /dev/null
+-+++ b/src/mbedtls_stream.h
+-@@ -0,0 +1,16 @@
+++++ b/src/streams/socket.h
++@@ -0,0 +1,21 @@
+ +/*
+ + * 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.
+ + */
+-+#ifndef INCLUDE_mbedtls_stream_h__
+-+#define INCLUDE_mbedtls_stream_h__
+++#ifndef INCLUDE_socket_stream_h__
+++#define INCLUDE_socket_stream_h__
+ +
+-+#include "git2/sys/stream.h"
+++#include "netops.h"
+ +
+-+extern int git_mbedtls_stream_global_init(void);
+++typedef struct {
+++	git_stream parent;
+++	char *host;
+++	char *port;
+++	GIT_SOCKET s;
+++} git_socket_stream;
+ +
+-+extern int git_mbedtls_stream_new(git_stream **out, const char *host, const char *port);
+++extern int git_socket_stream_new(git_stream **out, const char *host, const char *port);
+ +
+ +#endif
+-diff --git a/src/settings.c b/src/settings.c
+-index 0da19ea..65bbb41 100644
+---- a/src/settings.c
+-+++ b/src/settings.c
+-@@ -9,6 +9,10 @@
+- # include <openssl/err.h>
+- #endif
+- 
+-+#ifdef GIT_MBEDTLS
+-+# include <mbedtls/error.h>
++diff --git a/src/streams/stransport.c b/src/streams/stransport.c
++new file mode 100644
++index 0000000..4c099f9
++--- /dev/null
+++++ b/src/streams/stransport.c
++@@ -0,0 +1,294 @@
+++/*
+++ * 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.
+++ */
+++
+++#ifdef GIT_SECURE_TRANSPORT
+++
+++#include <CoreFoundation/CoreFoundation.h>
+++#include <Security/SecureTransport.h>
+++#include <Security/SecCertificate.h>
+++
+++#include "git2/transport.h"
+++
+++#include "streams/socket.h"
+++#include "streams/curl.h"
+++
+++static int stransport_error(OSStatus ret)
+++{
+++	CFStringRef message;
+++
+++	if (ret == noErr || ret == errSSLClosedGraceful) {
+++		giterr_clear();
+++		return 0;
+++	}
+++
+++#if !TARGET_OS_IPHONE
+++	message = SecCopyErrorMessageString(ret, NULL);
+++	GITERR_CHECK_ALLOC(message);
+++
+++	giterr_set(GITERR_NET, "SecureTransport error: %s", CFStringGetCStringPtr(message, kCFStringEncodingUTF8));
+++	CFRelease(message);
+++#else
+++    giterr_set(GITERR_NET, "SecureTransport error: OSStatus %d", (unsigned int)ret);
+++    GIT_UNUSED(message);
+ +#endif
+ +
+- #include <git2.h>
+- #include "common.h"
+- #include "sysdir.h"
+-@@ -29,7 +33,7 @@ int git_libgit2_features()
+- #ifdef GIT_THREADS
+- 		| GIT_FEATURE_THREADS
+- #endif
+--#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT)
+-+#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_MBEDTLS)
+- 		| GIT_FEATURE_HTTPS
+- #endif
+- #if defined(GIT_SSH)
+-@@ -174,8 +178,34 @@ int git_libgit2_opts(int key, ...)
+- 				error = -1;
+- 			}
+- 		}
+-+#elif GIT_MBEDTLS
+-+		{
+-+			const char *file = va_arg(ap, const char *);
+-+			const char *path = va_arg(ap, const char *);
+-+			int ret = 0;
+-+			char errbuf[512];
+-+			mbedtls_x509_crt *cacert;
+-+			cacert = git__malloc(sizeof(mbedtls_x509_crt));
+-+			mbedtls_x509_crt_init(cacert);
+-+			if (file) {
+-+				ret = mbedtls_x509_crt_parse_file(cacert, file);
+-+			} else if (path) {
+-+				ret = mbedtls_x509_crt_parse_path(cacert, path);
+-+			}
+-+			if (!ret) {
+-+				mbedtls_x509_crt_free(cacert);
+-+				git__free(cacert);
+-+				mbedtls_strerror( ret, errbuf, 512 );
+-+				giterr_set(GITERR_SSL, "SSL error: failed to load CA certificates : %s (%d)", ret, errbuf);
+-+				error = -1;
+-+			} else {
+-+				mbedtls_x509_crt_free(git__ssl_conf->ca_chain);
+-+				git__free(git__ssl_conf->ca_chain);
+-+				mbedtls_ssl_conf_ca_chain(git__ssl_conf, cacert, NULL);
+-+			}
+++	return -1;
+++}
+++
+++typedef struct {
+++	git_stream parent;
+++	git_stream *io;
+++	SSLContextRef ctx;
+++	CFDataRef der_data;
+++	git_cert_x509 cert_info;
+++} stransport_stream;
+++
+++static int stransport_connect(git_stream *stream)
+++{
+++	stransport_stream *st = (stransport_stream *) stream;
+++	int error;
+++	SecTrustRef trust = NULL;
+++	SecTrustResultType sec_res;
+++	OSStatus ret;
+++
+++	if ((error = git_stream_connect(st->io)) < 0)
+++		return error;
+++
+++	ret = SSLHandshake(st->ctx);
+++	if (ret != errSSLServerAuthCompleted) {
+++		giterr_set(GITERR_SSL, "unexpected return value from ssl handshake %d", ret);
+++		return -1;
+++	}
+++
+++	if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
+++		goto on_error;
+++
+++	if (!trust)
+++		return GIT_ECERTIFICATE;
+++
+++	if ((ret = SecTrustEvaluate(trust, &sec_res)) != noErr)
+++		goto on_error;
+++
+++	CFRelease(trust);
+++
+++	if (sec_res == kSecTrustResultInvalid || sec_res == kSecTrustResultOtherError) {
+++		giterr_set(GITERR_SSL, "internal security trust error");
+++		return -1;
+++	}
+++
+++	if (sec_res == kSecTrustResultDeny || sec_res == kSecTrustResultRecoverableTrustFailure ||
+++	    sec_res == kSecTrustResultFatalTrustFailure)
+++		return GIT_ECERTIFICATE;
+++
+++	return 0;
+++
+++on_error:
+++	if (trust)
+++		CFRelease(trust);
+++
+++	return stransport_error(ret);
+++}
+++
+++static int stransport_certificate(git_cert **out, git_stream *stream)
+++{
+++	stransport_stream *st = (stransport_stream *) stream;
+++	SecTrustRef trust = NULL;
+++	SecCertificateRef sec_cert;
+++	OSStatus ret;
+++
+++	if ((ret = SSLCopyPeerTrust(st->ctx, &trust)) != noErr)
+++		return stransport_error(ret);
+++
+++	sec_cert = SecTrustGetCertificateAtIndex(trust, 0);
+++	st->der_data = SecCertificateCopyData(sec_cert);
+++	CFRelease(trust);
+++
+++	if (st->der_data == NULL) {
+++		giterr_set(GITERR_SSL, "retrieved invalid certificate data");
+++		return -1;
+++	}
+++
+++	st->cert_info.parent.cert_type = GIT_CERT_X509;
+++	st->cert_info.data = (void *) CFDataGetBytePtr(st->der_data);
+++	st->cert_info.len = CFDataGetLength(st->der_data);
+++
+++	*out = (git_cert *)&st->cert_info;
+++	return 0;
+++}
+++
+++static int stransport_set_proxy(
+++	git_stream *stream,
+++	const git_proxy_options *proxy_opts)
+++{
+++	stransport_stream *st = (stransport_stream *) stream;
+++
+++	return git_stream_set_proxy(st->io, proxy_opts);
+++}
+++
+++/*
+++ * Contrary to typical network IO callbacks, Secure Transport write callback is
+++ * expected to write *all* passed data, not just as much as it can, and any
+++ * other case would be considered a failure.
+++ *
+++ * This behavior is actually not specified in the Apple documentation, but is
+++ * required for things to work correctly (and incidentally, that's also how
+++ * Apple implements it in its projects at opensource.apple.com).
+++ *
+++ * Libgit2 streams happen to already have this very behavior so this is just
+++ * passthrough.
+++ */
+++static OSStatus write_cb(SSLConnectionRef conn, const void *data, size_t *len)
+++{
+++	git_stream *io = (git_stream *) conn;
+++
+++	if (git_stream_write(io, data, *len, 0) < 0) {
+++		return -36; /* "ioErr" from MacErrors.h which is not available on iOS */
+++	}
+++
+++	return noErr;
+++}
+++
+++static ssize_t stransport_write(git_stream *stream, const char *data, size_t len, int flags)
+++{
+++	stransport_stream *st = (stransport_stream *) stream;
+++	size_t data_len, processed;
+++	OSStatus ret;
+++
+++	GIT_UNUSED(flags);
+++
+++	data_len = len;
+++	if ((ret = SSLWrite(st->ctx, data, data_len, &processed)) != noErr)
+++		return stransport_error(ret);
+++
+++	return processed;
+++}
+++
+++/*
+++ * Contrary to typical network IO callbacks, Secure Transport read callback is
+++ * expected to read *exactly* the requested number of bytes, not just as much
+++ * as it can, and any other case would be considered a failure.
+++ *
+++ * This behavior is actually not specified in the Apple documentation, but is
+++ * required for things to work correctly (and incidentally, that's also how
+++ * Apple implements it in its projects at opensource.apple.com).
+++ */
+++static OSStatus read_cb(SSLConnectionRef conn, void *data, size_t *len)
+++{
+++	git_stream *io = (git_stream *) conn;
+++	OSStatus error = noErr;
+++	size_t off = 0;
+++	ssize_t ret;
+++
+++	do {
+++		ret = git_stream_read(io, data + off, *len - off);
+++		if (ret < 0) {
+++			error = -36; /* "ioErr" from MacErrors.h which is not available on iOS */
+++			break;
+ +		}
+- #else
+--		giterr_set(GITERR_NET, "cannot set certificate locations: OpenSSL is not enabled");
+-+		giterr_set(GITERR_NET, "Cannot set certificate locations: OpenSSL or mbedTLS is not enabled");
+- 		error = -1;
+- #endif
+- 		break;
+++		if (ret == 0) {
+++			error = errSSLClosedGraceful;
+++			break;
+++		}
+++
+++		off += ret;
+++	} while (off < *len);
+++
+++	*len = off;
+++	return error;
+++}
+++
+++static ssize_t stransport_read(git_stream *stream, void *data, size_t len)
+++{
+++	stransport_stream *st = (stransport_stream *) stream;
+++	size_t processed;
+++	OSStatus ret;
+++
+++	if ((ret = SSLRead(st->ctx, data, len, &processed)) != noErr)
+++		return stransport_error(ret);
+++
+++	return processed;
+++}
+++
+++static int stransport_close(git_stream *stream)
+++{
+++	stransport_stream *st = (stransport_stream *) stream;
+++	OSStatus ret;
+++
+++	ret = SSLClose(st->ctx);
+++	if (ret != noErr && ret != errSSLClosedGraceful)
+++		return stransport_error(ret);
+++
+++	return git_stream_close(st->io);
+++}
+++
+++static void stransport_free(git_stream *stream)
+++{
+++	stransport_stream *st = (stransport_stream *) stream;
+++
+++	git_stream_free(st->io);
+++	CFRelease(st->ctx);
+++	if (st->der_data)
+++		CFRelease(st->der_data);
+++	git__free(st);
+++}
+++
+++int git_stransport_stream_new(git_stream **out, const char *host, const char *port)
+++{
+++	stransport_stream *st;
+++	int error;
+++	OSStatus ret;
+++
+++	assert(out && host);
+++
+++	st = git__calloc(1, sizeof(stransport_stream));
+++	GITERR_CHECK_ALLOC(st);
+++
+++#ifdef GIT_CURL
+++	error = git_curl_stream_new(&st->io, host, port);
+++#else
+++	error = git_socket_stream_new(&st->io, host, port);
+++#endif
+++
+++	if (error < 0){
+++		git__free(st);
+++		return error;
+++	}
+++
+++	st->ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
+++	if (!st->ctx) {
+++		giterr_set(GITERR_NET, "failed to create SSL context");
+++		git__free(st);
+++		return -1;
+++	}
+++
+++	if ((ret = SSLSetIOFuncs(st->ctx, read_cb, write_cb)) != noErr ||
+++	    (ret = SSLSetConnection(st->ctx, st->io)) != noErr ||
+++	    (ret = SSLSetSessionOption(st->ctx, kSSLSessionOptionBreakOnServerAuth, true)) != noErr ||
+++	    (ret = SSLSetProtocolVersionMin(st->ctx, kTLSProtocol1)) != noErr ||
+++	    (ret = SSLSetProtocolVersionMax(st->ctx, kTLSProtocol12)) != noErr ||
+++	    (ret = SSLSetPeerDomainName(st->ctx, host, strlen(host))) != noErr) {
+++		CFRelease(st->ctx);
+++		git__free(st);
+++		return stransport_error(ret);
+++	}
+++
+++	st->parent.version = GIT_STREAM_VERSION;
+++	st->parent.encrypted = 1;
+++	st->parent.proxy_support = git_stream_supports_proxy(st->io);
+++	st->parent.connect = stransport_connect;
+++	st->parent.certificate = stransport_certificate;
+++	st->parent.set_proxy = stransport_set_proxy;
+++	st->parent.read = stransport_read;
+++	st->parent.write = stransport_write;
+++	st->parent.close = stransport_close;
+++	st->parent.free = stransport_free;
+++
+++	*out = (git_stream *) st;
+++	return 0;
+++}
+++
+++#endif
++diff --git a/src/streams/stransport.h b/src/streams/stransport.h
++new file mode 100644
++index 0000000..714f902
++--- /dev/null
+++++ b/src/streams/stransport.h
++@@ -0,0 +1,14 @@
+++/*
+++ * 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.
+++ */
+++#ifndef INCLUDE_stransport_stream_h__
+++#define INCLUDE_stransport_stream_h__
+++
+++#include "git2/sys/stream.h"
+++
+++extern int git_stransport_stream_new(git_stream **out, const char *host, const char *port);
+++
+++#endif
+ diff --git a/src/tls_stream.c b/src/tls_stream.c
+-index 83e2d06..6fb538f 100644
++index 83e2d06..27e5cc2 100644
+ --- a/src/tls_stream.c
+ +++ b/src/tls_stream.c
+-@@ -9,6 +9,7 @@
++@@ -8,8 +8,9 @@
++ #include "git2/errors.h"
+  #include "common.h"
+  
+- #include "openssl_stream.h"
+-+#include "mbedtls_stream.h"
+- #include "stransport_stream.h"
++-#include "openssl_stream.h"
++-#include "stransport_stream.h"
+++#include "streams/mbedtls.h"
+++#include "streams/openssl.h"
+++#include "streams/stransport.h"
+  
+  static git_stream_cb tls_ctor;
++ 
+ @@ -30,6 +31,8 @@ int git_tls_stream_new(git_stream **out, const char *host, const char *port)
+  	return git_stransport_stream_new(out, host, port);
+  #elif defined(GIT_OPENSSL)
+  	return git_openssl_stream_new(out, host, port);
+ +#elif defined(GIT_MBEDTLS)
+-+    return git_mbedtls_stream_new(out, host, port);
+++	return git_mbedtls_stream_new(out, host, port);
+  #else
+  	GIT_UNUSED(out);
+  	GIT_UNUSED(host);
++diff --git a/src/transports/git.c b/src/transports/git.c
++index 01edfdc..cae10c3 100644
++--- a/src/transports/git.c
+++++ b/src/transports/git.c
++@@ -10,7 +10,7 @@
++ #include "netops.h"
++ #include "git2/sys/transport.h"
++ #include "stream.h"
++-#include "socket_stream.h"
+++#include "streams/socket.h"
++ 
++ #define OWNING_SUBTRANSPORT(s) ((git_subtransport *)(s)->parent.subtransport)
++ 
++diff --git a/src/transports/http.c b/src/transports/http.c
++index cb4a6d0..b602adf 100644
++--- a/src/transports/http.c
+++++ b/src/transports/http.c
++@@ -16,8 +16,8 @@
++ #include "auth.h"
++ #include "auth_negotiate.h"
++ #include "tls_stream.h"
++-#include "socket_stream.h"
++-#include "curl_stream.h"
+++#include "streams/socket.h"
+++#include "streams/curl.h"
++ 
++ git_http_auth_scheme auth_schemes[] = {
++ 	{ GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
++diff --git a/src/transports/ssh.c b/src/transports/ssh.c
++index 4c55e3f..3cb5655 100644
++--- a/src/transports/ssh.c
+++++ b/src/transports/ssh.c
++@@ -15,7 +15,7 @@
++ #include "netops.h"
++ #include "smart.h"
++ #include "cred.h"
++-#include "socket_stream.h"
+++#include "streams/socket.h"
++ #include "ssh.h"
++ 
++ #ifdef GIT_SSH
+ diff --git a/tests/core/stream.c b/tests/core/stream.c
+-index 0cbf442..a4fa2b4 100644
++index 0cbf442..2da4b2f 100644
+ --- a/tests/core/stream.c
+ +++ b/tests/core/stream.c
+-@@ -38,7 +38,7 @@ void test_core_stream__register_tls(void)
++@@ -37,8 +37,7 @@ void test_core_stream__register_tls(void)
++ 	 * or when openssl support is disabled (except on OSX
+  	 * with Security framework).
+  	 */
+- #if defined(GIT_WIN32) || \
++-#if defined(GIT_WIN32) || \
+ -	(!defined(GIT_SECURE_TRANSPORT) && !defined(GIT_OPENSSL))
+-+	(!defined(GIT_SECURE_TRANSPORT) && !(defined(GIT_OPENSSL) || defined(GIT_MBEDTLS)))
+++#if defined(GIT_WIN32) || !defined(GIT_HTTPS)
+  	cl_git_fail_with(-1, error);
+  #else
+  	cl_git_pass(error);
+-diff --git a/tests/online/badssl.c b/tests/online/badssl.c
+-index 66b090d..bba31cc 100644
+---- a/tests/online/badssl.c
+-+++ b/tests/online/badssl.c
+-@@ -4,7 +4,7 @@
++diff --git a/tests/main.c b/tests/main.c
++index f67c8ff..3dadc5d 100644
++--- a/tests/main.c
+++++ b/tests/main.c
++@@ -11,7 +11,11 @@ int main(int argc, char *argv[])
+  
+- static git_repository *g_repo;
++ 	clar_test_init(argc, argv);
++ 
++-	git_libgit2_init();
+++	res = git_libgit2_init();
+++	if (res < 0) {
+++		return res;
+++	}
+++
++ 	cl_global_trace_register();
++ 	cl_sandbox_set_search_path_defaults();
+  
+--#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT)
+-+#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_MBEDTLS)
+- static bool g_has_ssl = true;
+- #else
+- static bool g_has_ssl = false;
+diff --git a/deps/patches/libgit2-remote-push-NULL.patch b/deps/patches/libgit2-remote-push-NULL.patch
+deleted file mode 100644
+index ac84d6d1bacb..000000000000
+--- a/deps/patches/libgit2-remote-push-NULL.patch
++++ /dev/null
+@@ -1,26 +0,0 @@
+-From 90cdf44ffb7c78cb9d36709f8a07a216e06bd919 Mon Sep 17 00:00:00 2001
+-From: Yichao Yu <[email-masked]>
+-Date: Sat, 29 Apr 2017 13:00:07 -0400
+-Subject: [PATCH] Allow NULL refspec in git_remote_push
+-
+-Since this is allowed in `git_remote_upload`
+----
+- src/remote.c | 2 +-
+- 1 file changed, 1 insertion(+), 1 deletion(-)
+-
+-diff --git a/src/remote.c b/src/remote.c
+-index d3132f75c..4cbc45eda 100644
+---- a/src/remote.c
+-+++ b/src/remote.c
+-@@ -2412,7 +2412,7 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
+- 		proxy = &opts->proxy_opts;
+- 	}
+- 
+--	assert(remote && refspecs);
+-+	assert(remote);
+- 
+- 	if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, proxy, custom_headers)) < 0)
+- 		return error;
+--- 
+-2.12.2
+-
+
+From 5492792021061ec6861564dad9575d5d6889c80d Mon Sep 17 00:00:00 2001
+From: Curtis Vogt <[email-masked]>
+Date: Sun, 2 Jul 2017 23:30:48 -0500
+Subject: [PATCH 2/2] Remove libgit2-free-config patch
+
+---
+ deps/patches/libgit2-free-config.patch | 25 -------------------------
+ 1 file changed, 25 deletions(-)
+ delete mode 100644 deps/patches/libgit2-free-config.patch
+
+diff --git a/deps/patches/libgit2-free-config.patch b/deps/patches/libgit2-free-config.patch
+deleted file mode 100644
+index 767aa816c3c1..000000000000
+--- a/deps/patches/libgit2-free-config.patch
++++ /dev/null
+@@ -1,25 +0,0 @@
+-From 5552237686dae90fb9c22f0088de488b48654828 Mon Sep 17 00:00:00 2001
+-From: Yichao Yu <[email-masked]>
+-Date: Sat, 29 Apr 2017 12:28:35 -0400
+-Subject: [PATCH] Do not free config when creating remote
+-
+-The regression was introduced in 22261344de18b3cc60ee6937468d66a6a6a28875
+----
+- src/remote.c | 1 -
+- 1 file changed, 1 deletion(-)
+-
+-diff --git a/src/remote.c b/src/remote.c
+-index d3132f75c..15752ab27 100644
+---- a/src/remote.c
+-+++ b/src/remote.c
+-@@ -260,7 +260,6 @@ on_error:
+- 	if (error)
+- 		git_remote_free(remote);
+- 
+--	git_config_free(config);
+- 	git_buf_free(&canonical_url);
+- 	git_buf_free(&var);
+- 	return error;
+--- 
+-2.12.2
+-
-- 
2.15.0

---
Unsubscribe:  [email-masked]
Help:         [email-masked]
---