2014-04-03 10:17:00 +08:00
|
|
|
/*
|
|
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
|
|
*
|
2017-04-03 14:09:37 +08:00
|
|
|
* Copyright (C) 2010-2017 Andy Green <andy@warmcat.com>
|
2014-04-03 10:17:00 +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
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "private-libwebsockets.h"
|
2016-02-18 20:36:09 +08:00
|
|
|
|
2017-04-19 20:28:48 +08:00
|
|
|
/* workaround for mingw */
|
|
|
|
#if !defined(ECONNABORTED)
|
|
|
|
#define ECONNABORTED 103
|
|
|
|
#endif
|
|
|
|
|
2017-03-16 10:46:31 +08:00
|
|
|
int lws_alloc_vfs_file(struct lws_context *context, const char *filename, uint8_t **buf,
|
2017-03-11 11:51:06 +08:00
|
|
|
lws_filepos_t *amount)
|
|
|
|
{
|
|
|
|
lws_filepos_t len;
|
|
|
|
lws_fop_flags_t flags = LWS_O_RDONLY;
|
|
|
|
lws_fop_fd_t fops_fd = lws_vfs_file_open(
|
|
|
|
lws_get_fops(context), filename, &flags);
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
if (!fops_fd)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
len = lws_vfs_get_length(fops_fd);
|
|
|
|
|
2017-06-09 20:20:42 +08:00
|
|
|
*buf = malloc((size_t)len);
|
2017-07-19 14:17:39 +08:00
|
|
|
if (!*buf)
|
2017-03-11 11:51:06 +08:00
|
|
|
goto bail;
|
|
|
|
|
|
|
|
if (lws_vfs_file_read(fops_fd, amount, *buf, len))
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
bail:
|
|
|
|
lws_vfs_file_close(&fops_fd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2017-03-16 10:46:31 +08:00
|
|
|
|
|
|
|
#if defined(LWS_WITH_ESP32)
|
|
|
|
int alloc_file(struct lws_context *context, const char *filename, uint8_t **buf,
|
|
|
|
lws_filepos_t *amount)
|
|
|
|
{
|
|
|
|
nvs_handle nvh;
|
|
|
|
size_t s;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
ESP_ERROR_CHECK(nvs_open("lws-station", NVS_READWRITE, &nvh));
|
|
|
|
if (nvs_get_blob(nvh, filename, NULL, &s) != ESP_OK) {
|
|
|
|
n = 1;
|
|
|
|
goto bail;
|
|
|
|
}
|
|
|
|
*buf = malloc(s);
|
|
|
|
if (!*buf) {
|
|
|
|
n = 2;
|
|
|
|
goto bail;
|
|
|
|
}
|
2017-05-11 15:02:01 +08:00
|
|
|
if (nvs_get_blob(nvh, filename, (char *)*buf, &s) != ESP_OK) {
|
|
|
|
free(*buf);
|
2017-03-16 10:46:31 +08:00
|
|
|
n = 1;
|
2017-05-11 15:02:01 +08:00
|
|
|
goto bail;
|
|
|
|
}
|
2017-03-16 10:46:31 +08:00
|
|
|
|
|
|
|
*amount = s;
|
|
|
|
|
|
|
|
bail:
|
|
|
|
nvs_close(nvh);
|
|
|
|
|
|
|
|
return n;
|
|
|
|
}
|
2017-05-11 15:02:01 +08:00
|
|
|
int alloc_pem_to_der_file(struct lws_context *context, const char *filename, uint8_t **buf,
|
|
|
|
lws_filepos_t *amount)
|
|
|
|
{
|
|
|
|
uint8_t *pem, *p, *q, *end;
|
|
|
|
lws_filepos_t len;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
n = alloc_file(context, filename, &pem, &len);
|
|
|
|
if (n)
|
|
|
|
return n;
|
|
|
|
|
|
|
|
/* trim the first line */
|
|
|
|
|
|
|
|
p = pem;
|
|
|
|
end = p + len;
|
|
|
|
if (strncmp((char *)p, "-----", 5))
|
|
|
|
goto bail;
|
|
|
|
p += 5;
|
|
|
|
while (p < end && *p != '\n' && *p != '-')
|
|
|
|
p++;
|
|
|
|
|
|
|
|
if (*p != '-')
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
while (p < end && *p != '\n')
|
|
|
|
p++;
|
|
|
|
|
|
|
|
if (p >= end)
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
/* trim the last line */
|
|
|
|
|
|
|
|
q = end - 2;
|
|
|
|
|
|
|
|
while (q > pem && *q != '\n')
|
|
|
|
q--;
|
|
|
|
|
|
|
|
if (*q != '\n')
|
|
|
|
goto bail;
|
|
|
|
|
|
|
|
*q = '\0';
|
|
|
|
|
|
|
|
*amount = lws_b64_decode_string((char *)p, (char *)pem, len);
|
|
|
|
*buf = pem;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
bail:
|
|
|
|
free(pem);
|
|
|
|
|
|
|
|
return 4;
|
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2016-04-17 11:28:43 +08:00
|
|
|
|
2016-03-28 10:10:43 +08:00
|
|
|
int openssl_websocket_private_data_index,
|
|
|
|
openssl_SSL_CTX_private_data_index;
|
2014-04-03 10:17:00 +08:00
|
|
|
|
2016-04-17 11:28:43 +08:00
|
|
|
int lws_ssl_get_error(struct lws *wsi, int n)
|
|
|
|
{
|
2017-03-11 11:51:06 +08:00
|
|
|
if (!wsi->ssl)
|
|
|
|
return 99;
|
|
|
|
lwsl_debug("%s: %p %d\n", __func__, wsi->ssl, n);
|
2016-04-17 11:28:43 +08:00
|
|
|
return SSL_get_error(wsi->ssl, n);
|
|
|
|
}
|
|
|
|
|
2016-12-21 09:32:25 +08:00
|
|
|
/* Copies a string describing the code returned by lws_ssl_get_error(),
|
|
|
|
* which may also contain system error information in the case of SSL_ERROR_SYSCALL,
|
|
|
|
* into buf up to len.
|
|
|
|
* Returns a pointer to buf.
|
|
|
|
*
|
|
|
|
* Note: the lws_ssl_get_error() code is *not* an error code that can be passed
|
|
|
|
* to ERR_error_string(),
|
|
|
|
*
|
|
|
|
* ret is the return value originally passed to lws_ssl_get_error(), needed to disambiguate
|
|
|
|
* SYS_ERROR_SYSCALL.
|
|
|
|
*
|
|
|
|
* See man page for SSL_get_error().
|
|
|
|
*
|
|
|
|
* Not thread safe, uses strerror()
|
|
|
|
*/
|
|
|
|
char* lws_ssl_get_error_string(int status, int ret, char *buf, size_t len) {
|
|
|
|
switch (status) {
|
|
|
|
case SSL_ERROR_NONE: return strncpy(buf, "SSL_ERROR_NONE", len);
|
|
|
|
case SSL_ERROR_ZERO_RETURN: return strncpy(buf, "SSL_ERROR_ZERO_RETURN", len);
|
|
|
|
case SSL_ERROR_WANT_READ: return strncpy(buf, "SSL_ERROR_WANT_READ", len);
|
|
|
|
case SSL_ERROR_WANT_WRITE: return strncpy(buf, "SSL_ERROR_WANT_WRITE", len);
|
|
|
|
case SSL_ERROR_WANT_CONNECT: return strncpy(buf, "SSL_ERROR_WANT_CONNECT", len);
|
|
|
|
case SSL_ERROR_WANT_ACCEPT: return strncpy(buf, "SSL_ERROR_WANT_ACCEPT", len);
|
|
|
|
case SSL_ERROR_WANT_X509_LOOKUP: return strncpy(buf, "SSL_ERROR_WANT_X509_LOOKUP", len);
|
|
|
|
case SSL_ERROR_SYSCALL:
|
|
|
|
switch (ret) {
|
|
|
|
case 0:
|
2017-05-03 20:25:16 +08:00
|
|
|
lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: EOF");
|
2016-12-21 09:32:25 +08:00
|
|
|
return buf;
|
|
|
|
case -1:
|
2017-01-17 07:01:02 +08:00
|
|
|
#ifndef LWS_PLAT_OPTEE
|
2017-05-03 20:25:16 +08:00
|
|
|
lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %s", strerror(errno));
|
2017-01-17 07:01:02 +08:00
|
|
|
#else
|
2017-05-03 20:25:16 +08:00
|
|
|
lws_snprintf(buf, len, "SSL_ERROR_SYSCALL: %d", errno);
|
2017-01-17 07:01:02 +08:00
|
|
|
#endif
|
|
|
|
return buf;
|
2016-12-21 09:32:25 +08:00
|
|
|
default:
|
|
|
|
return strncpy(buf, "SSL_ERROR_SYSCALL", len);
|
|
|
|
}
|
|
|
|
case SSL_ERROR_SSL: return "SSL_ERROR_SSL";
|
|
|
|
default: return "SSL_ERROR_UNKNOWN";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-03 07:26:10 +08:00
|
|
|
void
|
|
|
|
lws_ssl_elaborate_error(void)
|
|
|
|
{
|
2017-03-11 11:51:06 +08:00
|
|
|
#if defined(LWS_WITH_ESP32)
|
|
|
|
#else
|
2016-05-03 07:26:10 +08:00
|
|
|
char buf[256];
|
|
|
|
u_long err;
|
|
|
|
|
|
|
|
while ((err = ERR_get_error()) != 0) {
|
|
|
|
ERR_error_string_n(err, buf, sizeof(buf));
|
|
|
|
lwsl_err("*** %s\n", buf);
|
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2016-05-03 07:26:10 +08:00
|
|
|
}
|
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
static int
|
|
|
|
lws_context_init_ssl_pem_passwd_cb(char * buf, int size, int rwflag, void *userdata)
|
2014-11-18 07:53:20 +08:00
|
|
|
{
|
2015-12-04 11:30:53 +08:00
|
|
|
struct lws_context_creation_info * info =
|
|
|
|
(struct lws_context_creation_info *)userdata;
|
2014-11-18 07:53:20 +08:00
|
|
|
|
|
|
|
strncpy(buf, info->ssl_private_key_password, size);
|
|
|
|
buf[size - 1] = '\0';
|
|
|
|
|
|
|
|
return strlen(buf);
|
|
|
|
}
|
|
|
|
|
2016-03-29 08:51:42 +08:00
|
|
|
void
|
|
|
|
lws_ssl_bind_passphrase(SSL_CTX *ssl_ctx, struct lws_context_creation_info *info)
|
2014-11-18 07:53:20 +08:00
|
|
|
{
|
|
|
|
if (!info->ssl_private_key_password)
|
|
|
|
return;
|
|
|
|
/*
|
|
|
|
* password provided, set ssl callback and user data
|
|
|
|
* for checking password which will be trigered during
|
|
|
|
* SSL_CTX_use_PrivateKey_file function
|
|
|
|
*/
|
2014-11-20 12:10:40 +08:00
|
|
|
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)info);
|
2015-12-17 17:03:59 +08:00
|
|
|
SSL_CTX_set_default_passwd_cb(ssl_ctx, lws_context_init_ssl_pem_passwd_cb);
|
2014-11-18 07:53:20 +08:00
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2014-11-18 07:53:20 +08:00
|
|
|
|
2016-03-28 10:10:43 +08:00
|
|
|
int
|
|
|
|
lws_context_init_ssl_library(struct lws_context_creation_info *info)
|
|
|
|
{
|
|
|
|
#ifdef USE_WOLFSSL
|
|
|
|
#ifdef USE_OLD_CYASSL
|
|
|
|
lwsl_notice(" Compiled with CyaSSL support\n");
|
|
|
|
#else
|
|
|
|
lwsl_notice(" Compiled with wolfSSL support\n");
|
|
|
|
#endif
|
2016-04-17 11:28:43 +08:00
|
|
|
#else
|
2017-01-17 07:01:02 +08:00
|
|
|
#if defined(LWS_USE_BORINGSSL)
|
|
|
|
lwsl_notice(" Compiled with BoringSSL support\n");
|
2016-03-28 10:10:43 +08:00
|
|
|
#else
|
|
|
|
lwsl_notice(" Compiled with OpenSSL support\n");
|
2016-04-17 11:28:43 +08:00
|
|
|
#endif
|
|
|
|
#endif
|
2016-03-28 10:10:43 +08:00
|
|
|
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
|
|
|
|
lwsl_notice(" SSL disabled: no LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* basic openssl init */
|
|
|
|
|
2017-01-17 07:01:02 +08:00
|
|
|
lwsl_notice("Doing SSL library init\n");
|
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
2016-03-28 10:10:43 +08:00
|
|
|
SSL_library_init();
|
|
|
|
OpenSSL_add_all_algorithms();
|
|
|
|
SSL_load_error_strings();
|
|
|
|
|
|
|
|
openssl_websocket_private_data_index =
|
|
|
|
SSL_get_ex_new_index(0, "lws", NULL, NULL, NULL);
|
|
|
|
|
|
|
|
openssl_SSL_CTX_private_data_index = SSL_CTX_get_ex_new_index(0,
|
|
|
|
NULL, NULL, NULL, NULL);
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2016-03-28 10:10:43 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-04-03 10:17:00 +08:00
|
|
|
LWS_VISIBLE void
|
2016-03-28 10:10:43 +08:00
|
|
|
lws_ssl_destroy(struct lws_vhost *vhost)
|
2014-04-03 10:17:00 +08:00
|
|
|
{
|
2016-04-17 11:28:43 +08:00
|
|
|
if (!lws_check_opt(vhost->context->options,
|
|
|
|
LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
|
2016-03-23 09:22:11 +08:00
|
|
|
return;
|
|
|
|
|
2016-03-28 10:10:43 +08:00
|
|
|
if (vhost->ssl_ctx)
|
|
|
|
SSL_CTX_free(vhost->ssl_ctx);
|
|
|
|
if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx)
|
|
|
|
SSL_CTX_free(vhost->ssl_client_ctx);
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
2014-04-03 10:17:00 +08:00
|
|
|
|
2017-01-07 11:29:32 +08:00
|
|
|
// after 1.1.0 no need
|
|
|
|
#if (OPENSSL_VERSION_NUMBER < 0x10100000)
|
|
|
|
// <= 1.0.1f = old api, 1.0.1g+ = new api
|
|
|
|
#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
|
2014-11-05 15:35:05 +08:00
|
|
|
ERR_remove_state(0);
|
2016-04-10 09:33:54 +08:00
|
|
|
#else
|
2017-01-07 11:29:32 +08:00
|
|
|
#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
|
|
|
|
!defined(LIBRESSL_VERSION_NUMBER) && \
|
|
|
|
!defined(OPENSSL_IS_BORINGSSL)
|
2016-04-10 09:33:54 +08:00
|
|
|
ERR_remove_thread_state();
|
2014-11-05 15:35:05 +08:00
|
|
|
#else
|
2014-10-27 11:38:03 +08:00
|
|
|
ERR_remove_thread_state(NULL);
|
2016-04-10 09:33:54 +08:00
|
|
|
#endif
|
2017-07-15 17:51:32 +08:00
|
|
|
#endif
|
|
|
|
// after 1.1.0 no need
|
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10002000) && (OPENSSL_VERSION_NUMBER <= 0x10100000)
|
|
|
|
SSL_COMP_free_compression_methods();
|
2014-11-05 15:35:05 +08:00
|
|
|
#endif
|
2014-04-03 10:17:00 +08:00
|
|
|
ERR_free_strings();
|
|
|
|
EVP_cleanup();
|
|
|
|
CRYPTO_cleanup_all_ex_data();
|
2016-04-17 11:28:43 +08:00
|
|
|
#endif
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2014-04-03 10:17:00 +08:00
|
|
|
}
|
|
|
|
|
2015-01-29 08:36:18 +08:00
|
|
|
LWS_VISIBLE void
|
2015-12-15 21:15:58 +08:00
|
|
|
lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
|
2015-01-29 08:36:18 +08:00
|
|
|
{
|
2015-12-15 21:15:58 +08:00
|
|
|
struct lws_context *context = wsi->context;
|
2016-01-19 03:34:24 +08:00
|
|
|
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
2015-12-15 21:15:58 +08:00
|
|
|
|
2015-01-29 08:36:18 +08:00
|
|
|
if (!wsi->pending_read_list_prev &&
|
|
|
|
!wsi->pending_read_list_next &&
|
2016-01-19 03:34:24 +08:00
|
|
|
pt->pending_read_list != wsi)
|
2015-01-29 08:36:18 +08:00
|
|
|
/* we are not on the list */
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* point previous guy's next to our next */
|
|
|
|
if (!wsi->pending_read_list_prev)
|
2016-01-19 03:34:24 +08:00
|
|
|
pt->pending_read_list = wsi->pending_read_list_next;
|
2015-01-29 08:36:18 +08:00
|
|
|
else
|
|
|
|
wsi->pending_read_list_prev->pending_read_list_next =
|
|
|
|
wsi->pending_read_list_next;
|
|
|
|
|
|
|
|
/* point next guy's previous to our previous */
|
|
|
|
if (wsi->pending_read_list_next)
|
|
|
|
wsi->pending_read_list_next->pending_read_list_prev =
|
|
|
|
wsi->pending_read_list_prev;
|
|
|
|
|
|
|
|
wsi->pending_read_list_prev = NULL;
|
|
|
|
wsi->pending_read_list_next = NULL;
|
|
|
|
}
|
|
|
|
|
2014-04-06 06:26:35 +01:00
|
|
|
LWS_VISIBLE int
|
2015-12-15 21:15:58 +08:00
|
|
|
lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len)
|
2014-04-06 06:26:35 +01:00
|
|
|
{
|
2015-12-15 21:15:58 +08:00
|
|
|
struct lws_context *context = wsi->context;
|
2016-01-19 03:34:24 +08:00
|
|
|
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
2016-04-17 11:28:43 +08:00
|
|
|
int n = 0;
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
|
|
|
int ssl_read_errno = 0;
|
|
|
|
#endif
|
2014-04-06 06:26:35 +01:00
|
|
|
|
|
|
|
if (!wsi->ssl)
|
2015-12-15 21:15:58 +08:00
|
|
|
return lws_ssl_capable_read_no_ssl(wsi, buf, len);
|
2014-04-06 06:26:35 +01:00
|
|
|
|
2017-05-07 10:02:03 +08:00
|
|
|
lws_stats_atomic_bump(context, pt, LWSSTATS_C_API_READ, 1);
|
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
errno = 0;
|
2014-04-06 06:26:35 +01:00
|
|
|
n = SSL_read(wsi->ssl, buf, len);
|
2017-03-11 11:51:06 +08:00
|
|
|
#if defined(LWS_WITH_ESP32)
|
|
|
|
if (!n && errno == ENOTCONN) {
|
|
|
|
lwsl_debug("%p: SSL_read ENOTCONN\n", wsi);
|
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
|
|
|
}
|
|
|
|
#endif
|
2017-05-13 10:26:59 +08:00
|
|
|
#if defined(LWS_WITH_STATS)
|
|
|
|
if (!wsi->seen_rx) {
|
|
|
|
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_SSL_RX_DELAY,
|
|
|
|
time_in_microseconds() - wsi->accept_start_us);
|
|
|
|
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNS_HAD_RX, 1);
|
|
|
|
wsi->seen_rx = 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-04-17 11:28:43 +08:00
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
lwsl_debug("%p: SSL_read says %d\n", wsi, n);
|
2015-12-03 21:37:34 +08:00
|
|
|
/* manpage: returning 0 means connection shut down */
|
2017-01-17 07:01:02 +08:00
|
|
|
if (!n) {
|
2017-03-16 10:46:31 +08:00
|
|
|
n = lws_ssl_get_error(wsi, n);
|
|
|
|
lwsl_debug("%p: ssl err %d errno %d\n", wsi, n, errno);
|
|
|
|
if (n == SSL_ERROR_ZERO_RETURN)
|
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
2017-02-26 04:24:40 +08:00
|
|
|
|
2017-03-16 10:46:31 +08:00
|
|
|
if (n == SSL_ERROR_SYSCALL) {
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
2017-03-16 10:46:31 +08:00
|
|
|
int err = ERR_get_error();
|
|
|
|
if (err == 0 && (ssl_read_errno == EPIPE ||
|
|
|
|
ssl_read_errno == ECONNABORTED ||
|
|
|
|
ssl_read_errno == 0))
|
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2017-03-16 10:46:31 +08:00
|
|
|
}
|
2017-02-26 04:24:40 +08:00
|
|
|
|
2017-02-22 09:54:47 +08:00
|
|
|
lwsl_err("%s failed: %s\n",__func__,
|
|
|
|
ERR_error_string(lws_ssl_get_error(wsi, 0), NULL));
|
2017-03-16 10:46:31 +08:00
|
|
|
lws_ssl_elaborate_error();
|
2017-01-17 07:01:02 +08:00
|
|
|
|
2015-12-03 21:37:34 +08:00
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
2017-01-17 07:01:02 +08:00
|
|
|
}
|
2015-12-03 21:37:34 +08:00
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
if (n < 0) {
|
2016-04-17 11:28:43 +08:00
|
|
|
n = lws_ssl_get_error(wsi, n);
|
2017-05-11 15:02:01 +08:00
|
|
|
// lwsl_notice("get_ssl_err result %d\n", n);
|
2017-04-03 14:09:37 +08:00
|
|
|
if (n == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) {
|
|
|
|
lwsl_debug("%s: WANT_READ\n", __func__);
|
|
|
|
lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
|
|
|
|
return LWS_SSL_CAPABLE_MORE_SERVICE;
|
|
|
|
}
|
|
|
|
if (n == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) {
|
|
|
|
lwsl_debug("%s: WANT_WRITE\n", __func__);
|
2017-03-16 10:46:31 +08:00
|
|
|
lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi);
|
2015-12-17 17:03:59 +08:00
|
|
|
return LWS_SSL_CAPABLE_MORE_SERVICE;
|
2017-03-16 10:46:31 +08:00
|
|
|
}
|
2015-01-29 08:36:18 +08:00
|
|
|
|
2017-04-03 14:09:37 +08:00
|
|
|
|
2017-01-17 07:01:02 +08:00
|
|
|
lwsl_err("%s failed2: %s\n",__func__,
|
|
|
|
ERR_error_string(lws_ssl_get_error(wsi, 0), NULL));
|
2017-03-16 10:46:31 +08:00
|
|
|
lws_ssl_elaborate_error();
|
2017-01-17 07:01:02 +08:00
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
2014-10-08 11:29:49 +08:00
|
|
|
}
|
2015-12-17 17:03:59 +08:00
|
|
|
|
2017-05-07 10:02:03 +08:00
|
|
|
lws_stats_atomic_bump(context, pt, LWSSTATS_B_READ, n);
|
|
|
|
|
2016-04-15 13:02:25 +08:00
|
|
|
if (wsi->vhost)
|
context deprecation
1) This makes lwsws run a parent process with the original permissions.
But this process is only able to respond to SIGHUP, it doesn't do anything
else.
2) You can send this parent process a SIGHUP now to cause it to
- close listening sockets in existing lwsws processes
- mark those processes as to exit when the number of active connections
on the falls to zero
- spawn a fresh child process from scratch, using latest configuration
file content, latest plugins, etc. It can now reopen listening sockets
if it chooses to, or open different listen ports or whatever.
Notes:
1) lws_context_destroy() has been split into two pieces... the reason for
the split is the first part closes the per-vhost protocols, but since
they may have created libuv objects in the per-vhost protocol storage,
these cannot be freed until after the loop has been run.
That's the purpose of the second part of the context destruction,
lws_context_destroy2().
For compatibility, if you are not using libuv, the first part calls the
second part. However if you are using libuv, you must now call the
second part from your own main.c after the first part.
2016-12-16 07:37:43 +08:00
|
|
|
wsi->vhost->conn_stats.rx += n;
|
2016-04-15 13:02:25 +08:00
|
|
|
|
2016-07-15 13:41:38 +08:00
|
|
|
lws_restart_ws_ping_pong_timer(wsi);
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
/*
|
|
|
|
* if it was our buffer that limited what we read,
|
|
|
|
* check if SSL has additional data pending inside SSL buffers.
|
|
|
|
*
|
|
|
|
* Because these won't signal at the network layer with POLLIN
|
|
|
|
* and if we don't realize, this data will sit there forever
|
|
|
|
*/
|
|
|
|
if (n != len)
|
|
|
|
goto bail;
|
|
|
|
if (!wsi->ssl)
|
|
|
|
goto bail;
|
2017-02-22 09:54:47 +08:00
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
if (!SSL_pending(wsi->ssl))
|
|
|
|
goto bail;
|
2017-02-22 09:54:47 +08:00
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
if (wsi->pending_read_list_next)
|
|
|
|
return n;
|
|
|
|
if (wsi->pending_read_list_prev)
|
|
|
|
return n;
|
2016-01-19 03:34:24 +08:00
|
|
|
if (pt->pending_read_list == wsi)
|
2015-12-17 17:03:59 +08:00
|
|
|
return n;
|
|
|
|
|
|
|
|
/* add us to the linked list of guys with pending ssl */
|
2016-01-19 03:34:24 +08:00
|
|
|
if (pt->pending_read_list)
|
|
|
|
pt->pending_read_list->pending_read_list_prev = wsi;
|
2015-12-17 17:03:59 +08:00
|
|
|
|
2016-01-19 03:34:24 +08:00
|
|
|
wsi->pending_read_list_next = pt->pending_read_list;
|
2015-12-17 17:03:59 +08:00
|
|
|
wsi->pending_read_list_prev = NULL;
|
2016-01-19 03:34:24 +08:00
|
|
|
pt->pending_read_list = wsi;
|
2015-12-17 17:03:59 +08:00
|
|
|
|
|
|
|
return n;
|
|
|
|
bail:
|
|
|
|
lws_ssl_remove_wsi_from_buffered_list(wsi);
|
|
|
|
|
|
|
|
return n;
|
2014-04-06 06:26:35 +01:00
|
|
|
}
|
|
|
|
|
2015-08-19 16:23:33 +02:00
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_ssl_pending(struct lws *wsi)
|
2015-08-19 16:23:33 +02:00
|
|
|
{
|
|
|
|
if (!wsi->ssl)
|
|
|
|
return 0;
|
2017-02-22 09:54:47 +08:00
|
|
|
|
2015-08-19 16:23:33 +02:00
|
|
|
return SSL_pending(wsi->ssl);
|
|
|
|
}
|
|
|
|
|
2014-04-06 06:26:35 +01:00
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len)
|
2014-04-06 06:26:35 +01:00
|
|
|
{
|
|
|
|
int n;
|
2017-03-16 10:46:31 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
|
|
|
int ssl_read_errno = 0;
|
|
|
|
#endif
|
2014-04-06 06:26:35 +01:00
|
|
|
|
|
|
|
if (!wsi->ssl)
|
|
|
|
return lws_ssl_capable_write_no_ssl(wsi, buf, len);
|
2015-11-08 12:10:26 +08:00
|
|
|
|
2014-04-06 06:26:35 +01:00
|
|
|
n = SSL_write(wsi->ssl, buf, len);
|
2015-12-03 21:37:34 +08:00
|
|
|
if (n > 0)
|
2014-04-06 06:26:35 +01:00
|
|
|
return n;
|
|
|
|
|
2016-04-17 11:28:43 +08:00
|
|
|
n = lws_ssl_get_error(wsi, n);
|
2014-04-06 06:26:35 +01:00
|
|
|
if (n == SSL_ERROR_WANT_READ || n == SSL_ERROR_WANT_WRITE) {
|
2017-03-11 11:51:06 +08:00
|
|
|
if (n == SSL_ERROR_WANT_WRITE) {
|
2017-04-03 14:09:37 +08:00
|
|
|
lwsl_debug("%s: WANT_WRITE\n", __func__);
|
2014-04-06 06:26:35 +01:00
|
|
|
lws_set_blocking_send(wsi);
|
2017-03-11 11:51:06 +08:00
|
|
|
}
|
2014-04-06 06:26:35 +01:00
|
|
|
return LWS_SSL_CAPABLE_MORE_SERVICE;
|
|
|
|
}
|
2017-01-17 07:01:02 +08:00
|
|
|
|
2017-02-26 04:24:40 +08:00
|
|
|
if (n == SSL_ERROR_ZERO_RETURN)
|
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
2017-02-26 04:24:40 +08:00
|
|
|
if (n == SSL_ERROR_SYSCALL) {
|
2017-03-11 11:51:06 +08:00
|
|
|
|
2017-02-26 04:24:40 +08:00
|
|
|
int err = ERR_get_error();
|
|
|
|
if (err == 0
|
|
|
|
&& (ssl_read_errno == EPIPE
|
|
|
|
|| ssl_read_errno == ECONNABORTED
|
|
|
|
|| ssl_read_errno == 0))
|
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2017-02-26 04:24:40 +08:00
|
|
|
|
|
|
|
lwsl_err("%s failed: %s\n",__func__,
|
|
|
|
ERR_error_string(lws_ssl_get_error(wsi, 0), NULL));
|
2017-03-16 10:46:31 +08:00
|
|
|
lws_ssl_elaborate_error();
|
2015-12-17 17:03:59 +08:00
|
|
|
|
2014-04-06 06:26:35 +01:00
|
|
|
return LWS_SSL_CAPABLE_ERROR;
|
|
|
|
}
|
|
|
|
|
2017-03-16 10:46:31 +08:00
|
|
|
static int
|
|
|
|
lws_gate_accepts(struct lws_context *context, int on)
|
|
|
|
{
|
|
|
|
struct lws_vhost *v = context->vhost_list;
|
|
|
|
|
|
|
|
lwsl_info("gating accepts %d\n", on);
|
2017-05-15 07:30:06 +08:00
|
|
|
context->ssl_gate_accepts = !on;
|
|
|
|
#if defined(LWS_WITH_STATS)
|
|
|
|
context->updated = 1;
|
|
|
|
#endif
|
2017-03-16 10:46:31 +08:00
|
|
|
|
|
|
|
while (v) {
|
|
|
|
if (v->use_ssl && v->lserv_wsi) /* gate ability to accept incoming connections */
|
|
|
|
if (lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on, (LWS_POLLIN) * on))
|
|
|
|
lwsl_err("Unable to set accept POLLIN %d\n", on);
|
|
|
|
|
|
|
|
v = v->vhost_next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-20 11:46:49 +08:00
|
|
|
void
|
|
|
|
lws_ssl_info_callback(const SSL *ssl, int where, int ret)
|
|
|
|
{
|
|
|
|
struct lws *wsi;
|
|
|
|
struct lws_context *context;
|
|
|
|
struct lws_ssl_info si;
|
|
|
|
|
|
|
|
context = (struct lws_context *)SSL_CTX_get_ex_data(
|
|
|
|
SSL_get_SSL_CTX(ssl),
|
|
|
|
openssl_SSL_CTX_private_data_index);
|
|
|
|
if (!context)
|
|
|
|
return;
|
|
|
|
wsi = wsi_from_fd(context, SSL_get_fd(ssl));
|
|
|
|
if (!wsi)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!(where & wsi->vhost->ssl_info_event_mask))
|
|
|
|
return;
|
|
|
|
|
|
|
|
si.where = where;
|
|
|
|
si.ret = ret;
|
|
|
|
|
|
|
|
if (user_callback_handle_rxflow(wsi->protocol->callback,
|
|
|
|
wsi, LWS_CALLBACK_SSL_INFO,
|
|
|
|
wsi->user_space, &si, 0))
|
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
LWS_VISIBLE int
|
2015-12-04 11:08:32 +08:00
|
|
|
lws_ssl_close(struct lws *wsi)
|
2014-04-12 10:07:02 +08:00
|
|
|
{
|
2017-03-11 11:51:06 +08:00
|
|
|
lws_sockfd_type n;
|
2014-04-12 10:07:02 +08:00
|
|
|
|
|
|
|
if (!wsi->ssl)
|
|
|
|
return 0; /* not handled */
|
|
|
|
|
2017-06-20 11:46:49 +08:00
|
|
|
#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
|
|
|
|
/* kill ssl callbacks, becausse we will remove the fd from the
|
|
|
|
* table linking it to the wsi
|
|
|
|
*/
|
|
|
|
if (wsi->vhost->ssl_info_event_mask)
|
|
|
|
SSL_set_info_callback(wsi->ssl, NULL);
|
|
|
|
#endif
|
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
n = SSL_get_fd(wsi->ssl);
|
|
|
|
SSL_shutdown(wsi->ssl);
|
|
|
|
compatible_close(n);
|
|
|
|
SSL_free(wsi->ssl);
|
2015-12-03 09:44:15 +08:00
|
|
|
wsi->ssl = NULL;
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2017-04-07 20:51:44 +08:00
|
|
|
if (wsi->context->simultaneous_ssl_restriction &&
|
|
|
|
wsi->context->simultaneous_ssl-- ==
|
|
|
|
wsi->context->simultaneous_ssl_restriction)
|
2017-03-16 10:46:31 +08:00
|
|
|
/* we made space and can do an accept */
|
|
|
|
lws_gate_accepts(wsi->context, 1);
|
2017-05-15 07:30:06 +08:00
|
|
|
#if defined(LWS_WITH_STATS)
|
|
|
|
wsi->context->updated = 1;
|
|
|
|
#endif
|
2017-03-16 10:46:31 +08:00
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
return 1; /* handled */
|
|
|
|
}
|
|
|
|
|
2015-12-06 06:39:51 +08:00
|
|
|
/* leave all wsi close processing to the caller */
|
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
LWS_VISIBLE int
|
2016-01-26 20:56:56 +08:00
|
|
|
lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
|
2014-04-12 10:07:02 +08:00
|
|
|
{
|
2015-12-15 21:15:58 +08:00
|
|
|
struct lws_context *context = wsi->context;
|
2016-01-19 03:34:24 +08:00
|
|
|
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
2015-12-06 06:39:51 +08:00
|
|
|
int n, m;
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(USE_WOLFSSL) && !defined(LWS_WITH_ESP32)
|
2014-04-12 10:07:02 +08:00
|
|
|
BIO *bio;
|
|
|
|
#endif
|
2017-01-18 07:20:09 +08:00
|
|
|
char buf[256];
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2016-03-28 10:10:43 +08:00
|
|
|
if (!LWS_SSL_ENABLED(wsi->vhost))
|
2014-04-12 10:07:02 +08:00
|
|
|
return 0;
|
2016-01-29 15:30:05 +08:00
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
switch (wsi->mode) {
|
2016-01-26 20:56:56 +08:00
|
|
|
case LWSCM_SSL_INIT:
|
2017-02-12 20:32:49 +08:00
|
|
|
case LWSCM_SSL_INIT_RAW:
|
2016-04-12 09:02:32 +08:00
|
|
|
if (wsi->ssl)
|
|
|
|
lwsl_err("%s: leaking ssl\n", __func__);
|
|
|
|
if (accept_fd == LWS_SOCK_INVALID)
|
|
|
|
assert(0);
|
2017-04-07 20:51:44 +08:00
|
|
|
if (context->simultaneous_ssl_restriction &&
|
|
|
|
context->simultaneous_ssl >= context->simultaneous_ssl_restriction) {
|
2017-03-16 10:46:31 +08:00
|
|
|
lwsl_notice("unable to deal with SSL connection\n");
|
|
|
|
return 1;
|
|
|
|
}
|
2017-03-11 11:51:06 +08:00
|
|
|
errno = 0;
|
2016-03-28 10:10:43 +08:00
|
|
|
wsi->ssl = SSL_new(wsi->vhost->ssl_ctx);
|
2016-01-26 20:56:56 +08:00
|
|
|
if (wsi->ssl == NULL) {
|
2017-03-16 10:46:31 +08:00
|
|
|
lwsl_err("SSL_new failed: %d (errno %d)\n",
|
|
|
|
lws_ssl_get_error(wsi, 0), errno);
|
2017-03-11 11:51:06 +08:00
|
|
|
|
2017-03-16 10:46:31 +08:00
|
|
|
lws_ssl_elaborate_error();
|
2016-01-29 15:40:08 +08:00
|
|
|
if (accept_fd != LWS_SOCK_INVALID)
|
|
|
|
compatible_close(accept_fd);
|
2015-06-25 17:14:44 +02:00
|
|
|
goto fail;
|
2014-04-12 10:07:02 +08:00
|
|
|
}
|
2017-06-20 11:46:49 +08:00
|
|
|
#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
|
|
|
|
if (wsi->vhost->ssl_info_event_mask)
|
|
|
|
SSL_set_info_callback(wsi->ssl, lws_ssl_info_callback);
|
|
|
|
#endif
|
2017-04-07 20:51:44 +08:00
|
|
|
if (context->simultaneous_ssl_restriction &&
|
|
|
|
++context->simultaneous_ssl == context->simultaneous_ssl_restriction)
|
2017-03-16 10:46:31 +08:00
|
|
|
/* that was the last allowed SSL connection */
|
|
|
|
lws_gate_accepts(context, 0);
|
2017-05-15 07:30:06 +08:00
|
|
|
#if defined(LWS_WITH_STATS)
|
|
|
|
context->updated = 1;
|
|
|
|
#endif
|
2017-03-16 10:46:31 +08:00
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
2016-01-26 20:56:56 +08:00
|
|
|
SSL_set_ex_data(wsi->ssl,
|
2017-01-23 19:35:00 +08:00
|
|
|
openssl_websocket_private_data_index, wsi);
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2016-01-26 20:56:56 +08:00
|
|
|
SSL_set_fd(wsi->ssl, accept_fd);
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2015-08-08 18:54:49 +02:00
|
|
|
#ifdef USE_WOLFSSL
|
2015-08-09 22:56:32 +02:00
|
|
|
#ifdef USE_OLD_CYASSL
|
2016-01-26 20:56:56 +08:00
|
|
|
CyaSSL_set_using_nonblock(wsi->ssl, 1);
|
2015-08-09 22:56:32 +02:00
|
|
|
#else
|
2016-01-26 20:56:56 +08:00
|
|
|
wolfSSL_set_using_nonblock(wsi->ssl, 1);
|
2015-08-09 22:56:32 +02:00
|
|
|
#endif
|
2017-03-11 11:51:06 +08:00
|
|
|
#else
|
|
|
|
#if defined(LWS_WITH_ESP32)
|
2017-04-03 14:09:37 +08:00
|
|
|
lws_plat_set_socket_options(wsi->vhost, accept_fd);
|
2014-04-12 10:07:02 +08:00
|
|
|
#else
|
2016-01-26 20:56:56 +08:00
|
|
|
SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
|
|
|
bio = SSL_get_rbio(wsi->ssl);
|
2014-04-12 10:07:02 +08:00
|
|
|
if (bio)
|
|
|
|
BIO_set_nbio(bio, 1); /* nonblocking */
|
|
|
|
else
|
|
|
|
lwsl_notice("NULL rbio\n");
|
2016-01-26 20:56:56 +08:00
|
|
|
bio = SSL_get_wbio(wsi->ssl);
|
2014-04-12 10:07:02 +08:00
|
|
|
if (bio)
|
|
|
|
BIO_set_nbio(bio, 1); /* nonblocking */
|
|
|
|
else
|
|
|
|
lwsl_notice("NULL rbio\n");
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2014-04-12 10:07:02 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2017-02-12 20:32:49 +08:00
|
|
|
if (wsi->mode == LWSCM_SSL_INIT)
|
|
|
|
wsi->mode = LWSCM_SSL_ACK_PENDING;
|
|
|
|
else
|
|
|
|
wsi->mode = LWSCM_SSL_ACK_PENDING_RAW;
|
|
|
|
|
2016-04-12 09:02:32 +08:00
|
|
|
if (insert_wsi_socket_into_fds(context, wsi)) {
|
|
|
|
lwsl_err("%s: failed to insert into fds\n", __func__);
|
2015-10-15 07:39:33 +08:00
|
|
|
goto fail;
|
2016-04-12 09:02:32 +08:00
|
|
|
}
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2015-12-04 08:43:54 +08:00
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_SSL_ACCEPT,
|
2016-02-15 20:36:02 +08:00
|
|
|
context->timeout_secs);
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
lwsl_debug("inserted SSL accept into fds, trying SSL_accept\n");
|
2014-04-12 10:07:02 +08:00
|
|
|
|
|
|
|
/* fallthru */
|
|
|
|
|
2015-12-17 17:03:59 +08:00
|
|
|
case LWSCM_SSL_ACK_PENDING:
|
2017-02-12 20:32:49 +08:00
|
|
|
case LWSCM_SSL_ACK_PENDING_RAW:
|
2016-04-12 09:02:32 +08:00
|
|
|
if (lws_change_pollfd(wsi, LWS_POLLOUT, 0)) {
|
|
|
|
lwsl_err("%s: lws_change_pollfd failed\n", __func__);
|
2014-04-12 10:07:02 +08:00
|
|
|
goto fail;
|
2016-04-12 09:02:32 +08:00
|
|
|
}
|
2014-04-12 10:07:02 +08:00
|
|
|
|
|
|
|
lws_latency_pre(context, wsi);
|
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
if (wsi->vhost->allow_non_ssl_on_ssl_port) {
|
|
|
|
|
|
|
|
n = recv(wsi->desc.sockfd, (char *)pt->serv_buf, context->pt_serv_buf_size,
|
|
|
|
MSG_PEEK);
|
2014-04-12 10:07:02 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* optionally allow non-SSL connect on SSL listening socket
|
|
|
|
* This is disabled by default, if enabled it goes around any
|
|
|
|
* SSL-level access control (eg, client-side certs) so leave
|
|
|
|
* it disabled unless you know it's not a problem for you
|
|
|
|
*/
|
|
|
|
|
2016-01-19 03:34:24 +08:00
|
|
|
if (n >= 1 && pt->serv_buf[0] >= ' ') {
|
2015-10-22 20:19:21 +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.
|
|
|
|
*/
|
2015-10-16 11:39:23 +08:00
|
|
|
wsi->use_ssl = 0;
|
2017-02-22 09:54:47 +08:00
|
|
|
|
2015-10-16 11:39:23 +08:00
|
|
|
SSL_shutdown(wsi->ssl);
|
|
|
|
SSL_free(wsi->ssl);
|
|
|
|
wsi->ssl = NULL;
|
2016-03-23 09:22:11 +08:00
|
|
|
if (lws_check_opt(context->options,
|
|
|
|
LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS))
|
2016-03-17 15:26:49 +08:00
|
|
|
wsi->redirect_to_https = 1;
|
2015-10-16 11:39:23 +08:00
|
|
|
goto accepted;
|
|
|
|
}
|
2015-12-14 08:52:03 +08:00
|
|
|
if (!n) /*
|
2015-11-06 08:23:05 +08:00
|
|
|
* connection is gone, or nothing to read
|
|
|
|
* if it's gone, we will timeout on
|
|
|
|
* PENDING_TIMEOUT_SSL_ACCEPT
|
|
|
|
*/
|
|
|
|
break;
|
2015-10-31 06:49:05 +08:00
|
|
|
if (n < 0 && (LWS_ERRNO == LWS_EAGAIN ||
|
|
|
|
LWS_ERRNO == LWS_EWOULDBLOCK)) {
|
2015-10-16 11:39:23 +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.
|
|
|
|
*/
|
|
|
|
m = SSL_ERROR_WANT_READ;
|
|
|
|
goto go_again;
|
|
|
|
}
|
2014-04-12 10:07:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* normal SSL connection processing path */
|
2017-02-22 09:54:47 +08:00
|
|
|
|
2017-05-07 10:02:03 +08:00
|
|
|
#if defined(LWS_WITH_STATS)
|
|
|
|
if (!wsi->accept_start_us)
|
|
|
|
wsi->accept_start_us = time_in_microseconds();
|
|
|
|
#endif
|
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
n = SSL_accept(wsi->ssl);
|
|
|
|
lws_latency(context, wsi,
|
2015-12-17 17:03:59 +08:00
|
|
|
"SSL_accept LWSCM_SSL_ACK_PENDING\n", n, n == 1);
|
2017-03-11 11:51:06 +08:00
|
|
|
lwsl_info("SSL_accept says %d\n", n);
|
2014-04-12 10:07:02 +08:00
|
|
|
if (n == 1)
|
|
|
|
goto accepted;
|
|
|
|
|
2016-04-17 11:28:43 +08:00
|
|
|
m = lws_ssl_get_error(wsi, n);
|
2017-03-11 11:51:06 +08:00
|
|
|
|
|
|
|
#if defined(LWS_WITH_ESP32)
|
|
|
|
if (m == 5 && errno == 11)
|
|
|
|
m = SSL_ERROR_WANT_READ;
|
|
|
|
#endif
|
|
|
|
|
2015-10-16 11:39:23 +08:00
|
|
|
go_again:
|
2017-04-03 14:09:37 +08:00
|
|
|
if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) {
|
2016-04-12 09:02:32 +08:00
|
|
|
if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) {
|
|
|
|
lwsl_err("%s: WANT_READ change_pollfd failed\n", __func__);
|
2014-04-12 10:07:02 +08:00
|
|
|
goto fail;
|
2016-04-12 09:02:32 +08:00
|
|
|
}
|
2014-04-12 10:07:02 +08:00
|
|
|
|
|
|
|
lwsl_info("SSL_ERROR_WANT_READ\n");
|
|
|
|
break;
|
|
|
|
}
|
2017-04-03 14:09:37 +08:00
|
|
|
if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) {
|
|
|
|
lwsl_debug("%s: WANT_WRITE\n", __func__);
|
|
|
|
|
2016-04-12 09:02:32 +08:00
|
|
|
if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) {
|
|
|
|
lwsl_err("%s: WANT_WRITE change_pollfd failed\n", __func__);
|
2014-04-12 10:07:02 +08:00
|
|
|
goto fail;
|
2016-04-12 09:02:32 +08:00
|
|
|
}
|
2014-04-12 10:07:02 +08:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2017-05-07 10:02:03 +08:00
|
|
|
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_FAILED, 1);
|
2017-02-27 12:55:56 +08:00
|
|
|
lwsl_err("SSL_accept failed socket %u: %s\n", wsi->desc.sockfd,
|
2016-12-21 09:32:25 +08:00
|
|
|
lws_ssl_get_error_string(m, n, buf, sizeof(buf)));
|
2016-05-03 07:26:10 +08:00
|
|
|
lws_ssl_elaborate_error();
|
2014-11-30 12:14:23 +08:00
|
|
|
goto fail;
|
2014-04-12 10:07:02 +08:00
|
|
|
|
|
|
|
accepted:
|
2017-05-07 10:02:03 +08:00
|
|
|
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_C_SSL_CONNECTIONS_ACCEPTED, 1);
|
|
|
|
#if defined(LWS_WITH_STATS)
|
|
|
|
lws_stats_atomic_bump(wsi->context, pt, LWSSTATS_MS_SSL_CONNECTIONS_ACCEPTED_DELAY, time_in_microseconds() - wsi->accept_start_us);
|
2017-05-13 10:26:59 +08:00
|
|
|
wsi->accept_start_us = time_in_microseconds();
|
2017-05-07 10:02:03 +08:00
|
|
|
#endif
|
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
/* OK, we are accepted... give him some time to negotiate */
|
2015-12-06 06:39:51 +08:00
|
|
|
lws_set_timeout(wsi, PENDING_TIMEOUT_ESTABLISH_WITH_SERVER,
|
2016-02-15 20:36:02 +08:00
|
|
|
context->timeout_secs);
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2017-02-12 20:32:49 +08:00
|
|
|
if (wsi->mode == LWSCM_SSL_ACK_PENDING_RAW)
|
|
|
|
wsi->mode = LWSCM_RAW;
|
|
|
|
else
|
|
|
|
wsi->mode = LWSCM_HTTP_SERVING;
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2014-10-22 15:37:28 +08:00
|
|
|
lws_http2_configure_if_upgraded(wsi);
|
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
lwsl_debug("accepted new SSL conn\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2015-12-14 08:52:03 +08:00
|
|
|
|
2014-04-12 10:07:02 +08:00
|
|
|
fail:
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-03-28 10:10:43 +08:00
|
|
|
void
|
|
|
|
lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost)
|
2014-04-12 10:07:02 +08:00
|
|
|
{
|
2017-02-22 09:54:47 +08:00
|
|
|
if (vhost->ssl_ctx)
|
2016-03-28 10:10:43 +08:00
|
|
|
SSL_CTX_free(vhost->ssl_ctx);
|
2017-02-22 09:54:47 +08:00
|
|
|
|
|
|
|
if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx)
|
2016-03-28 10:10:43 +08:00
|
|
|
SSL_CTX_free(vhost->ssl_client_ctx);
|
|
|
|
}
|
2014-04-12 10:07:02 +08:00
|
|
|
|
2016-03-28 10:10:43 +08:00
|
|
|
void
|
|
|
|
lws_ssl_context_destroy(struct lws_context *context)
|
|
|
|
{
|
2017-01-07 11:29:32 +08:00
|
|
|
|
2017-03-11 11:51:06 +08:00
|
|
|
#if !defined(LWS_WITH_ESP32)
|
|
|
|
|
2017-01-07 11:29:32 +08:00
|
|
|
// after 1.1.0 no need
|
|
|
|
#if (OPENSSL_VERSION_NUMBER < 0x10100000)
|
|
|
|
// <= 1.0.1f = old api, 1.0.1g+ = new api
|
|
|
|
#if (OPENSSL_VERSION_NUMBER <= 0x1000106f) || defined(USE_WOLFSSL)
|
2014-11-05 15:35:05 +08:00
|
|
|
ERR_remove_state(0);
|
2016-04-10 09:33:54 +08:00
|
|
|
#else
|
2017-01-07 11:29:32 +08:00
|
|
|
#if OPENSSL_VERSION_NUMBER >= 0x1010005f && \
|
|
|
|
!defined(LIBRESSL_VERSION_NUMBER) && \
|
|
|
|
!defined(OPENSSL_IS_BORINGSSL)
|
2016-04-10 09:33:54 +08:00
|
|
|
ERR_remove_thread_state();
|
2014-11-05 15:35:05 +08:00
|
|
|
#else
|
2014-10-27 11:38:03 +08:00
|
|
|
ERR_remove_thread_state(NULL);
|
2016-04-10 09:33:54 +08:00
|
|
|
#endif
|
2017-07-15 17:51:32 +08:00
|
|
|
#endif
|
|
|
|
// after 1.1.0 no need
|
|
|
|
#if (OPENSSL_VERSION_NUMBER >= 0x10002000) && (OPENSSL_VERSION_NUMBER <= 0x10100000)
|
|
|
|
SSL_COMP_free_compression_methods();
|
2014-11-05 15:35:05 +08:00
|
|
|
#endif
|
2014-04-12 10:07:02 +08:00
|
|
|
ERR_free_strings();
|
|
|
|
EVP_cleanup();
|
|
|
|
CRYPTO_cleanup_all_ex_data();
|
2016-04-17 11:28:43 +08:00
|
|
|
#endif
|
2017-03-11 11:51:06 +08:00
|
|
|
#endif
|
2014-04-27 13:28:22 +02:00
|
|
|
}
|