]>
Commit | Line | Data |
---|---|---|
c25aa7cd PP |
1 | /* |
2 | * Copyright (C) the libgit2 contributors. All rights reserved. | |
3 | * | |
4 | * This file is part of libgit2, distributed under the GNU GPL v2 with | |
5 | * a Linking Exception. For full terms see the included COPYING file. | |
6 | */ | |
7 | ||
8 | #include "streams/openssl.h" | |
9 | #include "streams/openssl_dynamic.h" | |
10 | ||
11 | #if defined(GIT_OPENSSL) && defined(GIT_OPENSSL_DYNAMIC) | |
12 | ||
13 | #include "runtime.h" | |
14 | ||
15 | #include <dlfcn.h> | |
16 | ||
17 | unsigned char *(*ASN1_STRING_data)(ASN1_STRING *x); | |
18 | const unsigned char *(*ASN1_STRING_get0_data)(const ASN1_STRING *x); | |
19 | int (*ASN1_STRING_length)(const ASN1_STRING *x); | |
20 | int (*ASN1_STRING_to_UTF8)(unsigned char **out, const ASN1_STRING *in); | |
21 | int (*ASN1_STRING_type)(const ASN1_STRING *x); | |
22 | ||
23 | void *(*BIO_get_data)(BIO *a); | |
24 | int (*BIO_get_new_index)(void); | |
25 | int (*OPENSSL_init_ssl)(uint64_t opts, const void *settings); | |
26 | void (*BIO_meth_free)(BIO_METHOD *biom); | |
27 | int (*BIO_meth_set_create)(BIO_METHOD *biom, int (*create) (BIO *)); | |
28 | int (*BIO_meth_set_ctrl)(BIO_METHOD *biom, long (*ctrl) (BIO *, int, long, void *)); | |
29 | int (*BIO_meth_set_destroy)(BIO_METHOD *biom, int (*destroy) (BIO *)); | |
30 | int (*BIO_meth_set_gets)(BIO_METHOD *biom, int (*gets) (BIO *, char *, int)); | |
31 | int (*BIO_meth_set_puts)(BIO_METHOD *biom, int (*puts) (BIO *, const char *)); | |
32 | int (*BIO_meth_set_read)(BIO_METHOD *biom, int (*read) (BIO *, char *, int)); | |
33 | int (*BIO_meth_set_write)(BIO_METHOD *biom, int (*write) (BIO *, const char *, int)); | |
34 | BIO_METHOD *(*BIO_meth_new)(int type, const char *name); | |
35 | BIO *(*BIO_new)(const BIO_METHOD *type); | |
36 | void (*BIO_set_data)(BIO *a, void *ptr); | |
37 | void (*BIO_set_init)(BIO *a, int init); | |
38 | ||
39 | void (*CRYPTO_free)(void *ptr, const char *file, int line); | |
40 | void *(*CRYPTO_malloc)(size_t num, const char *file, int line); | |
41 | int (*CRYPTO_num_locks)(void); | |
42 | void (*CRYPTO_set_locking_callback)(void (*func)(int mode, int type, const char *file, int line)); | |
43 | int (*CRYPTO_set_mem_functions)(void *(*m)(size_t bytes), void *(*r)(void *mem, size_t size), void (*f)(void *mem)); | |
44 | int (*CRYPTO_THREADID_set_callback)(void (*func)(CRYPTO_THREADID *id)); | |
45 | void (*CRYPTO_THREADID_set_numeric)(CRYPTO_THREADID *id, unsigned long val); | |
46 | ||
47 | char *(*ERR_error_string)(unsigned long e, char *buf); | |
48 | void (*ERR_error_string_n)(unsigned long e, char *buf, size_t len); | |
49 | unsigned long (*ERR_get_error)(void); | |
50 | ||
51 | int (*SSL_connect)(SSL *ssl); | |
52 | long (*SSL_ctrl)(SSL *ssl, int cmd, long arg, void *parg); | |
53 | void (*SSL_free)(SSL *ssl); | |
54 | int (*SSL_get_error)(SSL *ssl, int ret); | |
55 | X509 *(*SSL_get_peer_certificate)(const SSL *ssl); | |
56 | long (*SSL_get_verify_result)(const SSL *ssl); | |
57 | int (*SSL_library_init)(void); | |
58 | void (*SSL_load_error_strings)(void); | |
59 | SSL *(*SSL_new)(SSL_CTX *ctx); | |
60 | int (*SSL_read)(SSL *ssl, const void *buf, int num); | |
61 | void (*SSL_set_bio)(SSL *ssl, BIO *rbio, BIO *wbio); | |
62 | int (*SSL_shutdown)(SSL *ssl); | |
63 | int (*SSL_write)(SSL *ssl, const void *buf, int num); | |
64 | ||
65 | long (*SSL_CTX_ctrl)(SSL_CTX *ctx, int cmd, long larg, void *parg); | |
66 | void (*SSL_CTX_free)(SSL_CTX *ctx); | |
67 | SSL_CTX *(*SSL_CTX_new)(const SSL_METHOD *method); | |
68 | int (*SSL_CTX_set_cipher_list)(SSL_CTX *ctx, const char *str); | |
69 | int (*SSL_CTX_set_default_verify_paths)(SSL_CTX *ctx); | |
70 | long (*SSL_CTX_set_options)(SSL_CTX *ctx, long options); | |
71 | void (*SSL_CTX_set_verify)(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *)); | |
72 | int (*SSL_CTX_load_verify_locations)(SSL_CTX *ctx, const char *CAfile, const char *CApath); | |
73 | ||
74 | const SSL_METHOD *(*SSLv23_method)(void); | |
75 | const SSL_METHOD *(*TLS_method)(void); | |
76 | ||
77 | ASN1_STRING *(*X509_NAME_ENTRY_get_data)(const X509_NAME_ENTRY *ne); | |
78 | X509_NAME_ENTRY *(*X509_NAME_get_entry)(X509_NAME *name, int loc); | |
79 | int (*X509_NAME_get_index_by_NID)(X509_NAME *name, int nid, int lastpos); | |
80 | void (*X509_free)(X509 *a); | |
81 | void *(*X509_get_ext_d2i)(const X509 *x, int nid, int *crit, int *idx); | |
82 | X509_NAME *(*X509_get_subject_name)(const X509 *x); | |
83 | ||
84 | int (*i2d_X509)(X509 *a, unsigned char **ppout); | |
85 | ||
86 | int (*OPENSSL_sk_num)(const void *sk); | |
87 | void *(*OPENSSL_sk_value)(const void *sk, int i); | |
88 | void (*OPENSSL_sk_free)(void *sk); | |
89 | ||
90 | int (*sk_num)(const void *sk); | |
91 | void *(*sk_value)(const void *sk, int i); | |
92 | void (*sk_free)(void *sk); | |
93 | ||
94 | void *openssl_handle; | |
95 | ||
96 | GIT_INLINE(void *) openssl_sym(int *err, const char *name, bool required) | |
97 | { | |
98 | void *symbol; | |
99 | ||
100 | /* if we've seen an err, noop to retain it */ | |
101 | if (*err) | |
102 | return NULL; | |
103 | ||
104 | ||
105 | if ((symbol = dlsym(openssl_handle, name)) == NULL && required) { | |
106 | const char *msg = dlerror(); | |
107 | git_error_set(GIT_ERROR_SSL, "could not load ssl function '%s': %s", name, msg ? msg : "unknown error"); | |
108 | *err = -1; | |
109 | } | |
110 | ||
111 | return symbol; | |
112 | } | |
113 | ||
114 | static void dynamic_shutdown(void) | |
115 | { | |
116 | dlclose(openssl_handle); | |
117 | openssl_handle = NULL; | |
118 | } | |
119 | ||
120 | int git_openssl_stream_dynamic_init(void) | |
121 | { | |
122 | int err = 0; | |
123 | ||
124 | if ((openssl_handle = dlopen("libssl.so.1.1", RTLD_NOW)) == NULL && | |
125 | (openssl_handle = dlopen("libssl.1.1.dylib", RTLD_NOW)) == NULL && | |
126 | (openssl_handle = dlopen("libssl.so.1.0.0", RTLD_NOW)) == NULL && | |
127 | (openssl_handle = dlopen("libssl.1.0.0.dylib", RTLD_NOW)) == NULL && | |
128 | (openssl_handle = dlopen("libssl.so.10", RTLD_NOW)) == NULL) { | |
129 | git_error_set(GIT_ERROR_SSL, "could not load ssl libraries"); | |
130 | return -1; | |
131 | } | |
132 | ||
133 | ASN1_STRING_data = (unsigned char *(*)(ASN1_STRING *x))openssl_sym(&err, "ASN1_STRING_data", false); | |
134 | ASN1_STRING_get0_data = (const unsigned char *(*)(const ASN1_STRING *x))openssl_sym(&err, "ASN1_STRING_get0_data", false); | |
135 | ASN1_STRING_length = (int (*)(const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_length", true); | |
136 | ASN1_STRING_to_UTF8 = (int (*)(unsigned char **, const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_to_UTF8", true); | |
137 | ASN1_STRING_type = (int (*)(const ASN1_STRING *))openssl_sym(&err, "ASN1_STRING_type", true); | |
138 | ||
139 | BIO_get_data = (void *(*)(BIO *))openssl_sym(&err, "BIO_get_data", false); | |
140 | BIO_get_new_index = (int (*)(void))openssl_sym(&err, "BIO_get_new_index", false); | |
141 | BIO_meth_free = (void (*)(BIO_METHOD *))openssl_sym(&err, "BIO_meth_free", false); | |
142 | BIO_meth_new = (BIO_METHOD *(*)(int, const char *))openssl_sym(&err, "BIO_meth_new", false); | |
143 | BIO_meth_set_create = (int (*)(BIO_METHOD *, int (*)(BIO *)))openssl_sym(&err, "BIO_meth_set_create", false); | |
144 | BIO_meth_set_ctrl = (int (*)(BIO_METHOD *, long (*)(BIO *, int, long, void *)))openssl_sym(&err, "BIO_meth_set_ctrl", false); | |
145 | BIO_meth_set_destroy = (int (*)(BIO_METHOD *, int (*)(BIO *)))openssl_sym(&err, "BIO_meth_set_destroy", false); | |
146 | BIO_meth_set_gets = (int (*)(BIO_METHOD *, int (*)(BIO *, char *, int)))openssl_sym(&err, "BIO_meth_set_gets", false); | |
147 | BIO_meth_set_puts = (int (*)(BIO_METHOD *, int (*)(BIO *, const char *)))openssl_sym(&err, "BIO_meth_set_puts", false); | |
148 | BIO_meth_set_read = (int (*)(BIO_METHOD *, int (*)(BIO *, char *, int)))openssl_sym(&err, "BIO_meth_set_read", false); | |
149 | BIO_meth_set_write = (int (*)(BIO_METHOD *, int (*)(BIO *, const char *, int)))openssl_sym(&err, "BIO_meth_set_write", false); | |
150 | BIO_new = (BIO *(*)(const BIO_METHOD *))openssl_sym(&err, "BIO_new", true); | |
151 | BIO_set_data = (void (*)(BIO *a, void *))openssl_sym(&err, "BIO_set_data", false); | |
152 | BIO_set_init = (void (*)(BIO *a, int))openssl_sym(&err, "BIO_set_init", false); | |
153 | ||
154 | CRYPTO_free = (void (*)(void *, const char *, int))openssl_sym(&err, "CRYPTO_free", true); | |
155 | CRYPTO_malloc = (void *(*)(size_t, const char *, int))openssl_sym(&err, "CRYPTO_malloc", true); | |
156 | CRYPTO_num_locks = (int (*)(void))openssl_sym(&err, "CRYPTO_num_locks", false); | |
157 | CRYPTO_set_locking_callback = (void (*)(void (*)(int, int, const char *, int)))openssl_sym(&err, "CRYPTO_set_locking_callback", false); | |
158 | CRYPTO_set_mem_functions = (int (*)(void *(*)(size_t), void *(*)(void *, size_t), void (*f)(void *)))openssl_sym(&err, "CRYPTO_set_mem_functions", true); | |
159 | ||
160 | CRYPTO_THREADID_set_callback = (int (*)(void (*)(CRYPTO_THREADID *)))openssl_sym(&err, "CRYPTO_THREADID_set_callback", false); | |
161 | CRYPTO_THREADID_set_numeric = (void (*)(CRYPTO_THREADID *, unsigned long))openssl_sym(&err, "CRYPTO_THREADID_set_numeric", false); | |
162 | ||
163 | ERR_error_string = (char *(*)(unsigned long, char *))openssl_sym(&err, "ERR_error_string", true); | |
164 | ERR_error_string_n = (void (*)(unsigned long, char *, size_t))openssl_sym(&err, "ERR_error_string_n", true); | |
165 | ERR_get_error = (unsigned long (*)(void))openssl_sym(&err, "ERR_get_error", true); | |
166 | ||
167 | OPENSSL_init_ssl = (int (*)(uint64_t opts, const void *settings))openssl_sym(&err, "OPENSSL_init_ssl", false); | |
168 | OPENSSL_sk_num = (int (*)(const void *))openssl_sym(&err, "OPENSSL_sk_num", false); | |
169 | OPENSSL_sk_value = (void *(*)(const void *sk, int i))openssl_sym(&err, "OPENSSL_sk_value", false); | |
170 | OPENSSL_sk_free = (void (*)(void *))openssl_sym(&err, "OPENSSL_sk_free", false); | |
171 | ||
172 | sk_num = (int (*)(const void *))openssl_sym(&err, "sk_num", false); | |
173 | sk_value = (void *(*)(const void *sk, int i))openssl_sym(&err, "sk_value", false); | |
174 | sk_free = (void (*)(void *))openssl_sym(&err, "sk_free", false); | |
175 | ||
176 | SSL_connect = (int (*)(SSL *))openssl_sym(&err, "SSL_connect", true); | |
177 | SSL_ctrl = (long (*)(SSL *, int, long, void *))openssl_sym(&err, "SSL_ctrl", true); | |
178 | SSL_get_peer_certificate = (X509 *(*)(const SSL *))openssl_sym(&err, "SSL_get_peer_certificate", true); | |
179 | SSL_library_init = (int (*)(void))openssl_sym(&err, "SSL_library_init", false); | |
180 | SSL_free = (void (*)(SSL *))openssl_sym(&err, "SSL_free", true); | |
181 | SSL_get_error = (int (*)(SSL *, int))openssl_sym(&err, "SSL_get_error", true); | |
182 | SSL_get_verify_result = (long (*)(const SSL *ssl))openssl_sym(&err, "SSL_get_verify_result", true); | |
183 | SSL_load_error_strings = (void (*)(void))openssl_sym(&err, "SSL_load_error_strings", false); | |
184 | SSL_new = (SSL *(*)(SSL_CTX *))openssl_sym(&err, "SSL_new", true); | |
185 | SSL_read = (int (*)(SSL *, const void *, int))openssl_sym(&err, "SSL_read", true); | |
186 | SSL_set_bio = (void (*)(SSL *, BIO *, BIO *))openssl_sym(&err, "SSL_set_bio", true); | |
187 | SSL_shutdown = (int (*)(SSL *ssl))openssl_sym(&err, "SSL_shutdown", true); | |
188 | SSL_write = (int (*)(SSL *, const void *, int))openssl_sym(&err, "SSL_write", true); | |
189 | ||
190 | SSL_CTX_ctrl = (long (*)(SSL_CTX *, int, long, void *))openssl_sym(&err, "SSL_CTX_ctrl", true); | |
191 | SSL_CTX_free = (void (*)(SSL_CTX *))openssl_sym(&err, "SSL_CTX_free", true); | |
192 | SSL_CTX_new = (SSL_CTX *(*)(const SSL_METHOD *))openssl_sym(&err, "SSL_CTX_new", true); | |
193 | SSL_CTX_set_cipher_list = (int (*)(SSL_CTX *, const char *))openssl_sym(&err, "SSL_CTX_set_cipher_list", true); | |
194 | SSL_CTX_set_default_verify_paths = (int (*)(SSL_CTX *ctx))openssl_sym(&err, "SSL_CTX_set_default_verify_paths", true); | |
195 | SSL_CTX_set_options = (long (*)(SSL_CTX *, long))openssl_sym(&err, "SSL_CTX_set_options", false); | |
196 | SSL_CTX_set_verify = (void (*)(SSL_CTX *, int, int (*)(int, X509_STORE_CTX *)))openssl_sym(&err, "SSL_CTX_set_verify", true); | |
197 | SSL_CTX_load_verify_locations = (int (*)(SSL_CTX *, const char *, const char *))openssl_sym(&err, "SSL_CTX_load_verify_locations", true); | |
198 | ||
199 | SSLv23_method = (const SSL_METHOD *(*)(void))openssl_sym(&err, "SSLv23_method", false); | |
200 | TLS_method = (const SSL_METHOD *(*)(void))openssl_sym(&err, "TLS_method", false); | |
201 | ||
202 | X509_NAME_ENTRY_get_data = (ASN1_STRING *(*)(const X509_NAME_ENTRY *))openssl_sym(&err, "X509_NAME_ENTRY_get_data", true); | |
203 | X509_NAME_get_entry = (X509_NAME_ENTRY *(*)(X509_NAME *, int))openssl_sym(&err, "X509_NAME_get_entry", true); | |
204 | X509_NAME_get_index_by_NID = (int (*)(X509_NAME *, int, int))openssl_sym(&err, "X509_NAME_get_index_by_NID", true); | |
205 | X509_free = (void (*)(X509 *))openssl_sym(&err, "X509_free", true); | |
206 | X509_get_ext_d2i = (void *(*)(const X509 *x, int nid, int *crit, int *idx))openssl_sym(&err, "X509_get_ext_d2i", true); | |
207 | X509_get_subject_name = (X509_NAME *(*)(const X509 *))openssl_sym(&err, "X509_get_subject_name", true); | |
208 | ||
209 | i2d_X509 = (int (*)(X509 *a, unsigned char **ppout))openssl_sym(&err, "i2d_X509", true); | |
210 | ||
211 | if (err) | |
212 | goto on_error; | |
213 | ||
214 | /* Add legacy functionality */ | |
215 | if (!OPENSSL_init_ssl) { | |
216 | OPENSSL_init_ssl = OPENSSL_init_ssl__legacy; | |
217 | ||
218 | if (!SSL_library_init || | |
219 | !SSL_load_error_strings || | |
220 | !CRYPTO_num_locks || | |
221 | !CRYPTO_set_locking_callback || | |
222 | !CRYPTO_THREADID_set_callback || | |
223 | !CRYPTO_THREADID_set_numeric) { | |
224 | git_error_set(GIT_ERROR_SSL, "could not load legacy openssl initialization functions"); | |
225 | goto on_error; | |
226 | } | |
227 | } | |
228 | ||
229 | if (!SSL_CTX_set_options) | |
230 | SSL_CTX_set_options = SSL_CTX_set_options__legacy; | |
231 | ||
232 | if (TLS_method) | |
233 | SSLv23_method = TLS_method; | |
234 | ||
235 | if (!BIO_meth_new) { | |
236 | BIO_meth_new = BIO_meth_new__legacy; | |
237 | BIO_meth_new = BIO_meth_new__legacy; | |
238 | BIO_meth_free = BIO_meth_free__legacy; | |
239 | BIO_meth_set_write = BIO_meth_set_write__legacy; | |
240 | BIO_meth_set_read = BIO_meth_set_read__legacy; | |
241 | BIO_meth_set_puts = BIO_meth_set_puts__legacy; | |
242 | BIO_meth_set_gets = BIO_meth_set_gets__legacy; | |
243 | BIO_meth_set_ctrl = BIO_meth_set_ctrl__legacy; | |
244 | BIO_meth_set_create = BIO_meth_set_create__legacy; | |
245 | BIO_meth_set_destroy = BIO_meth_set_destroy__legacy; | |
246 | BIO_get_new_index = BIO_get_new_index__legacy; | |
247 | BIO_set_data = BIO_set_data__legacy; | |
248 | BIO_set_init = BIO_set_init__legacy; | |
249 | BIO_get_data = BIO_get_data__legacy; | |
250 | } | |
251 | ||
252 | if (!ASN1_STRING_get0_data) { | |
253 | if (!ASN1_STRING_data) { | |
254 | git_error_set(GIT_ERROR_SSL, "could not load legacy openssl string function"); | |
255 | goto on_error; | |
256 | } | |
257 | ||
258 | ASN1_STRING_get0_data = ASN1_STRING_get0_data__legacy; | |
259 | } | |
260 | ||
261 | if ((!OPENSSL_sk_num && !sk_num) || | |
262 | (!OPENSSL_sk_value && !sk_value) || | |
263 | (!OPENSSL_sk_free && !sk_free)) { | |
264 | git_error_set(GIT_ERROR_SSL, "could not load legacy openssl stack functions"); | |
265 | goto on_error; | |
266 | } | |
267 | ||
268 | if (git_runtime_shutdown_register(dynamic_shutdown) != 0) | |
269 | goto on_error; | |
270 | ||
271 | return 0; | |
272 | ||
273 | on_error: | |
274 | dlclose(openssl_handle); | |
275 | return -1; | |
276 | } | |
277 | ||
278 | ||
279 | int sk_GENERAL_NAME_num(const GENERAL_NAME *sk) | |
280 | { | |
281 | if (OPENSSL_sk_num) | |
282 | return OPENSSL_sk_num(sk); | |
283 | else if (sk_num) | |
284 | return sk_num(sk); | |
285 | ||
286 | GIT_ASSERT_WITH_RETVAL(false, 0); | |
287 | return 0; | |
288 | } | |
289 | ||
290 | GENERAL_NAME *sk_GENERAL_NAME_value(const GENERAL_NAME *sk, int i) | |
291 | { | |
292 | if (OPENSSL_sk_value) | |
293 | return OPENSSL_sk_value(sk, i); | |
294 | else if (sk_value) | |
295 | return sk_value(sk, i); | |
296 | ||
297 | GIT_ASSERT_WITH_RETVAL(false, NULL); | |
298 | return NULL; | |
299 | } | |
300 | ||
301 | void GENERAL_NAMES_free(GENERAL_NAME *sk) | |
302 | { | |
303 | if (OPENSSL_sk_free) | |
304 | OPENSSL_sk_free(sk); | |
305 | else if (sk_free) | |
306 | sk_free(sk); | |
307 | } | |
308 | ||
309 | #endif /* GIT_OPENSSL && GIT_OPENSSL_DYNAMIC */ |