2016-03-29 08:51:42 +08:00
|
|
|
/*
|
2017-10-18 09:41:44 +08:00
|
|
|
* libwebsockets - client-related ssl code independent of backend
|
2016-03-29 08:51:42 +08:00
|
|
|
*
|
2018-11-23 08:47:56 +08:00
|
|
|
* Copyright (C) 2010-2018 Andy Green <andy@warmcat.com>
|
2016-03-29 08:51:42 +08:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation:
|
|
|
|
* version 2.1 of the License.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
* MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
2018-05-03 10:49:36 +08:00
|
|
|
#include "core/private.h"
|
2016-03-29 08:51:42 +08:00
|
|
|
|
|
|
|
int
|
|
|
|
lws_ssl_client_connect1(struct lws *wsi)
|
|
|
|
{
|
|
|
|
struct lws_context *context = wsi->context;
|
2016-04-17 11:28:43 +08:00
|
|
|
int n = 0;
|
2016-03-29 08:51:42 +08:00
|
|
|
|
|
|
|
lws_latency_pre(context, wsi);
|
2017-10-18 09:41:44 +08:00
|
|
|
n = lws_tls_client_connect(wsi);
|
2018-04-02 11:55:17 +08:00
|
|
|
lws_latency(context, wsi, "SSL_connect hs", n, n > 0);
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
switch (n) {
|
|
|
|
case LWS_SSL_CAPABLE_ERROR:
|
|
|
|
return -1;
|
|
|
|
case LWS_SSL_CAPABLE_DONE:
|
|
|
|
return 1; /* connected */
|
|
|
|
case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
|
|
|
|
lws_callback_on_writable(wsi);
|
|
|
|
/* fallthru */
|
2019-11-15 09:15:37 +00:00
|
|
|
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
2017-10-18 09:41:44 +08:00
|
|
|
case LWS_SSL_CAPABLE_MORE_SERVICE_READ:
|
2018-04-02 11:55:17 +08:00
|
|
|
lwsi_set_state(wsi, LRS_WAITING_SSL);
|
2017-10-18 09:41:44 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0; /* retry */
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-03-24 17:52:57 +01:00
|
|
|
lws_ssl_client_connect2(struct lws *wsi, char *errbuf, int len)
|
2016-03-29 08:51:42 +08:00
|
|
|
{
|
2016-04-17 11:28:43 +08:00
|
|
|
int n = 0;
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2018-04-02 11:55:17 +08:00
|
|
|
if (lwsi_state(wsi) == LRS_WAITING_SSL) {
|
2017-10-18 09:41:44 +08:00
|
|
|
lws_latency_pre(wsi->context, wsi);
|
2017-01-17 07:01:02 +08:00
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
n = lws_tls_client_connect(wsi);
|
|
|
|
lwsl_debug("%s: SSL_connect says %d\n", __func__, n);
|
|
|
|
lws_latency(wsi->context, wsi,
|
2018-04-02 11:55:17 +08:00
|
|
|
"SSL_connect LRS_WAITING_SSL", n, n > 0);
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
switch (n) {
|
|
|
|
case LWS_SSL_CAPABLE_ERROR:
|
2018-03-24 17:52:57 +01:00
|
|
|
lws_snprintf(errbuf, len, "client connect failed");
|
2016-05-03 07:26:10 +08:00
|
|
|
return -1;
|
2017-10-18 09:41:44 +08:00
|
|
|
case LWS_SSL_CAPABLE_DONE:
|
|
|
|
break; /* connected */
|
|
|
|
case LWS_SSL_CAPABLE_MORE_SERVICE_WRITE:
|
|
|
|
lws_callback_on_writable(wsi);
|
|
|
|
/* fallthru */
|
|
|
|
case LWS_SSL_CAPABLE_MORE_SERVICE_READ:
|
2018-04-02 11:55:17 +08:00
|
|
|
lwsi_set_state(wsi, LRS_WAITING_SSL);
|
2017-10-18 09:41:44 +08:00
|
|
|
/* fallthru */
|
|
|
|
case LWS_SSL_CAPABLE_MORE_SERVICE:
|
|
|
|
return 0;
|
2016-03-29 08:51:42 +08:00
|
|
|
}
|
|
|
|
}
|
2017-01-10 09:31:23 +08:00
|
|
|
|
2018-03-24 17:52:57 +01:00
|
|
|
if (lws_tls_client_confirm_peer_cert(wsi, errbuf, len))
|
2017-10-18 09:41:44 +08:00
|
|
|
return -1;
|
2016-03-29 08:51:42 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-27 08:27:16 +08:00
|
|
|
int lws_context_init_client_ssl(const struct lws_context_creation_info *info,
|
2016-05-12 19:39:29 +08:00
|
|
|
struct lws_vhost *vhost)
|
2016-03-29 08:51:42 +08:00
|
|
|
{
|
2017-02-22 07:28:13 +08:00
|
|
|
const char *private_key_filepath = info->ssl_private_key_filepath;
|
2017-03-16 10:46:31 +08:00
|
|
|
const char *cert_filepath = info->ssl_cert_filepath;
|
2018-11-23 08:47:56 +08:00
|
|
|
const char *ca_filepath = info->ssl_ca_filepath;
|
|
|
|
const char *cipher_list = info->ssl_cipher_list;
|
2017-10-18 09:41:44 +08:00
|
|
|
struct lws wsi;
|
2016-03-29 08:51:42 +08:00
|
|
|
|
2018-11-29 08:47:49 +08:00
|
|
|
if (vhost->options & LWS_SERVER_OPTION_ADOPT_APPLY_LISTEN_ACCEPT_CONFIG)
|
2017-10-16 16:59:57 +08:00
|
|
|
return 0;
|
|
|
|
|
2019-03-08 15:26:33 +08:00
|
|
|
if (vhost->tls.ssl_ctx) {
|
|
|
|
cert_filepath = NULL;
|
|
|
|
private_key_filepath = NULL;
|
|
|
|
ca_filepath = NULL;
|
|
|
|
}
|
|
|
|
|
2017-02-22 07:28:13 +08:00
|
|
|
/*
|
|
|
|
* for backwards-compatibility default to using ssl_... members, but
|
|
|
|
* if the newer client-specific ones are given, use those
|
|
|
|
*/
|
|
|
|
if (info->client_ssl_cipher_list)
|
|
|
|
cipher_list = info->client_ssl_cipher_list;
|
|
|
|
if (info->client_ssl_cert_filepath)
|
|
|
|
cert_filepath = info->client_ssl_cert_filepath;
|
|
|
|
if (info->client_ssl_private_key_filepath)
|
|
|
|
private_key_filepath = info->client_ssl_private_key_filepath;
|
2017-10-18 09:41:44 +08:00
|
|
|
|
2017-09-02 10:50:54 +08:00
|
|
|
if (info->client_ssl_ca_filepath)
|
|
|
|
ca_filepath = info->client_ssl_ca_filepath;
|
2017-02-22 07:28:13 +08:00
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
|
|
|
|
return 0;
|
|
|
|
|
2018-05-01 12:41:42 +08:00
|
|
|
if (vhost->tls.ssl_client_ctx)
|
2017-07-08 16:01:34 +08:00
|
|
|
return 0;
|
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
if (info->provided_client_ssl_ctx) {
|
|
|
|
/* use the provided OpenSSL context if given one */
|
2018-05-01 12:41:42 +08:00
|
|
|
vhost->tls.ssl_client_ctx = info->provided_client_ssl_ctx;
|
2016-03-29 08:51:42 +08:00
|
|
|
/* nothing for lib to delete */
|
2018-05-01 12:41:42 +08:00
|
|
|
vhost->tls.user_supplied_ssl_ctx = 1;
|
2016-05-12 19:39:29 +08:00
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-18 09:41:44 +08:00
|
|
|
if (lws_tls_client_create_vhost_context(vhost, info, cipher_list,
|
2018-10-26 09:44:58 +08:00
|
|
|
ca_filepath,
|
|
|
|
info->client_ssl_ca_mem,
|
|
|
|
info->client_ssl_ca_mem_len,
|
|
|
|
cert_filepath,
|
2019-01-11 13:13:40 +08:00
|
|
|
info->client_ssl_cert_mem,
|
|
|
|
info->client_ssl_cert_mem_len,
|
2017-10-18 09:41:44 +08:00
|
|
|
private_key_filepath))
|
2016-03-29 08:51:42 +08:00
|
|
|
return 1;
|
|
|
|
|
2019-08-07 10:41:03 +01:00
|
|
|
lwsl_info("created client ssl context for %s\n", vhost->name);
|
2017-09-02 10:50:54 +08:00
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
/*
|
|
|
|
* give him a fake wsi with context set, so he can use
|
|
|
|
* lws_get_context() in the callback
|
|
|
|
*/
|
|
|
|
memset(&wsi, 0, sizeof(wsi));
|
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
|
|
|
wsi.vhost = vhost; /* not a real bound wsi */
|
2016-03-29 08:51:42 +08:00
|
|
|
wsi.context = vhost->context;
|
|
|
|
|
|
|
|
vhost->protocols[0].callback(&wsi,
|
|
|
|
LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS,
|
2018-11-23 08:47:56 +08:00
|
|
|
vhost->tls.ssl_client_ctx, NULL, 0);
|
2016-03-29 08:51:42 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|