blob: 6f5582627f65d7546f63782f3c473209b85ce274 [file] [log] [blame]
Andy Greenc57037a2014-04-03 10:17:00 +08001/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301 USA
20 */
21
22#include "private-libwebsockets.h"
Alexander Bruinesc3bcb892015-08-08 18:54:49 +020023#ifndef USE_WOLFSSL
Joakim Soderberg1b97ec22014-11-24 16:03:19 +010024 #include <openssl/err.h>
Alexander Bruinesc3bcb892015-08-08 18:54:49 +020025#endif
Andy Greenc57037a2014-04-03 10:17:00 +080026
27int openssl_websocket_private_data_index;
28
Andy Green50000a12014-11-18 07:53:20 +080029static int lws_context_init_ssl_pem_passwd_cb(char * buf, int size, int rwflag, void *userdata)
30{
31 struct lws_context_creation_info * info = (struct lws_context_creation_info *)userdata;
32
33 strncpy(buf, info->ssl_private_key_password, size);
34 buf[size - 1] = '\0';
35
36 return strlen(buf);
37}
38
Andy Green4076a2c2014-11-20 12:10:40 +080039static void lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx,
Andy Green50000a12014-11-18 07:53:20 +080040 struct lws_context_creation_info *info)
41{
42 if (!info->ssl_private_key_password)
43 return;
44 /*
45 * password provided, set ssl callback and user data
46 * for checking password which will be trigered during
47 * SSL_CTX_use_PrivateKey_file function
48 */
Andy Green4076a2c2014-11-20 12:10:40 +080049 SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info);
50 SSL_CTX_set_default_passwd_cb(ssl_ctx,
Andy Green50000a12014-11-18 07:53:20 +080051 lws_context_init_ssl_pem_passwd_cb);
52}
53
Andy Green70b543f2014-11-26 14:29:03 +080054#ifndef LWS_NO_SERVER
55static int
56OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
57{
58 SSL *ssl;
59 int n;
Andy Green4b85c1d2015-12-04 11:08:32 +080060 struct lws_context *context;
Andy Green70b543f2014-11-26 14:29:03 +080061
62 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
63 SSL_get_ex_data_X509_STORE_CTX_idx());
64
65 /*
66 * !!! nasty openssl requires the index to come as a library-scope
67 * static
68 */
69 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
70
71 n = context->protocols[0].callback(NULL, NULL,
72 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
73 x509_ctx, ssl, preverify_ok);
74
75 /* convert return code from 0 = OK to 1 = OK */
76 return !n;
77}
78
Andy Greenc57037a2014-04-03 10:17:00 +080079LWS_VISIBLE int
80lws_context_init_server_ssl(struct lws_context_creation_info *info,
Andy Green4b85c1d2015-12-04 11:08:32 +080081 struct lws_context *context)
Andy Greenc57037a2014-04-03 10:17:00 +080082{
83 SSL_METHOD *method;
84 int error;
85 int n;
86
Andy Green2eedea92014-04-03 14:33:48 +080087 if (info->port != CONTEXT_PORT_NO_LISTEN) {
88
Octav Zlatiorcf518962014-12-15 16:29:15 +010089 context->use_ssl = info->ssl_cert_filepath != NULL;
90
Alexander Bruinesc3bcb892015-08-08 18:54:49 +020091#ifdef USE_WOLFSSL
ABruines80a70682015-08-09 22:56:32 +020092#ifdef USE_OLD_CYASSL
93 lwsl_notice(" Compiled with CyaSSL support\n");
94#else
95 lwsl_notice(" Compiled with wolfSSL support\n");
96#endif
Andy Green2eedea92014-04-03 14:33:48 +080097#else
98 lwsl_notice(" Compiled with OpenSSL support\n");
99#endif
100
101 if (info->ssl_cipher_list)
102 lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list);
103
104 if (context->use_ssl)
105 lwsl_notice(" Using SSL mode\n");
106 else
107 lwsl_notice(" Using non-SSL mode\n");
108 }
109
Andy Greenc57037a2014-04-03 10:17:00 +0800110 /* basic openssl init */
111
112 SSL_library_init();
113
114 OpenSSL_add_all_algorithms();
115 SSL_load_error_strings();
116
117 openssl_websocket_private_data_index =
118 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
119
120 /*
121 * Firefox insists on SSLv23 not SSLv3
122 * Konq disables SSLv2 by default now, SSLv23 works
Roger A. Lightd893d962014-06-03 01:35:00 +0100123 *
124 * SSLv23_server_method() is the openssl method for "allow all TLS
125 * versions", compared to e.g. TLSv1_2_server_method() which only allows
126 * tlsv1.2. Unwanted versions must be disabled using SSL_CTX_set_options()
Andy Greenc57037a2014-04-03 10:17:00 +0800127 */
128
129 method = (SSL_METHOD *)SSLv23_server_method();
130 if (!method) {
131 error = ERR_get_error();
132 lwsl_err("problem creating ssl method %lu: %s\n",
133 error, ERR_error_string(error,
134 (char *)context->service_buffer));
135 return 1;
136 }
137 context->ssl_ctx = SSL_CTX_new(method); /* create context */
138 if (!context->ssl_ctx) {
139 error = ERR_get_error();
140 lwsl_err("problem creating ssl context %lu: %s\n",
141 error, ERR_error_string(error,
142 (char *)context->service_buffer));
143 return 1;
144 }
145
Roger A. Lightd893d962014-06-03 01:35:00 +0100146 /* Disable SSLv2 and SSLv3 */
147 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
Andy Greenc57037a2014-04-03 10:17:00 +0800148#ifdef SSL_OP_NO_COMPRESSION
149 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
150#endif
151 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
152 if (info->ssl_cipher_list)
153 SSL_CTX_set_cipher_list(context->ssl_ctx,
154 info->ssl_cipher_list);
155
156 /* as a server, are we requiring clients to identify themselves? */
157
158 if (info->options &
159 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
Andy Greena739f752015-10-15 09:00:31 +0800160
Andy Green6d59f592015-10-15 09:12:58 +0800161 int verify_options = SSL_VERIFY_PEER;
162
163 if (!(info->options & LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
164 verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
165
Andy Greena739f752015-10-15 09:00:31 +0800166 SSL_CTX_set_session_id_context(context->ssl_ctx,
167 (unsigned char *)context, sizeof(void *));
Andy Greenc57037a2014-04-03 10:17:00 +0800168
169 /* absolutely require the client cert */
170
171 SSL_CTX_set_verify(context->ssl_ctx,
Andy Green6d59f592015-10-15 09:12:58 +0800172 verify_options, OpenSSL_verify_callback);
Andy Greenc57037a2014-04-03 10:17:00 +0800173
174 /*
175 * give user code a chance to load certs into the server
176 * allowing it to verify incoming client certs
177 */
178
179 context->protocols[0].callback(context, NULL,
180 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
181 context->ssl_ctx, NULL, 0);
182 }
183
184 if (info->options & LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT) {
185 /* Normally SSL listener rejects non-ssl, optionally allow */
186 context->allow_non_ssl_on_ssl_port = 1;
187 }
188
189 if (context->use_ssl) {
190
191 /* openssl init for server sockets */
192
193 /* set the local certificate from CertFile */
194 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
195 info->ssl_cert_filepath);
196 if (n != 1) {
197 error = ERR_get_error();
198 lwsl_err("problem getting cert '%s' %lu: %s\n",
199 info->ssl_cert_filepath,
200 error,
201 ERR_error_string(error,
202 (char *)context->service_buffer));
203 return 1;
204 }
Andy Green4076a2c2014-11-20 12:10:40 +0800205 lws_ssl_bind_passphrase(context->ssl_ctx, info);
Octav Zlatiorcf518962014-12-15 16:29:15 +0100206
207 if (info->ssl_private_key_filepath != NULL) {
208 /* set the private key from KeyFile */
209 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
210 info->ssl_private_key_filepath,
Andy Greenc57037a2014-04-03 10:17:00 +0800211 SSL_FILETYPE_PEM) != 1) {
Octav Zlatiorcf518962014-12-15 16:29:15 +0100212 error = ERR_get_error();
213 lwsl_err("ssl problem getting key '%s' %lu: %s\n",
214 info->ssl_private_key_filepath,
215 error,
216 ERR_error_string(error,
217 (char *)context->service_buffer));
218 return 1;
219 }
Andy Greenc57037a2014-04-03 10:17:00 +0800220 }
Octav Zlatiorcf518962014-12-15 16:29:15 +0100221 else {
222 if (context->protocols[0].callback(context, NULL,
223 LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
=?UTF-8?q?Christoph=20M=C3=BCllner?=87840d12015-01-24 15:55:17 +0100224 context->ssl_ctx, NULL, 0)) {
Octav Zlatiorcf518962014-12-15 16:29:15 +0100225 lwsl_err("ssl private key not set\n");
226 return 1;
=?UTF-8?q?Christoph=20M=C3=BCllner?=87840d12015-01-24 15:55:17 +0100227 }
Octav Zlatiorcf518962014-12-15 16:29:15 +0100228 }
229
Andy Greenc57037a2014-04-03 10:17:00 +0800230 /* verify private key */
231 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
232 lwsl_err("Private SSL key doesn't match cert\n");
233 return 1;
234 }
235
Andy Green2eedea92014-04-03 14:33:48 +0800236 /*
237 * SSL is happy and has a cert it's content with
238 * If we're supporting HTTP2, initialize that
239 */
240
241 lws_context_init_http2_ssl(context);
Andy Greenc57037a2014-04-03 10:17:00 +0800242 }
243
244 return 0;
245}
Andy Green8721f4f2014-08-27 16:31:20 +0800246#endif
Andy Greenc57037a2014-04-03 10:17:00 +0800247
248LWS_VISIBLE void
Andy Green4b85c1d2015-12-04 11:08:32 +0800249lws_ssl_destroy(struct lws_context *context)
Andy Greenc57037a2014-04-03 10:17:00 +0800250{
251 if (context->ssl_ctx)
252 SSL_CTX_free(context->ssl_ctx);
joseph.urciuoli4d9c8fc2014-10-16 08:53:19 +0800253 if (!context->user_supplied_ssl_ctx && context->ssl_client_ctx)
Andy Greenc57037a2014-04-03 10:17:00 +0800254 SSL_CTX_free(context->ssl_client_ctx);
255
Alexander Bruinesc3bcb892015-08-08 18:54:49 +0200256#if (OPENSSL_VERSION_NUMBER < 0x01000000) || defined(USE_WOLFSSL)
Andy Greenfce6bde2014-11-05 15:35:05 +0800257 ERR_remove_state(0);
258#else
Andy Green040465d2014-10-27 11:38:03 +0800259 ERR_remove_thread_state(NULL);
Andy Greenfce6bde2014-11-05 15:35:05 +0800260#endif
Andy Greenc57037a2014-04-03 10:17:00 +0800261 ERR_free_strings();
262 EVP_cleanup();
263 CRYPTO_cleanup_all_ex_data();
264}
265
266LWS_VISIBLE void
Andy Green3ef579b2015-12-04 09:23:56 +0800267lws_decode_ssl_error(void)
Andy Greenc57037a2014-04-03 10:17:00 +0800268{
269 char buf[256];
270 u_long err;
271
272 while ((err = ERR_get_error()) != 0) {
273 ERR_error_string_n(err, buf, sizeof(buf));
274 lwsl_err("*** %lu %s\n", err, buf);
275 }
276}
277
278#ifndef LWS_NO_CLIENT
Olehfaeac3c2014-07-29 23:18:41 +0800279
Andy Greenc57037a2014-04-03 10:17:00 +0800280int lws_context_init_client_ssl(struct lws_context_creation_info *info,
Andy Green4b85c1d2015-12-04 11:08:32 +0800281 struct lws_context *context)
Andy Greenc57037a2014-04-03 10:17:00 +0800282{
283 int error;
284 int n;
285 SSL_METHOD *method;
286
Andy Green0c512392014-10-17 08:47:51 +0800287 if (info->provided_client_ssl_ctx) {
288 /* use the provided OpenSSL context if given one */
289 context->ssl_client_ctx = info->provided_client_ssl_ctx;
290 /* nothing for lib to delete */
291 context->user_supplied_ssl_ctx = 1;
292 return 0;
293 }
294
Andy Greenc57037a2014-04-03 10:17:00 +0800295 if (info->port != CONTEXT_PORT_NO_LISTEN)
296 return 0;
297
Marek Kochanowiczb2112292014-10-13 07:32:32 +0200298 /* basic openssl init */
299
300 SSL_library_init();
301
302 OpenSSL_add_all_algorithms();
303 SSL_load_error_strings();
304
Andy Greenc57037a2014-04-03 10:17:00 +0800305 method = (SSL_METHOD *)SSLv23_client_method();
306 if (!method) {
307 error = ERR_get_error();
308 lwsl_err("problem creating ssl method %lu: %s\n",
309 error, ERR_error_string(error,
310 (char *)context->service_buffer));
311 return 1;
312 }
313 /* create context */
314 context->ssl_client_ctx = SSL_CTX_new(method);
315 if (!context->ssl_client_ctx) {
316 error = ERR_get_error();
317 lwsl_err("problem creating ssl context %lu: %s\n",
318 error, ERR_error_string(error,
319 (char *)context->service_buffer));
320 return 1;
321 }
322
323#ifdef SSL_OP_NO_COMPRESSION
324 SSL_CTX_set_options(context->ssl_client_ctx,
325 SSL_OP_NO_COMPRESSION);
326#endif
327 SSL_CTX_set_options(context->ssl_client_ctx,
328 SSL_OP_CIPHER_SERVER_PREFERENCE);
329 if (info->ssl_cipher_list)
330 SSL_CTX_set_cipher_list(context->ssl_client_ctx,
331 info->ssl_cipher_list);
332
333#ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
Andy Greenf55b2ef2014-07-05 10:59:59 +0800334 if (!(info->options & LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
335 /* loads OS default CA certs */
336 SSL_CTX_set_default_verify_paths(context->ssl_client_ctx);
Andy Greenc57037a2014-04-03 10:17:00 +0800337#endif
338
339 /* openssl init for cert verification (for client sockets) */
340 if (!info->ssl_ca_filepath) {
341 if (!SSL_CTX_load_verify_locations(
342 context->ssl_client_ctx, NULL,
343 LWS_OPENSSL_CLIENT_CERTS))
344 lwsl_err(
345 "Unable to load SSL Client certs from %s "
346 "(set by --with-client-cert-dir= "
347 "in configure) -- client ssl isn't "
348 "going to work", LWS_OPENSSL_CLIENT_CERTS);
349 } else
350 if (!SSL_CTX_load_verify_locations(
351 context->ssl_client_ctx, info->ssl_ca_filepath,
352 NULL))
353 lwsl_err(
354 "Unable to load SSL Client certs "
355 "file from %s -- client ssl isn't "
356 "going to work", info->ssl_ca_filepath);
Andy Green752963d2014-11-18 09:28:35 +0800357 else
358 lwsl_info("loaded ssl_ca_filepath\n");
Andy Greenc57037a2014-04-03 10:17:00 +0800359
360 /*
361 * callback allowing user code to load extra verification certs
362 * helping the client to verify server identity
363 */
364
365 /* support for client-side certificate authentication */
366 if (info->ssl_cert_filepath) {
367 n = SSL_CTX_use_certificate_chain_file(
368 context->ssl_client_ctx,
369 info->ssl_cert_filepath);
370 if (n != 1) {
371 lwsl_err("problem getting cert '%s' %lu: %s\n",
372 info->ssl_cert_filepath,
373 ERR_get_error(),
374 ERR_error_string(ERR_get_error(),
375 (char *)context->service_buffer));
376 return 1;
377 }
378 }
379 if (info->ssl_private_key_filepath) {
Andy Green4076a2c2014-11-20 12:10:40 +0800380 lws_ssl_bind_passphrase(context->ssl_client_ctx, info);
Andy Greenc57037a2014-04-03 10:17:00 +0800381 /* set the private key from KeyFile */
382 if (SSL_CTX_use_PrivateKey_file(context->ssl_client_ctx,
Olehfaeac3c2014-07-29 23:18:41 +0800383 info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
Andy Greenc57037a2014-04-03 10:17:00 +0800384 lwsl_err("use_PrivateKey_file '%s' %lu: %s\n",
385 info->ssl_private_key_filepath,
386 ERR_get_error(),
387 ERR_error_string(ERR_get_error(),
388 (char *)context->service_buffer));
389 return 1;
390 }
391
392 /* verify private key */
393 if (!SSL_CTX_check_private_key(
394 context->ssl_client_ctx)) {
395 lwsl_err("Private SSL key doesn't match cert\n");
396 return 1;
397 }
398 }
399
400 context->protocols[0].callback(context, NULL,
401 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
402 context->ssl_client_ctx, NULL, 0);
403
404 return 0;
405}
Andy Green02138122014-04-06 06:26:35 +0100406#endif
407
Andy Green52815602015-01-29 08:36:18 +0800408LWS_VISIBLE void
Andy Green4b85c1d2015-12-04 11:08:32 +0800409lws_ssl_remove_wsi_from_buffered_list(struct lws_context *context,
410 struct lws *wsi)
Andy Green52815602015-01-29 08:36:18 +0800411{
412 if (!wsi->pending_read_list_prev &&
413 !wsi->pending_read_list_next &&
414 context->pending_read_list != wsi)
415 /* we are not on the list */
416 return;
417
418 /* point previous guy's next to our next */
419 if (!wsi->pending_read_list_prev)
420 context->pending_read_list = wsi->pending_read_list_next;
421 else
422 wsi->pending_read_list_prev->pending_read_list_next =
423 wsi->pending_read_list_next;
424
425 /* point next guy's previous to our previous */
426 if (wsi->pending_read_list_next)
427 wsi->pending_read_list_next->pending_read_list_prev =
428 wsi->pending_read_list_prev;
429
430 wsi->pending_read_list_prev = NULL;
431 wsi->pending_read_list_next = NULL;
432}
433
Andy Green02138122014-04-06 06:26:35 +0100434LWS_VISIBLE int
Andy Green4b85c1d2015-12-04 11:08:32 +0800435lws_ssl_capable_read(struct lws_context *context,
436 struct lws *wsi, unsigned char *buf, int len)
Andy Green02138122014-04-06 06:26:35 +0100437{
438 int n;
439
440 if (!wsi->ssl)
Andy Green1f5c9f02014-10-09 08:14:30 +0800441 return lws_ssl_capable_read_no_ssl(context, wsi, buf, len);
Andy Green02138122014-04-06 06:26:35 +0100442
443 n = SSL_read(wsi->ssl, buf, len);
Andy Green972eaf92015-12-03 21:37:34 +0800444 /* manpage: returning 0 means connection shut down */
445 if (!n)
446 return LWS_SSL_CAPABLE_ERROR;
447
448 if (n > 0) {
Andy Greenfe3e3e62014-10-08 11:29:49 +0800449 /*
450 * if it was our buffer that limited what we read,
451 * check if SSL has additional data pending inside SSL buffers.
452 *
453 * Because these won't signal at the network layer with POLLIN
454 * and if we don't realize, this data will sit there forever
455 */
Andy Green609ec852014-10-09 08:29:22 +0800456 if (n == len && wsi->ssl && SSL_pending(wsi->ssl)) {
Andy Green413b3a62015-01-30 10:33:00 +0800457 if (!wsi->pending_read_list_next && !wsi->pending_read_list_prev) {
Roger A. Lightb9f28ac2015-07-02 20:31:17 +0100458 if (context->pending_read_list != wsi) {
459 /* add us to the linked list of guys with pending ssl */
460 if (context->pending_read_list)
461 context->pending_read_list->pending_read_list_prev = wsi;
462 wsi->pending_read_list_next = context->pending_read_list;
463 wsi->pending_read_list_prev = NULL;
464 context->pending_read_list = wsi;
465 }
Andy Green413b3a62015-01-30 10:33:00 +0800466 }
467 } else
468 lws_ssl_remove_wsi_from_buffered_list(context, wsi);
Andy Green52815602015-01-29 08:36:18 +0800469
Andy Green02138122014-04-06 06:26:35 +0100470 return n;
Andy Greenfe3e3e62014-10-08 11:29:49 +0800471 }
Andy Green529d4812014-04-06 12:39:22 +0100472 n = SSL_get_error(wsi->ssl, n);
Andy Green02138122014-04-06 06:26:35 +0100473 if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE)
474 return LWS_SSL_CAPABLE_MORE_SERVICE;
Andy Green11f27342015-11-08 12:10:26 +0800475lwsl_err("%s: LWS_SSL_CAPABLE_ERROR\n", __func__);
Andy Green02138122014-04-06 06:26:35 +0100476 return LWS_SSL_CAPABLE_ERROR;
477}
478
479LWS_VISIBLE int
Andy Green4b85c1d2015-12-04 11:08:32 +0800480lws_ssl_pending(struct lws *wsi)
=?UTF-8?q?Jos=C3=A9=20Luis=20Mill=C3=A1n?=4c0ba022015-08-19 16:23:33 +0200481{
482 if (!wsi->ssl)
483 return 0;
484
485 return SSL_pending(wsi->ssl);
486}
487
488LWS_VISIBLE int
Andy Green4b85c1d2015-12-04 11:08:32 +0800489lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len)
Andy Green02138122014-04-06 06:26:35 +0100490{
491 int n;
492
493 if (!wsi->ssl)
494 return lws_ssl_capable_write_no_ssl(wsi, buf, len);
Andy Green11f27342015-11-08 12:10:26 +0800495
Andy Green02138122014-04-06 06:26:35 +0100496 n = SSL_write(wsi->ssl, buf, len);
Andy Green972eaf92015-12-03 21:37:34 +0800497 if (n > 0)
Andy Green02138122014-04-06 06:26:35 +0100498 return n;
499
Andy Green529d4812014-04-06 12:39:22 +0100500 n = SSL_get_error(wsi->ssl, n);
Andy Green02138122014-04-06 06:26:35 +0100501 if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) {
502 if (n == SSL_ERROR_WANT_WRITE)
503 lws_set_blocking_send(wsi);
504 return LWS_SSL_CAPABLE_MORE_SERVICE;
505 }
Andy Green11f27342015-11-08 12:10:26 +0800506lwsl_err("%s: LWS_SSL_CAPABLE_ERROR\n", __func__);
Andy Green02138122014-04-06 06:26:35 +0100507 return LWS_SSL_CAPABLE_ERROR;
508}
509
510LWS_VISIBLE int
Andy Green4b85c1d2015-12-04 11:08:32 +0800511lws_ssl_close(struct lws *wsi)
Andy Greencdb9bf92014-04-12 10:07:02 +0800512{
513 int n;
514
515 if (!wsi->ssl)
516 return 0; /* not handled */
517
518 n = SSL_get_fd(wsi->ssl);
519 SSL_shutdown(wsi->ssl);
520 compatible_close(n);
521 SSL_free(wsi->ssl);
Andrew Canadayad2248a2015-12-03 09:44:15 +0800522 wsi->ssl = NULL;
Andy Greencdb9bf92014-04-12 10:07:02 +0800523
524 return 1; /* handled */
525}
526
527LWS_VISIBLE int
Andy Green4b85c1d2015-12-04 11:08:32 +0800528lws_server_socket_service_ssl(struct lws_context *context,
529 struct lws **pwsi, struct lws *new_wsi,
530 int accept_fd, struct lws_pollfd *pollfd)
Andy Greencdb9bf92014-04-12 10:07:02 +0800531{
532 int n, m;
Andy Green4b85c1d2015-12-04 11:08:32 +0800533 struct lws *wsi = *pwsi;
Alexander Bruinesc3bcb892015-08-08 18:54:49 +0200534#ifndef USE_WOLFSSL
Andy Greencdb9bf92014-04-12 10:07:02 +0800535 BIO *bio;
536#endif
537
538 if (!LWS_SSL_ENABLED(context))
539 return 0;
540
541 switch (wsi->mode) {
542 case LWS_CONNMODE_SERVER_LISTENER:
543
Andy Green62824f92014-08-10 09:50:42 +0800544 if (!new_wsi) {
545 lwsl_err("no new_wsi\n");
546 return 0;
547 }
548
Andy Greencdb9bf92014-04-12 10:07:02 +0800549 new_wsi->ssl = SSL_new(context->ssl_ctx);
550 if (new_wsi->ssl == NULL) {
551 lwsl_err("SSL_new failed: %s\n",
=?UTF-8?q?Joakim=20S=C3=B6derberg?=8361d342015-06-25 17:14:44 +0200552 ERR_error_string(SSL_get_error(new_wsi->ssl, 0), NULL));
Andy Green3ef579b2015-12-04 09:23:56 +0800553 lws_decode_ssl_error();
=?UTF-8?q?Joakim=20S=C3=B6derberg?=8361d342015-06-25 17:14:44 +0200554
555 // TODO: Shouldn't the caller handle this?
Andy Greencdb9bf92014-04-12 10:07:02 +0800556 compatible_close(accept_fd);
=?UTF-8?q?Joakim=20S=C3=B6derberg?=8361d342015-06-25 17:14:44 +0200557 goto fail;
Andy Greencdb9bf92014-04-12 10:07:02 +0800558 }
559
560 SSL_set_ex_data(new_wsi->ssl,
561 openssl_websocket_private_data_index, context);
562
563 SSL_set_fd(new_wsi->ssl, accept_fd);
564
Alexander Bruinesc3bcb892015-08-08 18:54:49 +0200565#ifdef USE_WOLFSSL
ABruines80a70682015-08-09 22:56:32 +0200566#ifdef USE_OLD_CYASSL
567 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
568#else
Alexander Bruinesc3bcb892015-08-08 18:54:49 +0200569 wolfSSL_set_using_nonblock(new_wsi->ssl, 1);
ABruines80a70682015-08-09 22:56:32 +0200570#endif
Andy Greencdb9bf92014-04-12 10:07:02 +0800571#else
572 SSL_set_mode(new_wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
573 bio = SSL_get_rbio(new_wsi->ssl);
574 if (bio)
575 BIO_set_nbio(bio, 1); /* nonblocking */
576 else
577 lwsl_notice("NULL rbio\n");
578 bio = SSL_get_wbio(new_wsi->ssl);
579 if (bio)
580 BIO_set_nbio(bio, 1); /* nonblocking */
581 else
582 lwsl_notice("NULL rbio\n");
583#endif
584
585 /*
586 * we are not accepted yet, but we need to enter ourselves
587 * as a live connection. That way we can retry when more
588 * pieces come if we're not sorted yet
589 */
590
591 *pwsi = new_wsi;
592 wsi = *pwsi;
593 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
Andy Green1963c9a2015-10-15 07:39:33 +0800594 if (insert_wsi_socket_into_fds(context, wsi))
595 goto fail;
Andy Greencdb9bf92014-04-12 10:07:02 +0800596
Andy Green62304762015-12-04 08:43:54 +0800597 lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
Andy Greencdb9bf92014-04-12 10:07:02 +0800598 AWAITING_TIMEOUT);
599
600 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
601
602 /* fallthru */
603
604 case LWS_CONNMODE_SSL_ACK_PENDING:
605
606 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
607 goto fail;
608
609 lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
610
611 lws_latency_pre(context, wsi);
612
Stephan Eberleb820e2c2015-10-23 08:10:55 +0200613 n = recv(wsi->sock, (char *)context->service_buffer,
Andy Greencdb9bf92014-04-12 10:07:02 +0800614 sizeof(context->service_buffer), MSG_PEEK);
615
616 /*
617 * optionally allow non-SSL connect on SSL listening socket
618 * This is disabled by default, if enabled it goes around any
619 * SSL-level access control (eg, client-side certs) so leave
620 * it disabled unless you know it's not a problem for you
621 */
622
Andy Greendbbd3112015-10-16 11:39:23 +0800623 if (context->allow_non_ssl_on_ssl_port) {
624 if (n >= 1 && context->service_buffer[0] >= ' ') {
Andy Green29ddc842015-10-22 20:19:21 +0800625 /*
626 * TLS content-type for Handshake is 0x16, and
627 * for ChangeCipherSpec Record, it's 0x14
628 *
629 * A non-ssl session will start with the HTTP
630 * method in ASCII. If we see it's not a legit
631 * SSL handshake kill the SSL for this
632 * connection and try to handle as a HTTP
633 * connection upgrade directly.
634 */
Andy Greendbbd3112015-10-16 11:39:23 +0800635 wsi->use_ssl = 0;
636 SSL_shutdown(wsi->ssl);
637 SSL_free(wsi->ssl);
638 wsi->ssl = NULL;
639 goto accepted;
640 }
Andy Green79a3c5d2015-11-06 08:23:05 +0800641 if (!n) /*
642 * connection is gone, or nothing to read
643 * if it's gone, we will timeout on
644 * PENDING_TIMEOUT_SSL_ACCEPT
645 */
646 break;
Andy Greencc64fb52015-10-31 06:49:05 +0800647 if (n < 0 && (LWS_ERRNO == LWS_EAGAIN ||
648 LWS_ERRNO == LWS_EWOULDBLOCK)) {
Andy Greendbbd3112015-10-16 11:39:23 +0800649 /*
650 * well, we get no way to know ssl or not
651 * so go around again waiting for something
652 * to come and give us a hint, or timeout the
653 * connection.
654 */
655 m = SSL_ERROR_WANT_READ;
656 goto go_again;
657 }
Andy Greencdb9bf92014-04-12 10:07:02 +0800658 }
659
660 /* normal SSL connection processing path */
661
662 n = SSL_accept(wsi->ssl);
663 lws_latency(context, wsi,
664 "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
665
666 if (n == 1)
667 goto accepted;
668
669 m = SSL_get_error(wsi->ssl, n);
670 lwsl_debug("SSL_accept failed %d / %s\n",
671 m, ERR_error_string(m, NULL));
Andy Greendbbd3112015-10-16 11:39:23 +0800672go_again:
Andy Greencdb9bf92014-04-12 10:07:02 +0800673 if (m == SSL_ERROR_WANT_READ) {
674 if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
675 goto fail;
676
677 lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
678
679 lwsl_info("SSL_ERROR_WANT_READ\n");
680 break;
681 }
682 if (m == SSL_ERROR_WANT_WRITE) {
683 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
684 goto fail;
685
686 lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
687 break;
688 }
689 lwsl_debug("SSL_accept failed skt %u: %s\n",
690 pollfd->fd, ERR_error_string(m, NULL));
Andy Green26193fa2014-11-30 12:14:23 +0800691 goto fail;
Andy Greencdb9bf92014-04-12 10:07:02 +0800692
693accepted:
694 /* OK, we are accepted... give him some time to negotiate */
Andy Green62304762015-12-04 08:43:54 +0800695 lws_set_timeout(wsi,
Andy Greencdb9bf92014-04-12 10:07:02 +0800696 PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
697 AWAITING_TIMEOUT);
698
699 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
700
Andy Green7df53c52014-10-22 15:37:28 +0800701 lws_http2_configure_if_upgraded(wsi);
702
Andy Greencdb9bf92014-04-12 10:07:02 +0800703 lwsl_debug("accepted new SSL conn\n");
704 break;
705 }
706
707 return 0;
708
709fail:
710 return 1;
711}
712
713LWS_VISIBLE void
Andy Green4b85c1d2015-12-04 11:08:32 +0800714lws_ssl_context_destroy(struct lws_context *context)
Andy Greencdb9bf92014-04-12 10:07:02 +0800715{
716 if (context->ssl_ctx)
717 SSL_CTX_free(context->ssl_ctx);
joseph.urciuoli4d9c8fc2014-10-16 08:53:19 +0800718 if (!context->user_supplied_ssl_ctx && context->ssl_client_ctx)
Andy Greencdb9bf92014-04-12 10:07:02 +0800719 SSL_CTX_free(context->ssl_client_ctx);
720
Alexander Bruinesc3bcb892015-08-08 18:54:49 +0200721#if (OPENSSL_VERSION_NUMBER < 0x01000000) || defined(USE_WOLFSSL)
Andy Greenfce6bde2014-11-05 15:35:05 +0800722 ERR_remove_state(0);
723#else
Andy Green040465d2014-10-27 11:38:03 +0800724 ERR_remove_thread_state(NULL);
Andy Greenfce6bde2014-11-05 15:35:05 +0800725#endif
Andy Greencdb9bf92014-04-12 10:07:02 +0800726 ERR_free_strings();
727 EVP_cleanup();
728 CRYPTO_cleanup_all_ex_data();
vpeter44dd8ada2014-04-27 13:28:22 +0200729}