1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
|
From c32f3d365a0848eb6b3350ec521fcd4d1d098295 Mon Sep 17 00:00:00 2001
From: Eneas U de Queiroz <cote2004-github@yahoo.com>
Date: Sun, 2 Sep 2018 19:01:28 -0300
Subject: [PATCH] openssl 1.1 runtime-loading support, misc changes
Added openssl 1.1.x support for runtime-loading.
Some of the calls were renamed in openssl 1.1.0, so the table that
handles runtime loading needed some adjustments to support them.
Added option to prefer ChaCha20-Poly1305 over AES-256-GCM.
This is important especially for SoC systems where CPU does not have
AES-NI instructions.
Added ECDSA suites to the ciphersuite ordering list.
Added version to default soname when loading libssl & libcrypto. The
unversioned lib{ssl,crypto}.so are not present in some distros, while the
versioned file always have to be there. Besides, when compiled with
openssl 1.0.x, shellinabox will not run with 1.1.x and vice-versa, and
the system may have more than one version installed.
Adding the version to the file avoids picking out the wrong one.
Allow the name to be defined at compile-time as well.
Allowed automatic EC curve choice for openssl >= 1.1.0, instead of
always setting P-256.
Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
---
configure.ac | 11 +++++++++
libhttp/ssl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++---
libhttp/ssl.h | 34 ++++++++++++++++++++++++++++
3 files changed, 104 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index 05ab1bb..5fa918d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -138,6 +138,17 @@ AC_ARG_ENABLE(runtime-loading,
these libraries into the binary, thus making them a
hard dependency, then disable runtime-loading.])
+dnl This changes the order of the top ciphersuites
+AC_ARG_ENABLE(prefer-chacha,
+ [ --enable-prefer-chacha Prefer ChaCha20-Poly1305 ciphersuites over
+ AES256-GCM. For processors without AES-NI or
+ similar capabilities, ChaCha20-Poly1305 is 3 times
+ faster than AES, with an equivalent strength.])
+if test "x$enable_prefer_chacha" == xyes; then
+ AC_DEFINE(SHELLINABOX_USE_CHACHA_FIRST, 1,
+ Set if you want to prefer Chacha20-Poly1305 over AES-GCM)
+fi
+
dnl This is feature is not suported in some standard C libs. So users can use
dnl this switch to avoid compile and runtime problems. Note that utmp must
dnl disabled on systems with musl libc.
diff --git a/libhttp/ssl.c b/libhttp/ssl.c
index 6d09035..609d4e5 100644
--- a/libhttp/ssl.c
+++ b/libhttp/ssl.c
@@ -117,6 +117,9 @@ SSL_CTX * (*SSL_CTX_new)(SSL_METHOD *);
int (*SSL_CTX_set_cipher_list)(SSL_CTX *, const char *);
void (*SSL_CTX_set_info_callback)(SSL_CTX *,
void (*)(const SSL *, int, int));
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+unsigned long (*SSL_CTX_set_options)(SSL_CTX *, unsigned long);
+#endif
int (*SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
int (*SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
const unsigned char *, long);
@@ -130,7 +133,9 @@ void * (*SSL_get_ex_data)(const SSL *, int);
BIO * (*SSL_get_rbio)(const SSL *);
const char * (*SSL_get_servername)(const SSL *, int);
BIO * (*SSL_get_wbio)(const SSL *);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
int (*SSL_library_init)(void);
+#endif
SSL * (*SSL_new)(SSL_CTX *);
int (*SSL_read)(SSL *, void *, int);
SSL_CTX * (*SSL_set_SSL_CTX)(SSL *, SSL_CTX *);
@@ -139,10 +144,16 @@ void (*SSL_set_bio)(SSL *, BIO *, BIO *);
int (*SSL_set_ex_data)(SSL *, int, void *);
int (*SSL_shutdown)(SSL *);
int (*SSL_write)(SSL *, const void *, int);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_METHOD * (*SSLv23_server_method)(void);
+#else
+SSL_METHOD * (*TLS_server_method)(void);
+#endif
X509 * (*d2i_X509)(X509 **px, const unsigned char **in, int len);
void (*X509_free)(X509 *a);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
void (*x_sk_zero)(void *st);
+#endif
void * (*x_SSL_COMP_get_compression_methods)(void);
#endif
@@ -208,7 +219,7 @@ static int maybeLoadCrypto(void) {
// The feature is currently disabled.
const char* path_libcrypto = NULL; // getenv ("SHELLINABOX_LIBCRYPTO_SO");
if (path_libcrypto == NULL)
- path_libcrypto = "libcrypto.so";
+ path_libcrypto = DEFAULT_LIBCRYPTO_SO;
if (!crypto++) {
#ifdef RTLD_NOLOAD
@@ -267,8 +278,8 @@ static void loadSSL(void) {
// The feature is currently disabled.
const char* path_libssl = NULL; // = getenv ("SHELLINABOX_LIBSSL_SO");
if (path_libssl == NULL)
- path_libssl = "libssl.so";
- check(!SSL_library_init);
+ path_libssl = DEFAULT_LIBSSL_SO;
+ check(!SSL_CTX_new);
struct {
union {
void *avoid_gcc_warning_about_type_punning;
@@ -299,6 +310,9 @@ static void loadSSL(void) {
{ { &SSL_CTX_new }, "SSL_CTX_new" },
{ { &SSL_CTX_set_cipher_list }, "SSL_CTX_set_cipher_list" },
{ { &SSL_CTX_set_info_callback }, "SSL_CTX_set_info_callback" },
+#if OPENSSL_VERSION_NUMBER > 0x10100000L
+ { { &SSL_CTX_set_options }, "SSL_CTX_set_options" },
+#endif
{ { &SSL_CTX_use_PrivateKey_file }, "SSL_CTX_use_PrivateKey_file" },
{ { &SSL_CTX_use_PrivateKey_ASN1 }, "SSL_CTX_use_PrivateKey_ASN1" },
{ { &SSL_CTX_use_certificate_file },"SSL_CTX_use_certificate_file"},
@@ -312,7 +326,9 @@ static void loadSSL(void) {
{ { &SSL_get_servername }, "SSL_get_servername" },
#endif
{ { &SSL_get_wbio }, "SSL_get_wbio" },
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
{ { &SSL_library_init }, "SSL_library_init" },
+#endif
{ { &SSL_new }, "SSL_new" },
{ { &SSL_read }, "SSL_read" },
#ifdef HAVE_TLSEXT
@@ -323,10 +339,16 @@ static void loadSSL(void) {
{ { &SSL_set_ex_data }, "SSL_set_ex_data" },
{ { &SSL_shutdown }, "SSL_shutdown" },
{ { &SSL_write }, "SSL_write" },
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
{ { &SSLv23_server_method }, "SSLv23_server_method" },
+#else
+ { { &TLS_server_method }, "TLS_server_method" },
+#endif
{ { &d2i_X509 }, "d2i_X509" },
{ { &X509_free }, "X509_free" },
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
{ { &x_sk_zero }, "sk_zero" }
+#endif
};
for (unsigned i = 0; i < sizeof(symbols)/sizeof(symbols[0]); i++) {
if (!(*symbols[i].var = loadSymbol(path_libssl, symbols[i].fn))) {
@@ -343,7 +365,9 @@ static void loadSSL(void) {
// ends
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_library_init();
+#endif
dcheck(!ERR_peek_error());
debug("[ssl] Loaded SSL suppport...");
}
@@ -351,7 +375,11 @@ static void loadSSL(void) {
int serverSupportsSSL(void) {
#if defined(HAVE_OPENSSL) && !defined(HAVE_DLOPEN)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
return SSL_library_init();
+#else
+ return 1;
+#endif
#else
#if defined(HAVE_OPENSSL)
// We want to call loadSSL() exactly once. For single-threaded applications,
@@ -372,7 +400,11 @@ int serverSupportsSSL(void) {
loadSSL();
}
}
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
return !!SSL_library_init;
+#else
+ return 1;
+#endif
#else
return 0;
#endif
@@ -623,7 +655,11 @@ static void sslInfoCallback(const SSL *sslHndl, int type, int val) {
static SSL_CTX *sslMakeContext(void) {
SSL_CTX *context;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
check(context = SSL_CTX_new(SSLv23_server_method()));
+#else
+ check(context = SSL_CTX_new(TLS_server_method()));
+#endif
long options = SSL_OP_ALL;
options |= SSL_OP_NO_SSLv2;
@@ -641,6 +677,7 @@ static SSL_CTX *sslMakeContext(void) {
// Set default SSL options.
SSL_CTX_set_options(context, options);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
// Workaround for SSL_OP_NO_COMPRESSION with older OpenSSL versions.
#ifdef HAVE_DLOPEN
if (SSL_COMP_get_compression_methods) {
@@ -648,6 +685,7 @@ static SSL_CTX *sslMakeContext(void) {
}
#elif OPENSSL_VERSION_NUMBER >= 0x00908000L
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
+#endif
#endif
// For Perfect Forward Secrecy (PFS) support we need to enable some additional
@@ -657,21 +695,39 @@ static SSL_CTX *sslMakeContext(void) {
SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L /* openssl 1.1 does this automatically */
EC_KEY *ecKey;
check(ecKey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
SSL_CTX_set_tmp_ecdh(context, ecKey);
EC_KEY_free(ecKey);
+#endif
debug("[ssl] Support for PFS enabled...");
#endif
check(SSL_CTX_set_cipher_list(context,
+#ifdef SHELLINABOX_USE_CHACHA_FIRST
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES256-GCM-SHA384:"
"ECDHE-RSA-AES256-GCM-SHA384:"
+#else
+ "ECDHE-ECDSA-AES256-GCM-SHA384:"
+ "ECDHE-RSA-AES256-GCM-SHA384:"
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+#endif
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
"ECDHE-RSA-AES128-GCM-SHA256:"
+ "ECDHE-ECDSA-AES256-SHA384:"
"ECDHE-RSA-AES256-SHA384:"
+ "ECDHE-ECDSA-AES128-SHA256:"
"ECDHE-RSA-AES128-SHA256:"
+ "ECDHE-ECDSA-AES256-SHA:"
"ECDHE-RSA-AES256-SHA:"
+ "ECDHE-ECDSA-AES128-SHA:"
"ECDHE-RSA-AES128-SHA:"
+ "ECDHE-ECDSA-DES-CBC3-SHA:"
"ECDHE-RSA-DES-CBC3-SHA:"
"HIGH:MEDIUM:!RC4:!aNULL:!MD5"));
diff --git a/libhttp/ssl.h b/libhttp/ssl.h
index 9fbac63..7c3a23d 100644
--- a/libhttp/ssl.h
+++ b/libhttp/ssl.h
@@ -57,6 +57,7 @@
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
+#include <openssl/safestack.h>
#else
#undef HAVE_OPENSSL
typedef struct BIO BIO;
@@ -77,6 +78,17 @@ typedef struct X509 X509;
#endif
#if defined(HAVE_DLOPEN)
+#if !defined(DEFAULT_LIBCRYPTO_SO) || !defined(DEFAULT_LIBSSL_SO)
+#undef DEFAULT_LIBCRYPTO_SO
+#undef DEFAULT_LIBSSL_SO
+#ifdef SHLIB_VERSION_NUMBER
+#define DEFAULT_LIBCRYPTO_SO "libcrypto.so." SHLIB_VERSION_NUMBER
+#define DEFAULT_LIBSSL_SO "libssl.so." SHLIB_VERSION_NUMBER
+#else
+#define DEFAULT_LIBCRYPTO_SO "libcrypto.so"
+#define DEFAULT_LIBSSL_SO "libssl.so"
+#endif
+#endif
extern long (*x_BIO_ctrl)(BIO *, int, long, void *);
extern BIO_METHOD *(*x_BIO_f_buffer)(void);
extern void (*x_BIO_free_all)(BIO *);
@@ -99,6 +111,9 @@ extern SSL_CTX*(*x_SSL_CTX_new)(SSL_METHOD *);
extern int (*x_SSL_CTX_set_cipher_list)(SSL_CTX *, const char *);
extern void (*x_SSL_CTX_set_info_callback)(SSL_CTX *,
void (*)(const SSL *, int, int));
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+extern unsigned long (*x_SSL_CTX_set_options)(SSL_CTX *, unsigned long);
+#endif
extern int (*x_SSL_CTX_use_PrivateKey_file)(SSL_CTX *, const char *, int);
extern int (*x_SSL_CTX_use_PrivateKey_ASN1)(int, SSL_CTX *,
const unsigned char *, long);
@@ -112,7 +127,9 @@ extern void *(*x_SSL_get_ex_data)(const SSL *, int);
extern BIO *(*x_SSL_get_rbio)(const SSL *);
extern const char *(*x_SSL_get_servername)(const SSL *, int);
extern BIO *(*x_SSL_get_wbio)(const SSL *);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
extern int (*x_SSL_library_init)(void);
+#endif
extern SSL *(*x_SSL_new)(SSL_CTX *);
extern int (*x_SSL_read)(SSL *, void *, int);
extern SSL_CTX*(*x_SSL_set_SSL_CTX)(SSL *, SSL_CTX *);
@@ -121,10 +138,16 @@ extern void (*x_SSL_set_bio)(SSL *, BIO *, BIO *);
extern int (*x_SSL_set_ex_data)(SSL *, int, void *);
extern int (*x_SSL_shutdown)(SSL *);
extern int (*x_SSL_write)(SSL *, const void *, int);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
extern SSL_METHOD *(*x_SSLv23_server_method)(void);
+#else
+extern SSL_METHOD *(*x_TLS_server_method)(void);
+#endif
extern X509 * (*x_d2i_X509)(X509 **px, const unsigned char **in, int len);
extern void (*x_X509_free)(X509 *a);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
extern void (*x_sk_zero)(void *st);
+#endif
extern void *(*x_SSL_COMP_get_compression_methods)(void);
#define BIO_ctrl x_BIO_ctrl
@@ -146,6 +169,9 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void);
#define SSL_CTX_new x_SSL_CTX_new
#define SSL_CTX_set_cipher_list x_SSL_CTX_set_cipher_list
#define SSL_CTX_set_info_callback x_SSL_CTX_set_info_callback
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define SSL_CTX_set_options x_SSL_CTX_set_options
+#endif
#define SSL_CTX_use_PrivateKey_file x_SSL_CTX_use_PrivateKey_file
#define SSL_CTX_use_PrivateKey_ASN1 x_SSL_CTX_use_PrivateKey_ASN1
#define SSL_CTX_use_certificate_file x_SSL_CTX_use_certificate_file
@@ -157,7 +183,9 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void);
#define SSL_get_rbio x_SSL_get_rbio
#define SSL_get_servername x_SSL_get_servername
#define SSL_get_wbio x_SSL_get_wbio
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define SSL_library_init x_SSL_library_init
+#endif
#define SSL_new x_SSL_new
#define SSL_read x_SSL_read
#define SSL_set_SSL_CTX x_SSL_set_SSL_CTX
@@ -166,10 +194,16 @@ extern void *(*x_SSL_COMP_get_compression_methods)(void);
#define SSL_set_ex_data x_SSL_set_ex_data
#define SSL_shutdown x_SSL_shutdown
#define SSL_write x_SSL_write
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define SSLv23_server_method x_SSLv23_server_method
+#else
+#define TLS_server_method x_TLS_server_method
+#endif
#define d2i_X509 x_d2i_X509
#define X509_free x_X509_free
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
#define sk_zero x_sk_zero
+#endif
#define SSL_COMP_get_compression_methods x_SSL_COMP_get_compression_methods
#undef BIO_set_buffer_read_data
|