2016-03-29 08:51:42 +08:00
|
|
|
/*
|
|
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
2016-03-29 08:51:42 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
2016-03-29 08:51:42 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
2016-03-29 08:51:42 +08:00
|
|
|
*
|
2019-08-14 10:44:14 +01:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
* IN THE SOFTWARE.
|
2016-03-29 08:51:42 +08:00
|
|
|
*/
|
|
|
|
|
2019-08-15 10:49:52 +01:00
|
|
|
#include "private-lib-core.h"
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2019-08-18 05:04:15 +01:00
|
|
|
#if defined(LWS_WITH_SERVER)
|
2019-08-09 10:12:09 +01:00
|
|
|
|
|
|
|
static void
|
|
|
|
lws_sul_tls_cb(lws_sorted_usec_list_t *sul)
|
|
|
|
{
|
|
|
|
struct lws_context_per_thread *pt = lws_container_of(sul,
|
|
|
|
struct lws_context_per_thread, sul_tls);
|
|
|
|
|
|
|
|
lws_tls_check_all_cert_lifetimes(pt->context);
|
|
|
|
|
2020-05-28 12:48:17 +01:00
|
|
|
__lws_sul_insert_us(&pt->pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED],
|
|
|
|
&pt->sul_tls,
|
|
|
|
(lws_usec_t)24 * 3600 * LWS_US_PER_SEC);
|
2019-08-09 10:12:09 +01:00
|
|
|
}
|
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2018-04-27 08:27:16 +08:00
|
|
|
lws_context_init_server_ssl(const struct lws_context_creation_info *info,
|
2016-03-29 08:51:42 +08:00
|
|
|
struct lws_vhost *vhost)
|
|
|
|
{
|
|
|
|
struct lws_context *context = vhost->context;
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
lws_fakewsi_def_plwsa(&vhost->context->pt[0]);
|
|
|
|
|
|
|
|
lws_fakewsi_prep_plwsa_ctx(vhost->context);
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
if (!lws_check_opt(info->options,
|
|
|
|
LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
|
2018-05-01 12:41:42 +08:00
|
|
|
vhost->tls.use_ssl = 0;
|
2017-10-18 09:41:44 +08:00
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2017-09-06 10:15:10 +08:00
|
|
|
|
|
|
|
/*
|
2019-02-14 14:35:24 +08:00
|
|
|
* If he is giving a server cert, take it as a sign he wants to use
|
2017-09-06 10:15:10 +08:00
|
|
|
* it on this vhost. User code can leave the cert filepath NULL and
|
|
|
|
* set the LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX option itself, in
|
|
|
|
* which case he's expected to set up the cert himself at
|
|
|
|
* LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
|
|
|
|
* provides the vhost SSL_CTX * in the user parameter.
|
|
|
|
*/
|
2019-02-14 14:35:24 +08:00
|
|
|
if (info->ssl_cert_filepath || info->server_ssl_cert_mem)
|
2018-04-27 08:27:16 +08:00
|
|
|
vhost->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX;
|
2017-09-06 10:15:10 +08:00
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
if (info->port != CONTEXT_PORT_NO_LISTEN) {
|
|
|
|
|
2018-05-01 12:41:42 +08:00
|
|
|
vhost->tls.use_ssl = lws_check_opt(vhost->options,
|
2017-09-06 10:15:10 +08:00
|
|
|
LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX);
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2018-05-01 12:41:42 +08:00
|
|
|
if (vhost->tls.use_ssl && info->ssl_cipher_list)
|
2017-10-18 09:41:44 +08:00
|
|
|
lwsl_notice(" SSL ciphers: '%s'\n",
|
|
|
|
info->ssl_cipher_list);
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
lwsl_notice(" Vhost '%s' using %sTLS mode\n",
|
|
|
|
vhost->name, vhost->tls.use_ssl ? "" : "non-");
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* give him a fake wsi with context + vhost set, so he can use
|
|
|
|
* lws_get_context() in the callback
|
|
|
|
*/
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
plwsa->vhost = vhost; /* not a real bound wsi */
|
2016-04-17 11:28:43 +08:00
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
/*
|
2017-10-18 09:41:44 +08:00
|
|
|
* as a server, if we are requiring clients to identify themselves
|
|
|
|
* then set the backend up for it
|
2016-03-29 08:51:42 +08:00
|
|
|
*/
|
2016-04-17 11:28:43 +08:00
|
|
|
if (lws_check_opt(info->options,
|
2017-10-18 09:41:44 +08:00
|
|
|
LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT))
|
|
|
|
/* Normally SSL listener rejects non-ssl, optionally allow */
|
2018-05-01 12:41:42 +08:00
|
|
|
vhost->tls.allow_non_ssl_on_ssl_port = 1;
|
2016-03-29 08:51:42 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* give user code a chance to load certs into the server
|
|
|
|
* allowing it to verify incoming client certs
|
|
|
|
*/
|
2018-05-01 12:41:42 +08:00
|
|
|
if (vhost->tls.use_ssl) {
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (lws_tls_server_vhost_backend_init(info, vhost, (struct lws *)plwsa))
|
2016-03-29 08:51:42 +08:00
|
|
|
return -1;
|
|
|
|
|
2017-11-06 06:28:55 +08:00
|
|
|
lws_tls_server_client_cert_verify_config(vhost);
|
2017-10-25 15:27:06 +02:00
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (vhost->protocols[0].callback((struct lws *)plwsa,
|
2017-11-26 09:22:42 +08:00
|
|
|
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
|
2018-05-01 12:41:42 +08:00
|
|
|
vhost->tls.ssl_ctx, vhost, 0))
|
2017-11-26 09:22:42 +08:00
|
|
|
return -1;
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
|
|
|
|
2018-05-01 12:41:42 +08:00
|
|
|
if (vhost->tls.use_ssl)
|
2018-04-12 15:56:38 +08:00
|
|
|
lws_context_init_alpn(vhost);
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2022-04-11 06:04:40 +01:00
|
|
|
/* check certs in a few seconds (after protocol init) and then once a day */
|
2019-08-09 10:12:09 +01:00
|
|
|
|
|
|
|
context->pt[0].sul_tls.cb = lws_sul_tls_cb;
|
2020-05-28 12:48:17 +01:00
|
|
|
__lws_sul_insert_us(&context->pt[0].pt_sul_owner[LWSSULLI_MISS_IF_SUSPENDED],
|
|
|
|
&context->pt[0].sul_tls,
|
2022-04-11 06:04:40 +01:00
|
|
|
(lws_usec_t)5 * LWS_US_PER_SEC);
|
2019-08-09 10:12:09 +01:00
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2019-06-05 05:04:17 +01:00
|
|
|
#endif
|
2017-01-10 09:10:49 +08:00
|
|
|
|
2020-01-02 08:32:23 +00:00
|
|
|
int
|
2020-04-19 08:43:01 +01:00
|
|
|
lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd, char from_pollin)
|
2017-10-18 09:41:44 +08:00
|
|
|
{
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
struct lws_context *context = wsi->a.context;
|
2017-10-18 09:41:44 +08:00
|
|
|
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
2018-11-23 08:47:56 +08:00
|
|
|
struct lws_vhost *vh;
|
2020-12-12 06:21:40 +00:00
|
|
|
ssize_t s;
|
2018-11-23 08:47:56 +08:00
|
|
|
int n;
|
2016-06-10 08:37:26 +08:00
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (!LWS_SSL_ENABLED(wsi->a.vhost))
|
2017-10-18 09:41:44 +08:00
|
|
|
return 0;
|
|
|
|
|
2018-04-02 11:55:17 +08:00
|
|
|
switch (lwsi_state(wsi)) {
|
|
|
|
case LRS_SSL_INIT:
|
|
|
|
|
2018-05-01 12:41:42 +08:00
|
|
|
if (wsi->tls.ssl)
|
2017-10-18 09:41:44 +08:00
|
|
|
lwsl_err("%s: leaking ssl\n", __func__);
|
|
|
|
if (accept_fd == LWS_SOCK_INVALID)
|
|
|
|
assert(0);
|
2020-01-15 16:32:00 +00:00
|
|
|
|
2021-09-22 09:34:56 +01:00
|
|
|
if (lws_tls_restrict_borrow(wsi)) {
|
2020-04-19 08:43:01 +01:00
|
|
|
lwsl_err("%s: failed on ssl restriction\n", __func__);
|
2016-03-29 08:51:42 +08:00
|
|
|
return 1;
|
2020-04-19 08:43:01 +01:00
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
if (lws_tls_server_new_nonblocking(wsi, accept_fd)) {
|
2020-04-19 08:43:01 +01:00
|
|
|
lwsl_err("%s: failed on lws_tls_server_new_nonblocking\n", __func__);
|
2017-10-18 09:41:44 +08:00
|
|
|
if (accept_fd != LWS_SOCK_INVALID)
|
|
|
|
compatible_close(accept_fd);
|
2021-09-22 09:34:56 +01:00
|
|
|
lws_tls_restrict_return(wsi);
|
2017-10-18 09:41:44 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
/*
|
|
|
|
* we are not accepted yet, but we need to enter ourselves
|
|
|
|
* as a live connection. That way we can retry when more
|
|
|
|
* pieces come if we're not sorted yet
|
|
|
|
*/
|
2018-04-02 11:55:17 +08:00
|
|
|
lwsi_set_state(wsi, LRS_SSL_ACK_PENDING);
|
2017-10-18 09:41:44 +08:00
|
|
|
|
2018-03-05 16:49:28 +08:00
|
|
|
lws_pt_lock(pt, __func__);
|
|
|
|
if (__insert_wsi_socket_into_fds(context, wsi)) {
|
2017-10-18 09:41:44 +08:00
|
|
|
lwsl_err("%s: failed to insert into fds\n", __func__);
|
|
|
|
goto fail;
|
2017-03-11 11:51:06 +08:00
|
|
|
}
|
2018-03-05 16:49:28 +08:00
|
|
|
lws_pt_unlock(pt);
|
2017-10-18 09:41:44 +08:00
|
|
|
|
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
|
2020-12-12 06:21:40 +00:00
|
|
|
(int)context->timeout_secs);
|
2017-10-18 09:41:44 +08:00
|
|
|
|
|
|
|
lwsl_debug("inserted SSL accept into fds, trying SSL_accept\n");
|
|
|
|
|
|
|
|
/* fallthru */
|
|
|
|
|
2018-04-02 11:55:17 +08:00
|
|
|
case LRS_SSL_ACK_PENDING:
|
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
|
|
|
|
lwsl_err("%s: lws_change_pollfd failed\n", __func__);
|
|
|
|
goto fail;
|
2017-03-11 11:51:06 +08:00
|
|
|
}
|
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (wsi->a.vhost->tls.allow_non_ssl_on_ssl_port && !wsi->skip_fallback) {
|
2020-04-19 08:43:01 +01:00
|
|
|
/*
|
|
|
|
* We came here by POLLIN, so there is supposed to be
|
|
|
|
* something to read...
|
|
|
|
*/
|
2017-10-18 09:41:44 +08:00
|
|
|
|
2020-12-12 06:21:40 +00:00
|
|
|
s = recv(wsi->desc.sockfd, (char *)pt->serv_buf,
|
2017-10-18 09:41:44 +08:00
|
|
|
context->pt_serv_buf_size, MSG_PEEK);
|
2018-11-29 08:47:49 +08:00
|
|
|
/*
|
|
|
|
* We have LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT..
|
|
|
|
* this just means don't hang up on him because of no
|
|
|
|
* tls hello... what happens next is driven by
|
|
|
|
* additional option flags:
|
|
|
|
*
|
|
|
|
* none: fail the connection
|
|
|
|
*
|
|
|
|
* LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS:
|
|
|
|
* Destroy the TLS, issue a redirect using plaintext
|
|
|
|
* http (this may not be accepted by a client that
|
|
|
|
* has visited the site before and received an STS
|
|
|
|
* header).
|
|
|
|
*
|
|
|
|
* LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER:
|
|
|
|
* Destroy the TLS, continue and serve normally
|
|
|
|
* using http
|
|
|
|
*
|
|
|
|
* LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG:
|
|
|
|
* Destroy the TLS, apply whatever role and protocol
|
|
|
|
* were told in the vhost info struct
|
|
|
|
* .listen_accept_role / .listen_accept_protocol and
|
|
|
|
* continue with that
|
|
|
|
*/
|
|
|
|
|
2020-12-12 06:21:40 +00:00
|
|
|
if (s >= 1 && pt->serv_buf[0] >= ' ') {
|
2017-10-18 09:41:44 +08:00
|
|
|
/*
|
|
|
|
* TLS content-type for Handshake is 0x16, and
|
|
|
|
* for ChangeCipherSpec Record, it's 0x14
|
|
|
|
*
|
|
|
|
* A non-ssl session will start with the HTTP
|
|
|
|
* method in ASCII. If we see it's not a legit
|
|
|
|
* SSL handshake kill the SSL for this
|
|
|
|
* connection and try to handle as a HTTP
|
|
|
|
* connection upgrade directly.
|
|
|
|
*/
|
2018-05-01 12:41:42 +08:00
|
|
|
wsi->tls.use_ssl = 0;
|
2017-10-18 09:41:44 +08:00
|
|
|
|
|
|
|
lws_tls_server_abort_connection(wsi);
|
2018-02-27 07:48:25 +08:00
|
|
|
/*
|
2018-11-29 08:47:49 +08:00
|
|
|
* care... this creates wsi with no ssl when ssl
|
|
|
|
* is enabled and normally mandatory
|
2018-02-27 07:48:25 +08:00
|
|
|
*/
|
2018-05-01 12:41:42 +08:00
|
|
|
wsi->tls.ssl = NULL;
|
2018-11-29 08:47:49 +08:00
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (lws_check_opt(wsi->a.vhost->options,
|
2018-11-29 08:47:49 +08:00
|
|
|
LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS)) {
|
|
|
|
lwsl_info("%s: redirecting from http "
|
|
|
|
"to https\n", __func__);
|
2018-05-01 12:41:42 +08:00
|
|
|
wsi->tls.redirect_to_https = 1;
|
2018-11-29 08:47:49 +08:00
|
|
|
goto notls_accepted;
|
|
|
|
}
|
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (lws_check_opt(wsi->a.vhost->options,
|
2018-11-29 08:47:49 +08:00
|
|
|
LWS_SERVER_OPTION_ALLOW_HTTP_ON_HTTPS_LISTENER)) {
|
|
|
|
lwsl_info("%s: allowing unencrypted "
|
|
|
|
"http service on tls port\n",
|
|
|
|
__func__);
|
|
|
|
goto notls_accepted;
|
|
|
|
}
|
|
|
|
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
if (lws_check_opt(wsi->a.vhost->options,
|
2018-11-29 08:47:49 +08:00
|
|
|
LWS_SERVER_OPTION_FALLBACK_TO_APPLY_LISTEN_ACCEPT_CONFIG)) {
|
|
|
|
if (lws_http_to_fallback(wsi, NULL, 0))
|
|
|
|
goto fail;
|
|
|
|
lwsl_info("%s: allowing non-tls "
|
|
|
|
"fallback\n", __func__);
|
|
|
|
goto notls_accepted;
|
|
|
|
}
|
|
|
|
|
|
|
|
lwsl_notice("%s: client did not send a valid "
|
2018-11-29 08:29:48 +08:00
|
|
|
"tls hello (default vhost %s)\n",
|
fakewsi: replace with smaller substructure
Currently we always reserve a fakewsi per pt so events that don't have a related actual
wsi, like vhost-protocol-init or vhost cert init via protocol callback can make callbacks
that look reasonable to user protocol handler code expecting a valid wsi every time.
This patch splits out stuff that user callbacks often unconditionally expect to be in
a wsi, like context pointer, vhost pointer etc into a substructure, which is composed
into struct lws at the top of it. Internal references (struct lws is opaque, so there
are only internal references) are all updated to go via the substructre, the compiler
should make that a NOP.
Helpers are added when fakewsi is used and referenced.
If not PLAT_FREERTOS, we continue to provide a full fakewsi in the pt as before,
although the helpers improve consistency by zeroing down the substructure. There is
a huge amount of user code out there over the last 10 years that did not always have
the minimal examples to follow, some of it does some unexpected things.
If it is PLAT_FREERTOS, that is a newer thing in lws and users have the benefit of
being able to follow the minimal examples' approach. For PLAT_FREERTOS we don't
reserve the fakewsi in the pt any more, saving around 800 bytes. The helpers then
create a struct lws_a (the substructure) on the stack, zero it down (but it is only
like 4 pointers) and prepare it with whatever we know like the context.
Then we cast it to a struct lws * and use it in the user protocol handler call.
In this case, the remainder of the struct lws is undefined. However the amount of
old protocol handlers that might touch things outside of the substructure in
PLAT_FREERTOS is very limited compared to legacy lws user code and the saving is
significant on constrained devices.
User handlers should not be touching everything in a wsi every time anyway, there
are several cases where there is no valid wsi to do the call with. Dereference of
things outside the substructure should only happen when the callback reason shows
there is a valid wsi bound to the activity (as in all the minimal examples).
2020-07-19 08:33:46 +01:00
|
|
|
__func__, wsi->a.vhost->name);
|
2018-11-29 08:47:49 +08:00
|
|
|
goto fail;
|
2017-10-18 09:41:44 +08:00
|
|
|
}
|
2020-12-12 06:21:40 +00:00
|
|
|
if (!s) {
|
2018-03-13 21:25:54 +08:00
|
|
|
/*
|
2020-04-19 08:43:01 +01:00
|
|
|
* POLLIN but nothing to read is supposed to
|
|
|
|
* mean the connection is gone, we should
|
|
|
|
* fail out...
|
|
|
|
*
|
2017-10-18 09:41:44 +08:00
|
|
|
*/
|
2020-05-25 05:40:13 +01:00
|
|
|
lwsl_debug("%s: PEEKed 0 (from_pollin %d)\n",
|
2020-04-19 08:43:01 +01:00
|
|
|
__func__, from_pollin);
|
|
|
|
if (!from_pollin)
|
|
|
|
/*
|
|
|
|
* If this wasn't actually info from a
|
|
|
|
* pollin let it go around again until
|
|
|
|
* either data came or we still get told
|
|
|
|
* zero length peek AND POLLIN
|
|
|
|
*/
|
|
|
|
goto punt;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* treat as remote closed
|
|
|
|
*/
|
|
|
|
|
2018-03-13 21:25:54 +08:00
|
|
|
goto fail;
|
|
|
|
}
|
2020-12-12 06:21:40 +00:00
|
|
|
if (s < 0 && (LWS_ERRNO == LWS_EAGAIN ||
|
2017-10-18 09:41:44 +08:00
|
|
|
LWS_ERRNO == LWS_EWOULDBLOCK)) {
|
2020-04-19 08:43:01 +01:00
|
|
|
|
|
|
|
punt:
|
2017-10-18 09:41:44 +08:00
|
|
|
/*
|
|
|
|
* well, we get no way to know ssl or not
|
|
|
|
* so go around again waiting for something
|
|
|
|
* to come and give us a hint, or timeout the
|
|
|
|
* connection.
|
|
|
|
*/
|
|
|
|
if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
|
2020-04-19 08:43:01 +01:00
|
|
|
lwsl_err("%s: change_pollfd failed\n",
|
2017-10-18 09:41:44 +08:00
|
|
|
__func__);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
lwsl_info("SSL_ERROR_WANT_READ\n");
|
|
|
|
return 0;
|
2017-10-13 10:33:02 +08:00
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
}
|
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
/* normal SSL connection processing path */
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
n = lws_tls_server_accept(wsi);
|
|
|
|
lwsl_info("SSL_accept says %d\n", n);
|
|
|
|
switch (n) {
|
|
|
|
case LWS_SSL_CAPABLE_DONE:
|
2021-09-22 09:34:56 +01:00
|
|
|
lws_tls_restrict_return_handshake(wsi);
|
2017-10-18 09:41:44 +08:00
|
|
|
break;
|
|
|
|
case LWS_SSL_CAPABLE_ERROR:
|
2021-09-22 09:34:56 +01:00
|
|
|
lws_tls_restrict_return_handshake(wsi);
|
2020-08-23 10:43:42 +01:00
|
|
|
lwsl_info("%s: SSL_accept failed socket %u: %d\n",
|
2020-04-19 08:43:01 +01:00
|
|
|
__func__, wsi->desc.sockfd, n);
|
2018-02-06 07:58:13 +08:00
|
|
|
wsi->socket_is_permanently_unusable = 1;
|
2017-10-18 09:41:44 +08:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
default: /* MORE_SERVICE */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* adapt our vhost to match the SNI SSL_CTX that was chosen */
|
|
|
|
vh = context->vhost_list;
|
|
|
|
while (vh) {
|
2018-05-01 12:41:42 +08:00
|
|
|
if (!vh->being_destroyed && wsi->tls.ssl &&
|
|
|
|
vh->tls.ssl_ctx == lws_tls_ctx_from_wsi(wsi)) {
|
2017-10-18 09:41:44 +08:00
|
|
|
lwsl_info("setting wsi to vh %s\n", vh->name);
|
vhost_destroy: use vhost wsi reference counting to trigger destroy
This changes the vhost destroy flow to only hand off the listen
socket if another vhost sharing it, and mark the vhost as
being_destroyed.
Each tsi calls lws_check_deferred_free() once a second, if it sees
any vhost being_destroyed there, it closes all wsi on its tsi on
the same vhost, one time.
As the wsi on the vhost complete close (ie, after libuv async close
if on libuv event loop), they decrement a reference count for all
wsi open on the vhost. The tsi who closes the last one then
completes the destroy flow for the vhost itself... it's random
which tsi completes the vhost destroy but since there are no
wsi left on the vhost, and it holds the context lock, nothing
can conflict.
The advantage of this is that owning tsi do the close for wsi
that are bound to the vhost under destruction, at a time when
they are guaranteed to be idle for service, and they do it with
both vhost and context locks owned, so no other service thread
can conflict for stuff protected by those either.
For the situation the user code may have allocations attached to
the vhost, this adds args to lws_vhost_destroy() to allow destroying
the user allocations just before the vhost is freed.
2018-06-16 09:31:07 +08:00
|
|
|
lws_vhost_bind_wsi(vh, wsi);
|
2017-10-18 09:41:44 +08:00
|
|
|
break;
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
2017-10-18 09:41:44 +08:00
|
|
|
vh = vh->vhost_next;
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
/* OK, we are accepted... give him some time to negotiate */
|
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
|
2020-12-12 06:21:40 +00:00
|
|
|
(int)context->timeout_secs);
|
2017-10-18 09:41:44 +08:00
|
|
|
|
2018-04-02 11:55:17 +08:00
|
|
|
lwsi_set_state(wsi, LRS_ESTABLISHED);
|
2020-04-19 08:43:01 +01:00
|
|
|
if (lws_tls_server_conn_alpn(wsi)) {
|
|
|
|
lwsl_warn("%s: fail on alpn\n", __func__);
|
2017-10-18 09:41:44 +08:00
|
|
|
goto fail;
|
2020-04-19 08:43:01 +01:00
|
|
|
}
|
2017-10-18 09:41:44 +08:00
|
|
|
lwsl_debug("accepted new SSL conn\n");
|
|
|
|
break;
|
2018-04-02 11:55:17 +08:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2017-10-18 09:41:44 +08:00
|
|
|
|
2018-11-29 08:47:49 +08:00
|
|
|
notls_accepted:
|
|
|
|
lwsi_set_state(wsi, LRS_ESTABLISHED);
|
2018-11-29 08:29:48 +08:00
|
|
|
|
2018-11-29 08:47:49 +08:00
|
|
|
return 0;
|
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
fail:
|
|
|
|
return 1;
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
|
|
|
|