d3dc6b8
From d3a5f68ae759bd5abaa5eb2ffb265210392462e1 Mon Sep 17 00:00:00 2001
d3dc6b8
From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= <cmn@dwim.me>
d3dc6b8
Date: Wed, 2 Nov 2016 12:28:25 +0100
d3dc6b8
Subject: [PATCH 2/4] openssl: recreate the OpenSSL 1.1 BIO interface for older
d3dc6b8
 versions
d3dc6b8
d3dc6b8
We want to program against the interface, so recreate it when we compile
d3dc6b8
against pre-1.1 versions.
d3dc6b8
d3dc6b8
(cherry picked from commit f15eedb3a390dcbe441cd77231c3449ff941d189)
d3dc6b8
---
d3dc6b8
 src/openssl_stream.c | 92 ++++++++++++++++++++-----------------------------
d3dc6b8
 src/openssl_stream.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++
d3dc6b8
 2 files changed, 134 insertions(+), 55 deletions(-)
d3dc6b8
d3dc6b8
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
d3dc6b8
index fc580cf..328a131 100644
d3dc6b8
--- a/src/openssl_stream.c
d3dc6b8
+++ b/src/openssl_stream.c
d3dc6b8
@@ -13,6 +13,7 @@
d3dc6b8
 #include "posix.h"
d3dc6b8
 #include "stream.h"
d3dc6b8
 #include "socket_stream.h"
d3dc6b8
+#include "openssl_stream.h"
d3dc6b8
 #include "netops.h"
d3dc6b8
 #include "git2/transport.h"
d3dc6b8
 #include "git2/sys/openssl.h"
d3dc6b8
@@ -71,12 +72,20 @@ static void shutdown_ssl_locking(void)
d3dc6b8
 
d3dc6b8
 #endif /* GIT_THREADS */
d3dc6b8
 
d3dc6b8
+static BIO_METHOD *git_stream_bio_method;
d3dc6b8
+static int init_bio_method(void);
d3dc6b8
+
d3dc6b8
 /**
d3dc6b8
  * This function aims to clean-up the SSL context which
d3dc6b8
  * we allocated.
d3dc6b8
  */
d3dc6b8
 static void shutdown_ssl(void)
d3dc6b8
 {
d3dc6b8
+	if (git_stream_bio_method) {
d3dc6b8
+		BIO_meth_free(git_stream_bio_method);
d3dc6b8
+		git_stream_bio_method = NULL;
d3dc6b8
+	}
d3dc6b8
+
d3dc6b8
 	if (git__ssl_ctx) {
d3dc6b8
 		SSL_CTX_free(git__ssl_ctx);
d3dc6b8
 		git__ssl_ctx = NULL;
d3dc6b8
@@ -121,6 +130,13 @@ int git_openssl_stream_global_init(void)
d3dc6b8
 		git__ssl_ctx = NULL;
d3dc6b8
 		return -1;
d3dc6b8
 	}
d3dc6b8
+
d3dc6b8
+	if (init_bio_method() < 0) {
d3dc6b8
+		SSL_CTX_free(git__ssl_ctx);
d3dc6b8
+		git__ssl_ctx = NULL;
d3dc6b8
+		return -1;
d3dc6b8
+	}
d3dc6b8
+
d3dc6b8
 #endif
d3dc6b8
 
d3dc6b8
 	git__on_shutdown(shutdown_ssl);
d3dc6b8
@@ -156,14 +172,8 @@ int git_openssl_set_locking(void)
d3dc6b8
 
d3dc6b8
 static int bio_create(BIO *b)
d3dc6b8
 {
d3dc6b8
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
-	b->init = 1;
d3dc6b8
-	b->num = 0;
d3dc6b8
-	b->ptr = NULL;
d3dc6b8
-	b->flags = 0;
d3dc6b8
-#else
d3dc6b8
 	BIO_set_init(b, 1);
d3dc6b8
-#endif
d3dc6b8
+	BIO_set_data(b, NULL);
d3dc6b8
 
d3dc6b8
 	return 1;
d3dc6b8
 }
d3dc6b8
@@ -173,36 +183,22 @@ static int bio_destroy(BIO *b)
d3dc6b8
 	if (!b)
d3dc6b8
 		return 0;
d3dc6b8
 
d3dc6b8
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
-	b->init = 0;
d3dc6b8
-	b->num = 0;
d3dc6b8
-	b->ptr = NULL;
d3dc6b8
-	b->flags = 0;
d3dc6b8
-#else
d3dc6b8
-	BIO_set_init(b, 0);
d3dc6b8
 	BIO_set_data(b, NULL);
d3dc6b8
-#endif
d3dc6b8
 
d3dc6b8
 	return 1;
d3dc6b8
 }
d3dc6b8
 
d3dc6b8
 static int bio_read(BIO *b, char *buf, int len)
d3dc6b8
 {
d3dc6b8
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
-	git_stream *io = (git_stream *) b->ptr;
d3dc6b8
-#else
d3dc6b8
 	git_stream *io = (git_stream *) BIO_get_data(b);
d3dc6b8
-#endif
d3dc6b8
+
d3dc6b8
 	return (int) git_stream_read(io, buf, len);
d3dc6b8
 }
d3dc6b8
 
d3dc6b8
 static int bio_write(BIO *b, const char *buf, int len)
d3dc6b8
 {
d3dc6b8
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
-	git_stream *io = (git_stream *) b->ptr;
d3dc6b8
-#else
d3dc6b8
 	git_stream *io = (git_stream *) BIO_get_data(b);
d3dc6b8
-#endif
d3dc6b8
+
d3dc6b8
 	return (int) git_stream_write(io, buf, len, 0);
d3dc6b8
 }
d3dc6b8
 
d3dc6b8
@@ -231,21 +227,22 @@ static int bio_puts(BIO *b, const char *str)
d3dc6b8
 	return bio_write(b, str, strlen(str));
d3dc6b8
 }
d3dc6b8
 
d3dc6b8
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
-static BIO_METHOD git_stream_bio_method = {
d3dc6b8
-	BIO_TYPE_SOURCE_SINK,
d3dc6b8
-	"git_stream",
d3dc6b8
-	bio_write,
d3dc6b8
-	bio_read,
d3dc6b8
-	bio_puts,
d3dc6b8
-	bio_gets,
d3dc6b8
-	bio_ctrl,
d3dc6b8
-	bio_create,
d3dc6b8
-	bio_destroy
d3dc6b8
-};
d3dc6b8
-#else
d3dc6b8
-static BIO_METHOD *git_stream_bio_method = NULL;
d3dc6b8
-#endif
d3dc6b8
+static int init_bio_method(void)
d3dc6b8
+{
d3dc6b8
+	/* Set up the BIO_METHOD we use for wrapping our own stream implementations */
d3dc6b8
+	git_stream_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "git_stream");
d3dc6b8
+	GITERR_CHECK_ALLOC(git_stream_bio_method);
d3dc6b8
+
d3dc6b8
+	BIO_meth_set_write(git_stream_bio_method, bio_write);
d3dc6b8
+	BIO_meth_set_read(git_stream_bio_method, bio_read);
d3dc6b8
+	BIO_meth_set_puts(git_stream_bio_method, bio_puts);
d3dc6b8
+	BIO_meth_set_gets(git_stream_bio_method, bio_gets);
d3dc6b8
+	BIO_meth_set_ctrl(git_stream_bio_method, bio_ctrl);
d3dc6b8
+	BIO_meth_set_create(git_stream_bio_method, bio_create);
d3dc6b8
+	BIO_meth_set_destroy(git_stream_bio_method, bio_destroy);
d3dc6b8
+
d3dc6b8
+	return 0;
d3dc6b8
+}
d3dc6b8
 
d3dc6b8
 static int ssl_set_error(SSL *ssl, int error)
d3dc6b8
 {
d3dc6b8
@@ -466,27 +463,12 @@ int openssl_connect(git_stream *stream)
d3dc6b8
 
d3dc6b8
 	st->connected = true;
d3dc6b8
 
d3dc6b8
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
-	bio = BIO_new(&git_stream_bio_method);
d3dc6b8
-#else
d3dc6b8
-	git_stream_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "git_stream");
d3dc6b8
-	BIO_meth_set_write(git_stream_bio_method, bio_write);
d3dc6b8
-	BIO_meth_set_read(git_stream_bio_method, bio_read);
d3dc6b8
-	BIO_meth_set_puts(git_stream_bio_method, bio_puts);
d3dc6b8
-	BIO_meth_set_gets(git_stream_bio_method, bio_gets);
d3dc6b8
-	BIO_meth_set_ctrl(git_stream_bio_method, bio_ctrl);
d3dc6b8
-	BIO_meth_set_create(git_stream_bio_method, bio_create);
d3dc6b8
-	BIO_meth_set_destroy(git_stream_bio_method, bio_destroy);
d3dc6b8
 	bio = BIO_new(git_stream_bio_method);
d3dc6b8
-#endif
d3dc6b8
 	GITERR_CHECK_ALLOC(bio);
d3dc6b8
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
-	bio->ptr = st->io;
d3dc6b8
-#else
d3dc6b8
-	BIO_set_data(bio, st->io);
d3dc6b8
-#endif
d3dc6b8
 
d3dc6b8
+	BIO_set_data(bio, st->io);
d3dc6b8
 	SSL_set_bio(st->ssl, bio, bio);
d3dc6b8
+
d3dc6b8
 	/* specify the host in case SNI is needed */
d3dc6b8
 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
d3dc6b8
 	SSL_set_tlsext_host_name(st->ssl, st->host);
d3dc6b8
diff --git a/src/openssl_stream.h b/src/openssl_stream.h
d3dc6b8
index 82b5110..509e404 100644
d3dc6b8
--- a/src/openssl_stream.h
d3dc6b8
+++ b/src/openssl_stream.h
d3dc6b8
@@ -7,10 +7,107 @@
d3dc6b8
 #ifndef INCLUDE_openssl_stream_h__
d3dc6b8
 #define INCLUDE_openssl_stream_h__
d3dc6b8
 
d3dc6b8
+#include <openssl/ssl.h>
d3dc6b8
+#include <openssl/err.h>
d3dc6b8
+#include <openssl/x509v3.h>
d3dc6b8
+#include <openssl/bio.h>
d3dc6b8
+
d3dc6b8
 #include "git2/sys/stream.h"
d3dc6b8
 
d3dc6b8
 extern int git_openssl_stream_global_init(void);
d3dc6b8
 
d3dc6b8
 extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
d3dc6b8
 
d3dc6b8
+/*
d3dc6b8
+ * OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
d3dc6b8
+ * which do not exist in previous versions. We define these inline functions so
d3dc6b8
+ * we can program against the interface instead of littering the implementation
d3dc6b8
+ * with ifdefs.
d3dc6b8
+ */
d3dc6b8
+# if OPENSSL_VERSION_NUMBER < 0x10100000L
d3dc6b8
+
d3dc6b8
+GIT_INLINE(BIO_METHOD*) BIO_meth_new(int type, const char *name)
d3dc6b8
+{
d3dc6b8
+	BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
d3dc6b8
+	if (!meth) {
d3dc6b8
+		return NULL;
d3dc6b8
+	}
d3dc6b8
+
d3dc6b8
+	meth->type = type;
d3dc6b8
+	meth->name = name;
d3dc6b8
+
d3dc6b8
+	return meth;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(void) BIO_meth_free(BIO_METHOD *biom)
d3dc6b8
+{
d3dc6b8
+	git__free(biom);
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
d3dc6b8
+{
d3dc6b8
+	biom->bwrite = write;
d3dc6b8
+	return 1;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
d3dc6b8
+{
d3dc6b8
+	biom->bread = read;
d3dc6b8
+	return 1;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
d3dc6b8
+{
d3dc6b8
+	biom->bputs = puts;
d3dc6b8
+	return 1;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
d3dc6b8
+
d3dc6b8
+{
d3dc6b8
+	biom->bgets = gets;
d3dc6b8
+	return 1;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
d3dc6b8
+{
d3dc6b8
+	biom->ctrl = ctrl;
d3dc6b8
+	return 1;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
d3dc6b8
+{
d3dc6b8
+	biom->create = create;
d3dc6b8
+	return 1;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
d3dc6b8
+{
d3dc6b8
+	biom->destroy = destroy;
d3dc6b8
+	return 1;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(int) BIO_get_new_index(void)
d3dc6b8
+{
d3dc6b8
+	/* This exists as of 1.1 so before we'd just have 0 */
d3dc6b8
+	return 0;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(void) BIO_set_init(BIO *b, int init)
d3dc6b8
+{
d3dc6b8
+	b->init = init;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(void) BIO_set_data(BIO *a, void *ptr)
d3dc6b8
+{
d3dc6b8
+	a->ptr = ptr;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+GIT_INLINE(void*) BIO_get_data(BIO *a)
d3dc6b8
+{
d3dc6b8
+	return a->ptr;
d3dc6b8
+}
d3dc6b8
+
d3dc6b8
+# endif
d3dc6b8
+
d3dc6b8
 #endif
d3dc6b8
-- 
d3dc6b8
2.10.1
d3dc6b8