Skip to content

Commit f15eedb

Browse files
committed
openssl: recreate the OpenSSL 1.1 BIO interface for older versions
We want to program against the interface, so recreate it when we compile against pre-1.1 versions.
1 parent feb330d commit f15eedb

File tree

2 files changed

+134
-55
lines changed

2 files changed

+134
-55
lines changed

src/openssl_stream.c

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "posix.h"
1414
#include "stream.h"
1515
#include "socket_stream.h"
16+
#include "openssl_stream.h"
1617
#include "netops.h"
1718
#include "git2/transport.h"
1819
#include "git2/sys/openssl.h"
@@ -71,12 +72,20 @@ static void shutdown_ssl_locking(void)
7172

7273
#endif /* GIT_THREADS */
7374

75+
static BIO_METHOD *git_stream_bio_method;
76+
static int init_bio_method(void);
77+
7478
/**
7579
* This function aims to clean-up the SSL context which
7680
* we allocated.
7781
*/
7882
static void shutdown_ssl(void)
7983
{
84+
if (git_stream_bio_method) {
85+
BIO_meth_free(git_stream_bio_method);
86+
git_stream_bio_method = NULL;
87+
}
88+
8089
if (git__ssl_ctx) {
8190
SSL_CTX_free(git__ssl_ctx);
8291
git__ssl_ctx = NULL;
@@ -121,6 +130,13 @@ int git_openssl_stream_global_init(void)
121130
git__ssl_ctx = NULL;
122131
return -1;
123132
}
133+
134+
if (init_bio_method() < 0) {
135+
SSL_CTX_free(git__ssl_ctx);
136+
git__ssl_ctx = NULL;
137+
return -1;
138+
}
139+
124140
#endif
125141

126142
git__on_shutdown(shutdown_ssl);
@@ -156,14 +172,8 @@ int git_openssl_set_locking(void)
156172

157173
static int bio_create(BIO *b)
158174
{
159-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
160-
b->init = 1;
161-
b->num = 0;
162-
b->ptr = NULL;
163-
b->flags = 0;
164-
#else
165175
BIO_set_init(b, 1);
166-
#endif
176+
BIO_set_data(b, NULL);
167177

168178
return 1;
169179
}
@@ -173,36 +183,22 @@ static int bio_destroy(BIO *b)
173183
if (!b)
174184
return 0;
175185

176-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
177-
b->init = 0;
178-
b->num = 0;
179-
b->ptr = NULL;
180-
b->flags = 0;
181-
#else
182-
BIO_set_init(b, 0);
183186
BIO_set_data(b, NULL);
184-
#endif
185187

186188
return 1;
187189
}
188190

189191
static int bio_read(BIO *b, char *buf, int len)
190192
{
191-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
192-
git_stream *io = (git_stream *) b->ptr;
193-
#else
194193
git_stream *io = (git_stream *) BIO_get_data(b);
195-
#endif
194+
196195
return (int) git_stream_read(io, buf, len);
197196
}
198197

199198
static int bio_write(BIO *b, const char *buf, int len)
200199
{
201-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
202-
git_stream *io = (git_stream *) b->ptr;
203-
#else
204200
git_stream *io = (git_stream *) BIO_get_data(b);
205-
#endif
201+
206202
return (int) git_stream_write(io, buf, len, 0);
207203
}
208204

@@ -231,21 +227,22 @@ static int bio_puts(BIO *b, const char *str)
231227
return bio_write(b, str, strlen(str));
232228
}
233229

234-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
235-
static BIO_METHOD git_stream_bio_method = {
236-
BIO_TYPE_SOURCE_SINK,
237-
"git_stream",
238-
bio_write,
239-
bio_read,
240-
bio_puts,
241-
bio_gets,
242-
bio_ctrl,
243-
bio_create,
244-
bio_destroy
245-
};
246-
#else
247-
static BIO_METHOD *git_stream_bio_method = NULL;
248-
#endif
230+
static int init_bio_method(void)
231+
{
232+
/* Set up the BIO_METHOD we use for wrapping our own stream implementations */
233+
git_stream_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "git_stream");
234+
GITERR_CHECK_ALLOC(git_stream_bio_method);
235+
236+
BIO_meth_set_write(git_stream_bio_method, bio_write);
237+
BIO_meth_set_read(git_stream_bio_method, bio_read);
238+
BIO_meth_set_puts(git_stream_bio_method, bio_puts);
239+
BIO_meth_set_gets(git_stream_bio_method, bio_gets);
240+
BIO_meth_set_ctrl(git_stream_bio_method, bio_ctrl);
241+
BIO_meth_set_create(git_stream_bio_method, bio_create);
242+
BIO_meth_set_destroy(git_stream_bio_method, bio_destroy);
243+
244+
return 0;
245+
}
249246

250247
static int ssl_set_error(SSL *ssl, int error)
251248
{
@@ -466,27 +463,12 @@ int openssl_connect(git_stream *stream)
466463

467464
st->connected = true;
468465

469-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
470-
bio = BIO_new(&git_stream_bio_method);
471-
#else
472-
git_stream_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "git_stream");
473-
BIO_meth_set_write(git_stream_bio_method, bio_write);
474-
BIO_meth_set_read(git_stream_bio_method, bio_read);
475-
BIO_meth_set_puts(git_stream_bio_method, bio_puts);
476-
BIO_meth_set_gets(git_stream_bio_method, bio_gets);
477-
BIO_meth_set_ctrl(git_stream_bio_method, bio_ctrl);
478-
BIO_meth_set_create(git_stream_bio_method, bio_create);
479-
BIO_meth_set_destroy(git_stream_bio_method, bio_destroy);
480466
bio = BIO_new(git_stream_bio_method);
481-
#endif
482467
GITERR_CHECK_ALLOC(bio);
483-
#if OPENSSL_VERSION_NUMBER < 0x10100000L
484-
bio->ptr = st->io;
485-
#else
486-
BIO_set_data(bio, st->io);
487-
#endif
488468

469+
BIO_set_data(bio, st->io);
489470
SSL_set_bio(st->ssl, bio, bio);
471+
490472
/* specify the host in case SNI is needed */
491473
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
492474
SSL_set_tlsext_host_name(st->ssl, st->host);

src/openssl_stream.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,107 @@
77
#ifndef INCLUDE_openssl_stream_h__
88
#define INCLUDE_openssl_stream_h__
99

10+
#include <openssl/ssl.h>
11+
#include <openssl/err.h>
12+
#include <openssl/x509v3.h>
13+
#include <openssl/bio.h>
14+
1015
#include "git2/sys/stream.h"
1116

1217
extern int git_openssl_stream_global_init(void);
1318

1419
extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
1520

21+
/*
22+
* OpenSSL 1.1 made BIO opaque so we have to use functions to interact with it
23+
* which do not exist in previous versions. We define these inline functions so
24+
* we can program against the interface instead of littering the implementation
25+
* with ifdefs.
26+
*/
27+
# if OPENSSL_VERSION_NUMBER < 0x10100000L
28+
29+
GIT_INLINE(BIO_METHOD*) BIO_meth_new(int type, const char *name)
30+
{
31+
BIO_METHOD *meth = git__calloc(1, sizeof(BIO_METHOD));
32+
if (!meth) {
33+
return NULL;
34+
}
35+
36+
meth->type = type;
37+
meth->name = name;
38+
39+
return meth;
40+
}
41+
42+
GIT_INLINE(void) BIO_meth_free(BIO_METHOD *biom)
43+
{
44+
git__free(biom);
45+
}
46+
47+
GIT_INLINE(int) BIO_meth_set_write(BIO_METHOD *biom, int (*write) (BIO *, const char *, int))
48+
{
49+
biom->bwrite = write;
50+
return 1;
51+
}
52+
53+
GIT_INLINE(int) BIO_meth_set_read(BIO_METHOD *biom, int (*read) (BIO *, char *, int))
54+
{
55+
biom->bread = read;
56+
return 1;
57+
}
58+
59+
GIT_INLINE(int) BIO_meth_set_puts(BIO_METHOD *biom, int (*puts) (BIO *, const char *))
60+
{
61+
biom->bputs = puts;
62+
return 1;
63+
}
64+
65+
GIT_INLINE(int) BIO_meth_set_gets(BIO_METHOD *biom, int (*gets) (BIO *, char *, int))
66+
67+
{
68+
biom->bgets = gets;
69+
return 1;
70+
}
71+
72+
GIT_INLINE(int) BIO_meth_set_ctrl(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *))
73+
{
74+
biom->ctrl = ctrl;
75+
return 1;
76+
}
77+
78+
GIT_INLINE(int) BIO_meth_set_create(BIO_METHOD *biom, int (*create) (BIO *))
79+
{
80+
biom->create = create;
81+
return 1;
82+
}
83+
84+
GIT_INLINE(int) BIO_meth_set_destroy(BIO_METHOD *biom, int (*destroy) (BIO *))
85+
{
86+
biom->destroy = destroy;
87+
return 1;
88+
}
89+
90+
GIT_INLINE(int) BIO_get_new_index(void)
91+
{
92+
/* This exists as of 1.1 so before we'd just have 0 */
93+
return 0;
94+
}
95+
96+
GIT_INLINE(void) BIO_set_init(BIO *b, int init)
97+
{
98+
b->init = init;
99+
}
100+
101+
GIT_INLINE(void) BIO_set_data(BIO *a, void *ptr)
102+
{
103+
a->ptr = ptr;
104+
}
105+
106+
GIT_INLINE(void*) BIO_get_data(BIO *a)
107+
{
108+
return a->ptr;
109+
}
110+
111+
# endif
112+
16113
#endif

0 commit comments

Comments
 (0)