2 * libwebsockets - small server side websockets and web server implementation
4 * Copyright (C) 2010-2014 Andy Green <andy@warmcat.com>
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.
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.
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,
22 #include "private-libwebsockets.h"
23 #include <openssl/err.h>
25 int openssl_websocket_private_data_index;
27 static int lws_context_init_ssl_pem_passwd_cb(char * buf, int size, int rwflag, void *userdata)
29 struct lws_context_creation_info * info = (struct lws_context_creation_info *)userdata;
31 strncpy(buf, info->ssl_private_key_password, size);
37 static void lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx,
38 struct lws_context_creation_info *info)
40 if (!info->ssl_private_key_password)
43 * password provided, set ssl callback and user data
44 * for checking password which will be trigered during
45 * SSL_CTX_use_PrivateKey_file function
47 SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info);
48 SSL_CTX_set_default_passwd_cb(ssl_ctx,
49 lws_context_init_ssl_pem_passwd_cb);
54 OpenSSL_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
58 struct libwebsocket_context *context;
60 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
61 SSL_get_ex_data_X509_STORE_CTX_idx());
64 * !!! nasty openssl requires the index to come as a library-scope
67 context = SSL_get_ex_data(ssl, openssl_websocket_private_data_index);
69 n = context->protocols[0].callback(NULL, NULL,
70 LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION,
71 x509_ctx, ssl, preverify_ok);
73 /* convert return code from 0 = OK to 1 = OK */
78 lws_context_init_server_ssl(struct lws_context_creation_info *info,
79 struct libwebsocket_context *context)
85 if (info->port != CONTEXT_PORT_NO_LISTEN) {
87 context->use_ssl = info->ssl_cert_filepath != NULL;
90 lwsl_notice(" Compiled with CYASSL support\n");
92 lwsl_notice(" Compiled with OpenSSL support\n");
95 if (info->ssl_cipher_list)
96 lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list);
99 lwsl_notice(" Using SSL mode\n");
101 lwsl_notice(" Using non-SSL mode\n");
104 /* basic openssl init */
108 OpenSSL_add_all_algorithms();
109 SSL_load_error_strings();
111 openssl_websocket_private_data_index =
112 SSL_get_ex_new_index(0, "libwebsockets", NULL, NULL, NULL);
115 * Firefox insists on SSLv23 not SSLv3
116 * Konq disables SSLv2 by default now, SSLv23 works
118 * SSLv23_server_method() is the openssl method for "allow all TLS
119 * versions", compared to e.g. TLSv1_2_server_method() which only allows
120 * tlsv1.2. Unwanted versions must be disabled using SSL_CTX_set_options()
123 method = (SSL_METHOD *)SSLv23_server_method();
125 error = ERR_get_error();
126 lwsl_err("problem creating ssl method %lu: %s\n",
127 error, ERR_error_string(error,
128 (char *)context->service_buffer));
131 context->ssl_ctx = SSL_CTX_new(method); /* create context */
132 if (!context->ssl_ctx) {
133 error = ERR_get_error();
134 lwsl_err("problem creating ssl context %lu: %s\n",
135 error, ERR_error_string(error,
136 (char *)context->service_buffer));
140 /* Disable SSLv2 and SSLv3 */
141 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
142 #ifdef SSL_OP_NO_COMPRESSION
143 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
145 SSL_CTX_set_options(context->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
146 if (info->ssl_cipher_list)
147 SSL_CTX_set_cipher_list(context->ssl_ctx,
148 info->ssl_cipher_list);
150 /* as a server, are we requiring clients to identify themselves? */
153 LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
155 /* absolutely require the client cert */
157 SSL_CTX_set_verify(context->ssl_ctx,
158 SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
159 OpenSSL_verify_callback);
162 * give user code a chance to load certs into the server
163 * allowing it to verify incoming client certs
166 context->protocols[0].callback(context, NULL,
167 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
168 context->ssl_ctx, NULL, 0);
171 if (info->options & LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT) {
172 /* Normally SSL listener rejects non-ssl, optionally allow */
173 context->allow_non_ssl_on_ssl_port = 1;
176 if (context->use_ssl) {
178 /* openssl init for server sockets */
180 /* set the local certificate from CertFile */
181 n = SSL_CTX_use_certificate_chain_file(context->ssl_ctx,
182 info->ssl_cert_filepath);
184 error = ERR_get_error();
185 lwsl_err("problem getting cert '%s' %lu: %s\n",
186 info->ssl_cert_filepath,
188 ERR_error_string(error,
189 (char *)context->service_buffer));
192 lws_ssl_bind_passphrase(context->ssl_ctx, info);
194 if (info->ssl_private_key_filepath != NULL) {
195 /* set the private key from KeyFile */
196 if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx,
197 info->ssl_private_key_filepath,
198 SSL_FILETYPE_PEM) != 1) {
199 error = ERR_get_error();
200 lwsl_err("ssl problem getting key '%s' %lu: %s\n",
201 info->ssl_private_key_filepath,
203 ERR_error_string(error,
204 (char *)context->service_buffer));
209 if (context->protocols[0].callback(context, NULL,
210 LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY,
211 context->ssl_ctx, NULL, 0)) {
212 lwsl_err("ssl private key not set\n");
217 /* verify private key */
218 if (!SSL_CTX_check_private_key(context->ssl_ctx)) {
219 lwsl_err("Private SSL key doesn't match cert\n");
224 * SSL is happy and has a cert it's content with
225 * If we're supporting HTTP2, initialize that
228 lws_context_init_http2_ssl(context);
236 lws_ssl_destroy(struct libwebsocket_context *context)
238 if (context->ssl_ctx)
239 SSL_CTX_free(context->ssl_ctx);
240 if (!context->user_supplied_ssl_ctx && context->ssl_client_ctx)
241 SSL_CTX_free(context->ssl_client_ctx);
243 #if (OPENSSL_VERSION_NUMBER < 0x01000000) || defined(USE_CYASSL)
246 ERR_remove_thread_state(NULL);
250 CRYPTO_cleanup_all_ex_data();
254 libwebsockets_decode_ssl_error(void)
259 while ((err = ERR_get_error()) != 0) {
260 ERR_error_string_n(err, buf, sizeof(buf));
261 lwsl_err("*** %lu %s\n", err, buf);
265 #ifndef LWS_NO_CLIENT
267 int lws_context_init_client_ssl(struct lws_context_creation_info *info,
268 struct libwebsocket_context *context)
274 if (info->provided_client_ssl_ctx) {
275 /* use the provided OpenSSL context if given one */
276 context->ssl_client_ctx = info->provided_client_ssl_ctx;
277 /* nothing for lib to delete */
278 context->user_supplied_ssl_ctx = 1;
282 if (info->port != CONTEXT_PORT_NO_LISTEN)
285 /* basic openssl init */
289 OpenSSL_add_all_algorithms();
290 SSL_load_error_strings();
292 method = (SSL_METHOD *)SSLv23_client_method();
294 error = ERR_get_error();
295 lwsl_err("problem creating ssl method %lu: %s\n",
296 error, ERR_error_string(error,
297 (char *)context->service_buffer));
301 context->ssl_client_ctx = SSL_CTX_new(method);
302 if (!context->ssl_client_ctx) {
303 error = ERR_get_error();
304 lwsl_err("problem creating ssl context %lu: %s\n",
305 error, ERR_error_string(error,
306 (char *)context->service_buffer));
310 #ifdef SSL_OP_NO_COMPRESSION
311 SSL_CTX_set_options(context->ssl_client_ctx,
312 SSL_OP_NO_COMPRESSION);
314 SSL_CTX_set_options(context->ssl_client_ctx,
315 SSL_OP_CIPHER_SERVER_PREFERENCE);
316 if (info->ssl_cipher_list)
317 SSL_CTX_set_cipher_list(context->ssl_client_ctx,
318 info->ssl_cipher_list);
320 #ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
321 if (!(info->options & LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
322 /* loads OS default CA certs */
323 SSL_CTX_set_default_verify_paths(context->ssl_client_ctx);
326 /* openssl init for cert verification (for client sockets) */
327 if (!info->ssl_ca_filepath) {
328 if (!SSL_CTX_load_verify_locations(
329 context->ssl_client_ctx, NULL,
330 LWS_OPENSSL_CLIENT_CERTS))
332 "Unable to load SSL Client certs from %s "
333 "(set by --with-client-cert-dir= "
334 "in configure) -- client ssl isn't "
335 "going to work", LWS_OPENSSL_CLIENT_CERTS);
337 if (!SSL_CTX_load_verify_locations(
338 context->ssl_client_ctx, info->ssl_ca_filepath,
341 "Unable to load SSL Client certs "
342 "file from %s -- client ssl isn't "
343 "going to work", info->ssl_ca_filepath);
345 lwsl_info("loaded ssl_ca_filepath\n");
348 * callback allowing user code to load extra verification certs
349 * helping the client to verify server identity
352 /* support for client-side certificate authentication */
353 if (info->ssl_cert_filepath) {
354 n = SSL_CTX_use_certificate_chain_file(
355 context->ssl_client_ctx,
356 info->ssl_cert_filepath);
358 lwsl_err("problem getting cert '%s' %lu: %s\n",
359 info->ssl_cert_filepath,
361 ERR_error_string(ERR_get_error(),
362 (char *)context->service_buffer));
366 if (info->ssl_private_key_filepath) {
367 lws_ssl_bind_passphrase(context->ssl_client_ctx, info);
368 /* set the private key from KeyFile */
369 if (SSL_CTX_use_PrivateKey_file(context->ssl_client_ctx,
370 info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) {
371 lwsl_err("use_PrivateKey_file '%s' %lu: %s\n",
372 info->ssl_private_key_filepath,
374 ERR_error_string(ERR_get_error(),
375 (char *)context->service_buffer));
379 /* verify private key */
380 if (!SSL_CTX_check_private_key(
381 context->ssl_client_ctx)) {
382 lwsl_err("Private SSL key doesn't match cert\n");
387 context->protocols[0].callback(context, NULL,
388 LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
389 context->ssl_client_ctx, NULL, 0);
396 lws_ssl_remove_wsi_from_buffered_list(struct libwebsocket_context *context,
397 struct libwebsocket *wsi)
399 if (!wsi->pending_read_list_prev &&
400 !wsi->pending_read_list_next &&
401 context->pending_read_list != wsi)
402 /* we are not on the list */
405 /* point previous guy's next to our next */
406 if (!wsi->pending_read_list_prev)
407 context->pending_read_list = wsi->pending_read_list_next;
409 wsi->pending_read_list_prev->pending_read_list_next =
410 wsi->pending_read_list_next;
412 /* point next guy's previous to our previous */
413 if (wsi->pending_read_list_next)
414 wsi->pending_read_list_next->pending_read_list_prev =
415 wsi->pending_read_list_prev;
417 wsi->pending_read_list_prev = NULL;
418 wsi->pending_read_list_next = NULL;
422 lws_ssl_capable_read(struct libwebsocket_context *context,
423 struct libwebsocket *wsi, unsigned char *buf, int len)
428 return lws_ssl_capable_read_no_ssl(context, wsi, buf, len);
430 n = SSL_read(wsi->ssl, buf, len);
433 * if it was our buffer that limited what we read,
434 * check if SSL has additional data pending inside SSL buffers.
436 * Because these won't signal at the network layer with POLLIN
437 * and if we don't realize, this data will sit there forever
439 if (n == len && wsi->ssl && SSL_pending(wsi->ssl)) {
440 assert(!wsi->pending_read_list_next && !wsi->pending_read_list_prev);
441 /* add us to the linked list of guys with pending ssl */
442 context->pending_read_list->pending_read_list_prev = wsi;
443 wsi->pending_read_list_next = context->pending_read_list;
444 wsi->pending_read_list_prev = NULL;
445 context->pending_read_list = wsi;
450 n = SSL_get_error(wsi->ssl, n);
451 if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE)
452 return LWS_SSL_CAPABLE_MORE_SERVICE;
454 return LWS_SSL_CAPABLE_ERROR;
458 lws_ssl_capable_write(struct libwebsocket *wsi, unsigned char *buf, int len)
463 return lws_ssl_capable_write_no_ssl(wsi, buf, len);
465 n = SSL_write(wsi->ssl, buf, len);
469 n = SSL_get_error(wsi->ssl, n);
470 if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) {
471 if (n == SSL_ERROR_WANT_WRITE)
472 lws_set_blocking_send(wsi);
473 return LWS_SSL_CAPABLE_MORE_SERVICE;
476 return LWS_SSL_CAPABLE_ERROR;
480 lws_ssl_close(struct libwebsocket *wsi)
485 return 0; /* not handled */
487 n = SSL_get_fd(wsi->ssl);
488 SSL_shutdown(wsi->ssl);
492 return 1; /* handled */
496 lws_server_socket_service_ssl(struct libwebsocket_context *context,
497 struct libwebsocket **pwsi, struct libwebsocket *new_wsi,
498 int accept_fd, struct libwebsocket_pollfd *pollfd)
501 struct libwebsocket *wsi = *pwsi;
506 if (!LWS_SSL_ENABLED(context))
510 case LWS_CONNMODE_SERVER_LISTENER:
513 lwsl_err("no new_wsi\n");
517 new_wsi->ssl = SSL_new(context->ssl_ctx);
518 if (new_wsi->ssl == NULL) {
519 lwsl_err("SSL_new failed: %s\n",
520 ERR_error_string(SSL_get_error(
521 new_wsi->ssl, 0), NULL));
522 libwebsockets_decode_ssl_error();
524 compatible_close(accept_fd);
528 SSL_set_ex_data(new_wsi->ssl,
529 openssl_websocket_private_data_index, context);
531 SSL_set_fd(new_wsi->ssl, accept_fd);
534 CyaSSL_set_using_nonblock(new_wsi->ssl, 1);
536 SSL_set_mode(new_wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
537 bio = SSL_get_rbio(new_wsi->ssl);
539 BIO_set_nbio(bio, 1); /* nonblocking */
541 lwsl_notice("NULL rbio\n");
542 bio = SSL_get_wbio(new_wsi->ssl);
544 BIO_set_nbio(bio, 1); /* nonblocking */
546 lwsl_notice("NULL rbio\n");
550 * we are not accepted yet, but we need to enter ourselves
551 * as a live connection. That way we can retry when more
552 * pieces come if we're not sorted yet
557 wsi->mode = LWS_CONNMODE_SSL_ACK_PENDING;
558 insert_wsi_socket_into_fds(context, wsi);
560 libwebsocket_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
563 lwsl_info("inserted SSL accept into fds, trying SSL_accept\n");
567 case LWS_CONNMODE_SSL_ACK_PENDING:
569 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
572 lws_libev_io(context, wsi, LWS_EV_STOP | LWS_EV_WRITE);
574 lws_latency_pre(context, wsi);
576 n = recv(wsi->sock, context->service_buffer,
577 sizeof(context->service_buffer), MSG_PEEK);
580 * optionally allow non-SSL connect on SSL listening socket
581 * This is disabled by default, if enabled it goes around any
582 * SSL-level access control (eg, client-side certs) so leave
583 * it disabled unless you know it's not a problem for you
586 if (context->allow_non_ssl_on_ssl_port && n >= 1 &&
587 context->service_buffer[0] >= ' ') {
589 * TLS content-type for Handshake is 0x16
590 * TLS content-type for ChangeCipherSpec Record is 0x14
592 * A non-ssl session will start with the HTTP method in
593 * ASCII. If we see it's not a legit SSL handshake
594 * kill the SSL for this connection and try to handle
595 * as a HTTP connection upgrade directly.
598 SSL_shutdown(wsi->ssl);
604 /* normal SSL connection processing path */
606 n = SSL_accept(wsi->ssl);
607 lws_latency(context, wsi,
608 "SSL_accept LWS_CONNMODE_SSL_ACK_PENDING\n", n, n == 1);
613 m = SSL_get_error(wsi->ssl, n);
614 lwsl_debug("SSL_accept failed %d / %s\n",
615 m, ERR_error_string(m, NULL));
617 if (m == SSL_ERROR_WANT_READ) {
618 if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
621 lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_READ);
623 lwsl_info("SSL_ERROR_WANT_READ\n");
626 if (m == SSL_ERROR_WANT_WRITE) {
627 if (lws_change_pollfd(wsi, 0, LWS_POLLOUT))
630 lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE);
633 lwsl_debug("SSL_accept failed skt %u: %s\n",
634 pollfd->fd, ERR_error_string(m, NULL));
638 /* OK, we are accepted... give him some time to negotiate */
639 libwebsocket_set_timeout(wsi,
640 PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
643 wsi->mode = LWS_CONNMODE_HTTP_SERVING;
645 lws_http2_configure_if_upgraded(wsi);
647 lwsl_debug("accepted new SSL conn\n");
658 lws_ssl_context_destroy(struct libwebsocket_context *context)
660 if (context->ssl_ctx)
661 SSL_CTX_free(context->ssl_ctx);
662 if (!context->user_supplied_ssl_ctx && context->ssl_client_ctx)
663 SSL_CTX_free(context->ssl_client_ctx);
665 #if (OPENSSL_VERSION_NUMBER < 0x01000000) || defined(USE_CYASSL)
668 ERR_remove_thread_state(NULL);
672 CRYPTO_cleanup_all_ex_data();