Skip to content

Commit 7175222

Browse files
authored
Merge pull request #3960 from ignatenkobrain/openssl-1.1.0
add support for OpenSSL 1.1.0 for BIO filter
2 parents d2451fe + 3b832a0 commit 7175222

File tree

2 files changed

+150
-25
lines changed

2 files changed

+150
-25
lines changed

src/openssl_stream.c

Lines changed: 44 additions & 25 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,10 +172,8 @@ int git_openssl_set_locking(void)
156172

157173
static int bio_create(BIO *b)
158174
{
159-
b->init = 1;
160-
b->num = 0;
161-
b->ptr = NULL;
162-
b->flags = 0;
175+
BIO_set_init(b, 1);
176+
BIO_set_data(b, NULL);
163177

164178
return 1;
165179
}
@@ -169,23 +183,22 @@ static int bio_destroy(BIO *b)
169183
if (!b)
170184
return 0;
171185

172-
b->init = 0;
173-
b->num = 0;
174-
b->ptr = NULL;
175-
b->flags = 0;
186+
BIO_set_data(b, NULL);
176187

177188
return 1;
178189
}
179190

180191
static int bio_read(BIO *b, char *buf, int len)
181192
{
182-
git_stream *io = (git_stream *) b->ptr;
193+
git_stream *io = (git_stream *) BIO_get_data(b);
194+
183195
return (int) git_stream_read(io, buf, len);
184196
}
185197

186198
static int bio_write(BIO *b, const char *buf, int len)
187199
{
188-
git_stream *io = (git_stream *) b->ptr;
200+
git_stream *io = (git_stream *) BIO_get_data(b);
201+
189202
return (int) git_stream_write(io, buf, len, 0);
190203
}
191204

@@ -214,17 +227,22 @@ static int bio_puts(BIO *b, const char *str)
214227
return bio_write(b, str, strlen(str));
215228
}
216229

217-
static BIO_METHOD git_stream_bio_method = {
218-
BIO_TYPE_SOURCE_SINK,
219-
"git_stream",
220-
bio_write,
221-
bio_read,
222-
bio_puts,
223-
bio_gets,
224-
bio_ctrl,
225-
bio_create,
226-
bio_destroy
227-
};
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+
}
228246

229247
static int ssl_set_error(SSL *ssl, int error)
230248
{
@@ -339,7 +357,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
339357
num = sk_GENERAL_NAME_num(alts);
340358
for (i = 0; i < num && matched != 1; i++) {
341359
const GENERAL_NAME *gn = sk_GENERAL_NAME_value(alts, i);
342-
const char *name = (char *) ASN1_STRING_data(gn->d.ia5);
360+
const char *name = (char *) ASN1_STRING_get0_data(gn->d.ia5);
343361
size_t namelen = (size_t) ASN1_STRING_length(gn->d.ia5);
344362

345363
/* Skip any names of a type we're not looking for */
@@ -394,7 +412,7 @@ static int verify_server_cert(SSL *ssl, const char *host)
394412
if (size > 0) {
395413
peer_cn = OPENSSL_malloc(size + 1);
396414
GITERR_CHECK_ALLOC(peer_cn);
397-
memcpy(peer_cn, ASN1_STRING_data(str), size);
415+
memcpy(peer_cn, ASN1_STRING_get0_data(str), size);
398416
peer_cn[size] = '\0';
399417
} else {
400418
goto cert_fail_name;
@@ -445,11 +463,12 @@ int openssl_connect(git_stream *stream)
445463

446464
st->connected = true;
447465

448-
bio = BIO_new(&git_stream_bio_method);
466+
bio = BIO_new(git_stream_bio_method);
449467
GITERR_CHECK_ALLOC(bio);
450-
bio->ptr = st->io;
451468

469+
BIO_set_data(bio, st->io);
452470
SSL_set_bio(st->ssl, bio, bio);
471+
453472
/* specify the host in case SNI is needed */
454473
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
455474
SSL_set_tlsext_host_name(st->ssl, st->host);

src/openssl_stream.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,110 @@ extern int git_openssl_stream_global_init(void);
1313

1414
extern int git_openssl_stream_new(git_stream **out, const char *host, const char *port);
1515

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

0 commit comments

Comments
 (0)