diff --git a/.travis.yml b/.travis.yml index 244c507d..6181435a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ env: matrix: - LWS_METHOD=lwsws CMAKE_ARGS="-DLWS_WITH_LWSWS=ON -DLWS_WITHOUT_EXTENSIONS=0 -DLWS_WITH_HTTP2=1 -DLWS_WITH_ACME=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG" - LWS_METHOD=default CMAKE_ARGS="-DLWS_WITH_MINIMAL_EXAMPLES=1" + - LWS_METHOD=mbedtls CMAKE_ARGS="-DLWS_WITH_MBEDTLS=1 -DLWS_WITH_HTTP2=1 -DLWS_WITH_LWSWS=1 -DLWS_WITH_MINIMAL_EXAMPLES=1 -DCMAKE_BUILD_TYPE=DEBUG" - LWS_METHOD=noserver CMAKE_ARGS="-DLWS_WITHOUT_SERVER=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - LWS_METHOD=noclient CMAKE_ARGS="-DLWS_WITHOUT_CLIENT=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" - LWS_METHOD=noext CMAKE_ARGS="-DLWS_WITHOUT_EXTENSIONS=ON -DLWS_WITH_MINIMAL_EXAMPLES=1" diff --git a/README.md b/README.md index 081d1729..6d604359 100644 --- a/README.md +++ b/README.md @@ -13,18 +13,18 @@ The Travis build of lws done on every commit now runs Tests|Count|Explanation ---|---|--- -Build / Linux / gcc|13|-Wall -Werror cmake config variants -Build / Mac / Clang|13|-Wall -Werror cmake config variants +Build / Linux / gcc|14|-Wall -Werror cmake config variants +Build / Mac / Clang|14|-Wall -Werror cmake config variants Build / Windows / MSVC|7|default -Selftests|33|minimal examples built and run against each other and remote server +Selftests|openssl:33, mbedtls:33|minimal examples built and run against each other and remote server attack.sh|225|Correctness, robustness and security tests for http parser Autobahn Server|480|Testing lws ws client, including permessage-deflate Autobahn Client|480|Testing lws ws server, including permaessage-deflate -h2spec|146|Http/2 server compliance suite (in strict mode) -h2load|6|Http/2 server load tool (checks 10K / 100K in h1 and h2, at 1, 10, 100 concurrency) +h2spec|openssl:146, mbedtls:146|Http/2 server compliance suite (in strict mode) +h2load|openssl:6, mbedtls:6|Http/2 server load tool (checks 10K / 100K in h1 and h2, at 1, 10, 100 concurrency) h2load SMP|6|Http/2 and http/1.1 server load checks on SMP server build -The over 1,400 tests run on every commit take most of an hour to complete. +The over 1,500 tests run on every commit take most of an hour to complete. If any problems are found, it breaks the travis build, generating an email. Current master passes all the tests and these new CI arrangements will help diff --git a/lib/context.c b/lib/context.c index ccc13c00..d638ff52 100644 --- a/lib/context.c +++ b/lib/context.c @@ -54,10 +54,6 @@ const struct lws_event_loop_ops *available_event_libs[] = { NULL }; -#if defined(LWS_WITH_TLS) -static char alpn_discovered[32]; -#endif - static const char *library_version = LWS_LIBRARY_VERSION " " LWS_BUILD_HASH; /** @@ -252,7 +248,7 @@ lws_protocol_init(struct lws_context *context) } #if defined(LWS_WITH_TLS) - any |= !!vh->ssl_ctx; + any |= !!vh->tls.ssl_ctx; #endif /* @@ -556,7 +552,7 @@ lws_create_vhost(struct lws_context *context, struct lws_protocols *lwsp; int m, f = !info->pvo; char buf[20]; -#ifdef LWS_HAVE_GETENV +#if !defined(LWS_WITHOUT_CLIENT) && defined(LWS_HAVE_GETENV) char *p; #endif int n; @@ -599,7 +595,6 @@ lws_create_vhost(struct lws_context *context, vh->pvo = info->pvo; vh->headers = info->headers; vh->user = info->user; - vh->alpn = info->alpn; LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) if (ar->init_vhost) @@ -607,7 +602,7 @@ lws_create_vhost(struct lws_context *context, return NULL; LWS_FOR_EVERY_AVAILABLE_ROLE_END; - vh->ssl_info_event_mask = info->ssl_info_event_mask; + if (info->keepalive_timeout) vh->keepalive_timeout = info->keepalive_timeout; else @@ -619,10 +614,13 @@ lws_create_vhost(struct lws_context *context, vh->timeout_secs_ah_idle = 10; #if defined(LWS_WITH_TLS) + + vh->tls.alpn = info->alpn; + vh->tls.ssl_info_event_mask = info->ssl_info_event_mask; + if (info->ecdh_curve) - lws_strncpy(vh->ecdh_curve, info->ecdh_curve, - sizeof(vh->ecdh_curve)); -#endif + lws_strncpy(vh->tls.ecdh_curve, info->ecdh_curve, + sizeof(vh->tls.ecdh_curve)); /* carefully allocate and take a copy of cert + key paths if present */ n = 0; @@ -632,16 +630,17 @@ lws_create_vhost(struct lws_context *context, n += (int)strlen(info->ssl_private_key_filepath) + 1; if (n) { - vh->key_path = vh->alloc_cert_path = lws_malloc(n, "vh paths"); + vh->tls.key_path = vh->tls.alloc_cert_path = lws_malloc(n, "vh paths"); if (info->ssl_cert_filepath) { n = (int)strlen(info->ssl_cert_filepath) + 1; - memcpy(vh->alloc_cert_path, info->ssl_cert_filepath, n); - vh->key_path += n; + memcpy(vh->tls.alloc_cert_path, info->ssl_cert_filepath, n); + vh->tls.key_path += n; } if (info->ssl_private_key_filepath) - memcpy(vh->key_path, info->ssl_private_key_filepath, + memcpy(vh->tls.key_path, info->ssl_private_key_filepath, strlen(info->ssl_private_key_filepath) + 1); } +#endif /* * give the vhost a unified list of protocols including the @@ -765,6 +764,7 @@ lws_create_vhost(struct lws_context *context, vh->socks_proxy_address[0] = '\0'; #endif +#if !defined(LWS_WITHOUT_CLIENT) /* either use proxy from info, or try get it from env var */ #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) /* http proxy */ @@ -782,6 +782,7 @@ lws_create_vhost(struct lws_context *context, lws_set_proxy(vh, p); #endif } +#endif #if defined(LWS_WITH_SOCKS5) /* socks proxy */ if (info->socks_proxy_address) { @@ -990,6 +991,8 @@ lws_create_context(const struct lws_context_creation_info *info) struct rlimit rt; #endif + + lwsl_info("Initial logging level %d\n", log_level); lwsl_info("Libwebsockets version: %s\n", library_version); #if defined(GCC_VER) @@ -1026,6 +1029,15 @@ lws_create_context(const struct lws_context_creation_info *info) lwsl_err("No memory for websocket context\n"); return NULL; } + +#if defined(LWS_WITH_TLS) +#if defined(LWS_WITH_MBEDTLS) + context->tls_ops = &tls_ops_mbedtls; +#else + context->tls_ops = &tls_ops_openssl; +#endif +#endif + if (info->pt_serv_buf_size) context->pt_serv_buf_size = info->pt_serv_buf_size; else @@ -1152,25 +1164,26 @@ lws_create_context(const struct lws_context_creation_info *info) #if defined(LWS_WITH_TLS) if (info->alpn) - context->alpn_default = info->alpn; + context->tls.alpn_default = info->alpn; else { - char *p = alpn_discovered, first = 1; + char *p = context->tls.alpn_discovered, first = 1; LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) { if (ar->alpn) { if (!first) *p++ = ','; - p += lws_snprintf(p, alpn_discovered + - sizeof(alpn_discovered) - 2 - p, - "%s", ar->alpn); + p += lws_snprintf(p, + context->tls.alpn_discovered + + sizeof(context->tls.alpn_discovered) - + 2 - p, "%s", ar->alpn); first = 0; } } LWS_FOR_EVERY_AVAILABLE_ROLE_END; - context->alpn_default = alpn_discovered; + context->tls.alpn_default = context->tls.alpn_discovered; } - lwsl_info("Default ALPN advertisment: %s\n", context->alpn_default); + lwsl_info("Default ALPN advertisment: %s\n", context->tls.alpn_default); #endif if (info->timeout_secs) @@ -1616,7 +1629,9 @@ lws_vhost_destroy2(struct lws_vhost *vh) close(vh->log_fd); #endif - lws_free_set_NULL(vh->alloc_cert_path); +#if defined (LWS_WITH_TLS) + lws_free_set_NULL(vh->tls.alloc_cert_path); +#endif #if LWS_MAX_SMP > 1 pthread_mutex_destroy(&vh->lock); diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index 81787db1..28bb2fe0 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -733,7 +733,7 @@ just_kill_connection: !wsi->socket_is_permanently_unusable) { #if defined(LWS_WITH_TLS) - if (lws_is_ssl(wsi) && wsi->ssl) { + if (lws_is_ssl(wsi) && wsi->tls.ssl) { n = 0; switch (__lws_tls_shutdown(wsi)) { case LWS_SSL_CAPABLE_DONE: @@ -1703,6 +1703,7 @@ int user_callback_handle_rxflow(lws_callback_function callback_function, return n; } +#if !defined(LWS_WITHOUT_CLIENT) LWS_VISIBLE int lws_set_proxy(struct lws_vhost *vhost, const char *proxy) { @@ -1761,6 +1762,7 @@ auth_too_long: return -1; } +#endif #if defined(LWS_WITH_SOCKS5) LWS_VISIBLE int @@ -2061,7 +2063,7 @@ LWS_VISIBLE int lws_is_ssl(struct lws *wsi) { #if defined(LWS_WITH_TLS) - return wsi->use_ssl & LCCSCF_USE_SSL; + return wsi->tls.use_ssl & LCCSCF_USE_SSL; #else (void)wsi; return 0; @@ -2072,7 +2074,7 @@ lws_is_ssl(struct lws *wsi) LWS_VISIBLE lws_tls_conn* lws_get_ssl(struct lws *wsi) { - return wsi->ssl; + return wsi->tls.ssl; } #endif @@ -2974,7 +2976,7 @@ lws_json_dump_vhost(const struct lws_vhost *vh, char *buf, int len) , vh->name, vh->listen_port, #if defined(LWS_WITH_TLS) - vh->use_ssl & LCCSCF_USE_SSL, + vh->tls.use_ssl & LCCSCF_USE_SSL, #else 0, #endif @@ -3304,10 +3306,9 @@ lws_stats_log_dump(struct lws_context *context) (unsigned long long)(lws_stats_get(context, LWSSTATS_MS_WRITABLE_DELAY) / lws_stats_get(context, LWSSTATS_C_WRITEABLE_CB))); - lwsl_notice("Simultaneous SSL restriction: %8d/%d/%d\n", + lwsl_notice("Simultaneous SSL restriction: %8d/%d\n", context->simultaneous_ssl, - context->simultaneous_ssl_restriction, - context->ssl_gate_accepts); + context->simultaneous_ssl_restriction); lwsl_notice("Live wsi: %8d\n", context->count_wsi_allocated); diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 1fb04d4e..14c65ac0 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -33,6 +33,9 @@ extern "C" { #include #endif +#include +#include + #include "lws_config.h" /* diff --git a/lib/plat/lws-plat-esp32.c b/lib/plat/lws-plat-esp32.c index a46110ce..89f1fb6b 100644 --- a/lib/plat/lws-plat-esp32.c +++ b/lib/plat/lws-plat-esp32.c @@ -217,16 +217,22 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) } } -#if defined(LWS_WITH_TLS) - if (!pt->ws.rx_draining_ext_list && - !lws_ssl_anybody_has_buffered_read_tsi(context, tsi) && !n) { -#else - if (!pt->ws.rx_draining_ext_list && !n) /* poll timeout */ { + m = 0; + +#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) + m |= !!pt->ws.rx_draining_ext_list; #endif + + if (pt->context->tls_ops && + pt->context->tls_ops->fake_POLLIN_for_buffered) + m |= pt->context->tls_ops->fake_POLLIN_for_buffered(pt); + + if (!m && !n) { lws_service_fd_tsi(context, NULL, tsi); return 0; } + faked_service: m = lws_service_flag_pending(context, tsi); if (m) @@ -1792,9 +1798,9 @@ lws_esp32_selfsigned(struct lws_vhost *vhost) } n = 0; - if (!nvs_get_blob(nvh, vhost->alloc_cert_path, NULL, &s)) + if (!nvs_get_blob(nvh, vhost->tls.alloc_cert_path, NULL, &s)) n |= 1; - if (!nvs_get_blob(nvh, vhost->key_path, NULL, &s)) + if (!nvs_get_blob(nvh, vhost->tls.key_path, NULL, &s)) n |= 2; nvs_close(nvh); @@ -2041,7 +2047,7 @@ lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf, const char *name = vhost->alloc_cert_path; if (is_key) - name = vhost->key_path; + name = vhost->tls.key_path; return lws_plat_write_file(name, buf, len) < 0; } diff --git a/lib/plat/lws-plat-optee.c b/lib/plat/lws-plat-optee.c index 5ccbedd6..ab04f842 100644 --- a/lib/plat/lws-plat-optee.c +++ b/lib/plat/lws-plat-optee.c @@ -137,19 +137,20 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) /* yes... come back again quickly */ timeout_ms = 0; } -#if 1 + n = poll(pt->fds, pt->fds_count, timeout_ms); -#if defined(LWS_WITH_TLS) - if (!pt->ws.rx_draining_ext_list && - !lws_ssl_anybody_has_buffered_read_tsi(context, tsi) && !n) { -#else - if (!pt->ws.rx_draining_ext_list && !n) /* poll timeout */ { -#endif + m = 0; + + if (pt->context->tls_ops && + pt->context->tls_ops->fake_POLLIN_for_buffered) + m = pt->context->tls_ops->fake_POLLIN_for_buffered(pt); + + if (/*!pt->ws.rx_draining_ext_list && */!m && !n) { /* nothing to do */ lws_service_fd_tsi(context, NULL, tsi); return 0; } -#endif + faked_service: m = lws_service_flag_pending(context, tsi); if (m) diff --git a/lib/plat/lws-plat-unix.c b/lib/plat/lws-plat-unix.c index 8ace4758..2c103bb1 100644 --- a/lib/plat/lws-plat-unix.c +++ b/lib/plat/lws-plat-unix.c @@ -257,15 +257,15 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) lws_pt_unlock(pt); m = 0; - -#if defined(LWS_WITH_TLS) - m |= !n && !lws_ssl_anybody_has_buffered_read_tsi(context, tsi); -#endif #if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS) - m |= !n && !pt->ws.rx_draining_ext_list; + m |= !!pt->ws.rx_draining_ext_list; #endif - if (m) { + if (pt->context->tls_ops && + pt->context->tls_ops->fake_POLLIN_for_buffered) + m |= pt->context->tls_ops->fake_POLLIN_for_buffered(pt); + + if (!m && !n) { /* nothing to do */ lws_service_fd_tsi(context, NULL, tsi); lws_service_do_ripe_rxflow(pt); diff --git a/lib/plat/lws-plat-win.c b/lib/plat/lws-plat-win.c index 13353053..287e144c 100644 --- a/lib/plat/lws-plat-win.c +++ b/lib/plat/lws-plat-win.c @@ -262,6 +262,10 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) WSAResetEvent(pt->events[0]); + if (pt->context->tls_ops && + pt->context->tls_ops->fake_POLLIN_for_buffered) + pt->context->tls_ops->fake_POLLIN_for_buffered(pt); + for (eIdx = 0; eIdx < pt->fds_count; ++eIdx) { if (WSAEnumNetworkEvents(pt->fds[eIdx].fd, 0, &networkevents) == SOCKET_ERROR) { @@ -302,7 +306,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) if (ev == WSA_WAIT_TIMEOUT) lws_service_fd(context, NULL); - return 0;; + return 0; } LWS_VISIBLE int diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 9f2859d0..a221201d 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -199,9 +199,7 @@ #include "libwebsockets.h" -#if defined(LWS_WITH_TLS) - #include "tls/private.h" -#endif +#include "tls/private.h" #if defined(WIN32) || defined(_WIN32) #include @@ -548,7 +546,7 @@ struct lws_context_per_thread { struct lws_dll_lws dll_head_buflist; /* guys with pending rxflow */ #if defined(LWS_WITH_TLS) - struct lws *pending_read_list; /* linked list */ + struct lws_pt_tls tls; #endif struct lws_pollfd *fds; @@ -633,15 +631,11 @@ struct lws_timed_vh_protocol { * SSL SNI -> wsi -> bind after SSL negotiation */ -struct lws_tls_ss_pieces; - -struct alpn_ctx { - uint8_t data[23]; - uint8_t len; -}; struct lws_vhost { +#if !defined(LWS_WITHOUT_CLIENT) char proxy_basic_auth_token[128]; +#endif #if LWS_MAX_SMP > 1 pthread_mutex_t lock; #endif @@ -671,8 +665,7 @@ struct lws_vhost { struct lws *lserv_wsi; const char *name; const char *iface; - char *alloc_cert_path; - char *key_path; + #if !defined(LWS_WITH_ESP32) && !defined(OPTEE_TA) && !defined(WIN32) int bind_iface; #endif @@ -686,16 +679,8 @@ struct lws_vhost { struct lws_dll_lws dll_active_client_conns; #endif - const char *alpn; #if defined(LWS_WITH_TLS) - lws_tls_ctx *ssl_ctx; - lws_tls_ctx *ssl_client_ctx; - struct lws_tls_ss_pieces *ss; /* for acme tls certs */ - char ecdh_curve[16]; - struct alpn_ctx alpn_ctx; -#endif -#if defined(LWS_WITH_MBEDTLS) - lws_tls_x509 *x509_client_CA; + struct lws_vhost_tls tls; #endif struct lws_timed_vh_protocol *timed_vh_protocol_list; @@ -713,21 +698,13 @@ struct lws_vhost { int ka_interval; int keepalive_timeout; int timeout_secs_ah_idle; - int ssl_info_event_mask; + #ifdef LWS_WITH_ACCESS_LOG int log_fd; #endif -#if defined(LWS_WITH_TLS) - int use_ssl; - int allow_non_ssl_on_ssl_port; - unsigned int user_supplied_ssl_ctx:1; -#endif - unsigned int created_vhost_protocols:1; unsigned int being_destroyed:1; - unsigned int skipped_certs:1; - unsigned int acme_challenge:1; unsigned char default_protocol_index; unsigned char raw_protocol_index; @@ -786,6 +763,9 @@ struct lws_context { const struct lws_plat_file_ops *fops; struct lws_plat_file_ops fops_platform; struct lws_context **pcontext_finalize; + + const struct lws_tls_ops *tls_ops; + #if defined(LWS_WITH_HTTP2) struct http2_settings set; #endif @@ -818,9 +798,7 @@ struct lws_context { void *external_baggage_free_on_destroy; const struct lws_token_limits *token_limits; void *user_space; - const char *server_string; const struct lws_protocol_vhost_options *reject_service_keywords; - const char *alpn_default; lws_reload_func deprecation_cb; void (*eventlib_signal_cb)(void *event_lib_handle, int signum); @@ -841,7 +819,13 @@ struct lws_context { struct lws_event_loop_ops *event_loop_ops; +#if defined(LWS_WITH_TLS) + struct lws_context_tls tls; +#endif + char canonical_hostname[128]; + const char *server_string; + #ifdef LWS_LATENCY unsigned long worst_latency; char worst_latency_info[256]; @@ -885,7 +869,6 @@ struct lws_context { unsigned int being_destroyed2:1; unsigned int requested_kill:1; unsigned int protocol_init_done:1; - unsigned int ssl_gate_accepts:1; unsigned int doing_protocol_init:1; unsigned int done_protocol_destroy_cb:1; unsigned int finalize_destroy_after_internal_loops_stopped:1; @@ -1014,6 +997,7 @@ struct lws_buflist { #define LWS_H2_FRAME_HEADER_LENGTH 9 + struct lws { /* structs */ @@ -1027,7 +1011,7 @@ struct lws { struct _lws_websocket_related *ws; /* allocated if we upgrade to ws */ #endif - struct lws_role_ops *role_ops; + const struct lws_role_ops *role_ops; lws_wsi_state_t wsistate; lws_wsi_state_t wsistate_pre_close; @@ -1076,9 +1060,7 @@ struct lws { unsigned char *trunc_alloc; /* non-NULL means buffering in progress */ #if defined(LWS_WITH_TLS) - lws_tls_conn *ssl; - lws_tls_bio *client_bio; - struct lws *pending_read_list_prev, *pending_read_list_next; + struct lws_lws_tls tls; #endif #ifdef LWS_LATENCY @@ -1097,8 +1079,6 @@ struct lws { lws_usec_t pending_timer; time_t pending_timeout_set; - - /* ints */ int position_in_fds_table; unsigned int trunc_alloc_len; /* size of malloc */ @@ -1160,10 +1140,6 @@ struct lws { unsigned int client_h2_substream:1; #endif -#if defined(LWS_WITH_TLS) - unsigned int use_ssl; - unsigned int redirect_to_https:1; -#endif #ifdef _WIN32 unsigned int sock_send_blocking:1; #endif @@ -1426,7 +1402,6 @@ LWS_EXTERN void lwsl_emit_stderr(int level, const char *line); #define lws_ssl_remove_wsi_from_buffered_list(_a) #define __lws_ssl_remove_wsi_from_buffered_list(_a) #define lws_context_init_ssl_library(_a) - #define lws_ssl_anybody_has_buffered_read_tsi(_a, _b) (0) #define lws_tls_check_all_cert_lifetimes(_a) #define lws_tls_acme_sni_cert_destroy(_a) #endif diff --git a/lib/roles/h1/ops-h1.c b/lib/roles/h1/ops-h1.c index d4aad661..172b8d82 100644 --- a/lib/roles/h1/ops-h1.c +++ b/lib/roles/h1/ops-h1.c @@ -469,7 +469,6 @@ try_pollout: fail: -lwsl_notice("%s: fail: closing\n", __func__); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "server socket svc fail"); return LWS_HPI_RET_WSI_ALREADY_DIED; diff --git a/lib/roles/http/client/client-handshake.c b/lib/roles/http/client/client-handshake.c index c4b61bcb..a28d7fe1 100644 --- a/lib/roles/http/client/client-handshake.c +++ b/lib/roles/http/client/client-handshake.c @@ -90,8 +90,8 @@ lws_client_connect_2(struct lws *wsi) if (w != wsi && w->client_hostname_copy && !strcmp(adsin, w->client_hostname_copy) && #if defined(LWS_WITH_TLS) - (wsi->use_ssl & LCCSCF_USE_SSL) == - (w->use_ssl & LCCSCF_USE_SSL) && + (wsi->tls.use_ssl & LCCSCF_USE_SSL) == + (w->tls.use_ssl & LCCSCF_USE_SSL) && #endif wsi->c_port == w->c_port) { @@ -658,7 +658,7 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port, __remove_wsi_socket_from_fds(wsi); #if defined(LWS_WITH_TLS) - wsi->use_ssl = ssl; + wsi->tls.use_ssl = ssl; #else if (ssl) { lwsl_err("%s: not configured for ssl\n", __func__); @@ -971,7 +971,7 @@ lws_client_connect_via_info(struct lws_client_connect_info *i) goto bail; #if defined(LWS_WITH_TLS) - wsi->use_ssl = i->ssl_connection; + wsi->tls.use_ssl = i->ssl_connection; #else if (i->ssl_connection & LCCSCF_USE_SSL) { lwsl_err("libwebsockets not configured for ssl\n"); diff --git a/lib/roles/http/client/client.c b/lib/roles/http/client/client.c index 1a61e62c..e035dbac 100644 --- a/lib/roles/http/client/client.c +++ b/lib/roles/http/client/client.c @@ -309,13 +309,13 @@ start_ws_handshake: #if defined(LWS_WITH_TLS) /* we can retry this... just cook the SSL BIO the first time */ - if ((wsi->use_ssl & LCCSCF_USE_SSL) && !wsi->ssl && + if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !wsi->tls.ssl && lws_ssl_client_bio_create(wsi) < 0) { cce = "bio_create failed"; goto bail3; } - if (wsi->use_ssl & LCCSCF_USE_SSL) { + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { n = lws_ssl_client_connect1(wsi); if (!n) return 0; @@ -324,13 +324,13 @@ start_ws_handshake: goto bail3; } } else - wsi->ssl = NULL; + wsi->tls.ssl = NULL; /* fallthru */ case LRS_WAITING_SSL: - if (wsi->use_ssl & LCCSCF_USE_SSL) { + if (wsi->tls.use_ssl & LCCSCF_USE_SSL) { n = lws_ssl_client_connect2(wsi, ebuf, sizeof(ebuf)); if (!n) return 0; @@ -339,7 +339,7 @@ start_ws_handshake: goto bail3; } } else - wsi->ssl = NULL; + wsi->tls.ssl = NULL; #endif #if defined (LWS_WITH_HTTP2) if (wsi->client_h2_alpn) { @@ -746,7 +746,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) /* Relative reference absolute path */ if (p[0] == '/') { #if defined(LWS_WITH_TLS) - ssl = wsi->use_ssl & LCCSCF_USE_SSL; + ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL; #endif ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS); @@ -769,7 +769,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) /* This doesn't try to calculate an absolute path, * that will be left to the server */ #if defined(LWS_WITH_TLS) - ssl = wsi->use_ssl & LCCSCF_USE_SSL; + ssl = wsi->tls.use_ssl & LCCSCF_USE_SSL; #endif ads = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_PEER_ADDRESS); @@ -787,7 +787,7 @@ lws_client_interpret_server_handshake(struct lws *wsi) } #if defined(LWS_WITH_TLS) - if ((wsi->use_ssl & LCCSCF_USE_SSL) && !ssl) { + if ((wsi->tls.use_ssl & LCCSCF_USE_SSL) && !ssl) { cce = "HS: Redirect attempted SSL downgrade"; goto bail3; } diff --git a/lib/roles/http/server/server.c b/lib/roles/http/server/server.c index 001c6c09..83f5de8a 100644 --- a/lib/roles/http/server/server.c +++ b/lib/roles/http/server/server.c @@ -952,7 +952,7 @@ lws_http_action(struct lws *wsi) lws_set_timeout(wsi, PENDING_TIMEOUT_HTTP_CONTENT, wsi->context->timeout_secs); #ifdef LWS_WITH_TLS - if (wsi->redirect_to_https) { + if (wsi->tls.redirect_to_https) { /* * we accepted http:// only so we could redirect to * https://, so issue the redirect. Create the redirection @@ -1681,7 +1681,7 @@ lws_create_new_server_wsi(struct lws_vhost *vhost, int fixed_tsi) new_wsi->hdr_parsing_completed = 0; #ifdef LWS_WITH_TLS - new_wsi->use_ssl = LWS_SSL_ENABLED(vhost); + new_wsi->tls.use_ssl = LWS_SSL_ENABLED(vhost); #endif /* @@ -1779,7 +1779,7 @@ lws_http_transaction_completed(struct lws *wsi) * SSL is scarce, drop this connection without waiting */ - if (wsi->vhost->use_ssl && + if (wsi->vhost->tls.use_ssl && wsi->context->simultaneous_ssl_restriction && wsi->context->simultaneous_ssl == wsi->context->simultaneous_ssl_restriction) { diff --git a/lib/roles/listen/ops-listen.c b/lib/roles/listen/ops-listen.c index 690476de..02f028a8 100644 --- a/lib/roles/listen/ops-listen.c +++ b/lib/roles/listen/ops-listen.c @@ -51,7 +51,7 @@ rops_handle_POLLIN_listen(struct lws_context_per_thread *pt, struct lws *wsi, * another vhost may also have had POLLIN on his * listener this round and used it up already */ - if (wsi->vhost->use_ssl && + if (wsi->vhost->tls.use_ssl && context->simultaneous_ssl_restriction && context->simultaneous_ssl == context->simultaneous_ssl_restriction) diff --git a/lib/roles/ws/ops-ws.c b/lib/roles/ws/ops-ws.c index 13402b46..9e2a52f0 100644 --- a/lib/roles/ws/ops-ws.c +++ b/lib/roles/ws/ops-ws.c @@ -791,7 +791,7 @@ lws_server_init_wsi_for_ws(struct lws *wsi) if (wsi->protocol->callback(wsi, LWS_CALLBACK_ESTABLISHED, wsi->user_space, #ifdef LWS_WITH_TLS - wsi->ssl, + wsi->tls.ssl, #else NULL, #endif diff --git a/lib/service.c b/lib/service.c index 0dd4b358..39dba41c 100644 --- a/lib/service.c +++ b/lib/service.c @@ -328,13 +328,12 @@ lws_service_adjust_timeout(struct lws_context *context, int timeout_ms, int tsi) return 0; #endif -#if defined(LWS_WITH_TLS) /* 2) if we know we have non-network pending data, do not wait in poll */ - if (lws_ssl_anybody_has_buffered_read_tsi(context, tsi)) { - lwsl_info("ssl buffered read\n"); - return 0; - } -#endif + + if (pt->context->tls_ops && + pt->context->tls_ops->fake_POLLIN_for_buffered) + if (pt->context->tls_ops->fake_POLLIN_for_buffered(pt)) + return 0; /* 3) If there is any wsi with rxflow buffered and in a state to process * it, we should not wait in poll @@ -521,9 +520,9 @@ lws_service_flag_pending(struct lws_context *context, int tsi) * service to use up the buffered incoming data, even though their * network socket may have nothing */ - wsi = pt->pending_read_list; + wsi = pt->tls.pending_read_list; while (wsi) { - wsi_next = wsi->pending_read_list_next; + wsi_next = wsi->tls.pending_read_list_next; pt->fds[wsi->position_in_fds_table].revents |= pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN; if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) { @@ -870,7 +869,7 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, } #if defined(LWS_WITH_TLS) - if (lwsi_state(wsi) == LRS_SHUTDOWN && lws_is_ssl(wsi) && wsi->ssl) { + if (lwsi_state(wsi) == LRS_SHUTDOWN && lws_is_ssl(wsi) && wsi->tls.ssl) { switch (__lws_tls_shutdown(wsi)) { case LWS_SSL_CAPABLE_DONE: case LWS_SSL_CAPABLE_ERROR: diff --git a/lib/tls/mbedtls/mbedtls-client.c b/lib/tls/mbedtls/mbedtls-client.c index fbf0a59c..fd9957b2 100644 --- a/lib/tls/mbedtls/mbedtls-client.c +++ b/lib/tls/mbedtls/mbedtls-client.c @@ -32,7 +32,7 @@ lws_ssl_client_bio_create(struct lws *wsi) { X509_VERIFY_PARAM *param; char hostname[128], *p; - const char *alpn_comma = wsi->context->alpn_default; + const char *alpn_comma = wsi->context->tls.alpn_default; struct alpn_ctx protos; if (lws_hdr_copy(wsi, hostname, sizeof(hostname), @@ -55,23 +55,23 @@ lws_ssl_client_bio_create(struct lws *wsi) p++; } - wsi->ssl = SSL_new(wsi->vhost->ssl_client_ctx); - if (!wsi->ssl) + wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_client_ctx); + if (!wsi->tls.ssl) return -1; - if (wsi->vhost->ssl_info_event_mask) - SSL_set_info_callback(wsi->ssl, lws_ssl_info_callback); + if (wsi->vhost->tls.ssl_info_event_mask) + SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); - if (!(wsi->use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { - param = SSL_get0_param(wsi->ssl); + if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { + param = SSL_get0_param(wsi->tls.ssl); /* Enable automatic hostname checks */ // X509_VERIFY_PARAM_set_hostflags(param, // X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); X509_VERIFY_PARAM_set1_host(param, hostname, 0); } - if (wsi->vhost->alpn) - alpn_comma = wsi->vhost->alpn; + if (wsi->vhost->tls.alpn) + alpn_comma = wsi->vhost->tls.alpn; if (lws_hdr_copy(wsi, hostname, sizeof(hostname), _WSI_TOKEN_CLIENT_ALPN) > 0) @@ -84,16 +84,16 @@ lws_ssl_client_bio_create(struct lws *wsi) sizeof(protos.data) - 1); /* with mbedtls, protos is not pointed to after exit from this call */ - SSL_set_alpn_select_cb(wsi->ssl, &protos); + SSL_set_alpn_select_cb(wsi->tls.ssl, &protos); /* * use server name indication (SNI), if supported, * when establishing connection */ - SSL_set_verify(wsi->ssl, SSL_VERIFY_PEER, + SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER, OpenSSL_client_verify_callback); - SSL_set_fd(wsi->ssl, wsi->desc.sockfd); + SSL_set_fd(wsi->tls.ssl, wsi->desc.sockfd); return 0; } @@ -106,23 +106,23 @@ int ERR_get_error(void) enum lws_ssl_capable_status lws_tls_client_connect(struct lws *wsi) { - int m, n = SSL_connect(wsi->ssl); + int m, n = SSL_connect(wsi->tls.ssl); const unsigned char *prot; unsigned int len; if (n == 1) { - SSL_get0_alpn_selected(wsi->ssl, &prot, &len); + SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len); lws_role_call_alpn_negotiated(wsi, (const char *)prot); lwsl_info("client connect OK\n"); return LWS_SSL_CAPABLE_DONE; } - m = SSL_get_error(wsi->ssl, n); + m = SSL_get_error(wsi->tls.ssl, n); - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; - if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; if (!n) /* we don't know what he wants, but he says to retry */ @@ -135,7 +135,7 @@ int lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len) { int n; - X509 *peer = SSL_get_peer_certificate(wsi->ssl); + X509 *peer = SSL_get_peer_certificate(wsi->tls.ssl); struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi]; char *sb = (char *)&pt->serv_buf[0]; @@ -146,7 +146,7 @@ lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len) } lwsl_info("peer provided cert\n"); - n = SSL_get_verify_result(wsi->ssl); + n = SSL_get_verify_result(wsi->tls.ssl); lws_latency(wsi->context, wsi, "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0); @@ -156,20 +156,20 @@ lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len) return 0; if (n == X509_V_ERR_HOSTNAME_MISMATCH && - (wsi->use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { + (wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { lwsl_info("accepting certificate for invalid hostname\n"); return 0; } if (n == X509_V_ERR_INVALID_CA && - (wsi->use_ssl & LCCSCF_ALLOW_SELFSIGNED)) { + (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)) { lwsl_info("accepting certificate from untrusted CA\n"); return 0; } if ((n == X509_V_ERR_CERT_NOT_YET_VALID || n == X509_V_ERR_CERT_HAS_EXPIRED) && - (wsi->use_ssl & LCCSCF_ALLOW_EXPIRED)) { + (wsi->tls.use_ssl & LCCSCF_ALLOW_EXPIRED)) { lwsl_info("accepting expired or not yet valid certificate\n"); return 0; @@ -205,8 +205,8 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } /* create context */ - vh->ssl_client_ctx = SSL_CTX_new(method); - if (!vh->ssl_client_ctx) { + vh->tls.ssl_client_ctx = SSL_CTX_new(method); + if (!vh->tls.ssl_client_ctx) { error = ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", error, ERR_error_string(error, @@ -222,17 +222,17 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } - vh->x509_client_CA = d2i_X509(NULL, buf, len); + vh->tls.x509_client_CA = d2i_X509(NULL, buf, len); free(buf); - if (!vh->x509_client_CA) { + if (!vh->tls.x509_client_CA) { lwsl_err("client CA: x509 parse failed\n"); return 1; } - if (!vh->ssl_ctx) - SSL_CTX_add_client_CA(vh->ssl_client_ctx, vh->x509_client_CA); + if (!vh->tls.ssl_ctx) + SSL_CTX_add_client_CA(vh->tls.ssl_client_ctx, vh->tls.x509_client_CA); else - SSL_CTX_add_client_CA(vh->ssl_ctx, vh->x509_client_CA); + SSL_CTX_add_client_CA(vh->tls.ssl_ctx, vh->tls.x509_client_CA); lwsl_notice("client loaded CA for verification %s\n", ca_filepath); diff --git a/lib/tls/mbedtls/mbedtls-server.c b/lib/tls/mbedtls/mbedtls-server.c index d3707f54..2a93468d 100644 --- a/lib/tls/mbedtls/mbedtls-server.c +++ b/lib/tls/mbedtls/mbedtls-server.c @@ -48,7 +48,7 @@ lws_tls_server_client_cert_verify_config(struct lws_vhost *vh) lwsl_notice("%s: vh %s requires client cert %d\n", __func__, vh->name, verify_options); - SSL_CTX_set_verify(vh->ssl_ctx, verify_options, NULL); + SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options, NULL); return 0; } @@ -71,7 +71,7 @@ lws_mbedtls_sni_cb(void *arg, mbedtls_ssl_context *mbedtls_ctx, vh = context->vhost_list; while (vh) { if (!vh->being_destroyed && - vh->ssl_ctx == SSL_get_SSL_CTX(ssl)) + vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl)) break; vh = vh->vhost_next; } @@ -93,7 +93,7 @@ lws_mbedtls_sni_cb(void *arg, mbedtls_ssl_context *mbedtls_ctx, vh->listen_port, vhost->name); /* select the ssl ctx from the selected vhost for this conn */ - SSL_set_SSL_CTX(ssl, vhost->ssl_ctx); + SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx); return 0; } @@ -158,7 +158,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, } f = 1; } - err = SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx, flen, p); + err = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, flen, p); if (!err) { free(p); lwsl_err("Problem loading cert\n"); @@ -178,7 +178,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, return 1; } - err = SSL_CTX_use_PrivateKey_ASN1(0, vhost->ssl_ctx, p, flen); + err = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx, p, flen); if (!err) { free(p); lwsl_err("Problem loading key\n"); @@ -195,13 +195,13 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, if (!private_key && !mem_privkey && vhost->protocols[0].callback(wsi, LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, - vhost->ssl_ctx, NULL, 0)) { + vhost->tls.ssl_ctx, NULL, 0)) { lwsl_err("ssl private key not set\n"); return 1; } - vhost->skipped_certs = 0; + vhost->tls.skipped_certs = 0; return 0; } @@ -215,13 +215,13 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, lws_filepos_t flen; int n; - vhost->ssl_ctx = SSL_CTX_new(method); /* create context */ - if (!vhost->ssl_ctx) { + vhost->tls.ssl_ctx = SSL_CTX_new(method); /* create context */ + if (!vhost->tls.ssl_ctx) { lwsl_err("problem creating ssl context\n"); return 1; } - if (!vhost->use_ssl || !info->ssl_cert_filepath) + if (!vhost->tls.use_ssl || !info->ssl_cert_filepath) return 0; if (info->ssl_ca_filepath) { @@ -235,7 +235,7 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, return 1; } - if (SSL_CTX_add_client_CA_ASN1(vhost->ssl_ctx, (int)flen, p) != 1) { + if (SSL_CTX_add_client_CA_ASN1(vhost->tls.ssl_ctx, (int)flen, p) != 1) { lwsl_err("%s: SSL_CTX_add_client_CA_ASN1 unhappy\n", __func__); free(p); @@ -257,20 +257,20 @@ int lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) { errno = 0; - wsi->ssl = SSL_new(wsi->vhost->ssl_ctx); - if (wsi->ssl == NULL) { + wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_ctx); + if (wsi->tls.ssl == NULL) { lwsl_err("SSL_new failed: errno %d\n", errno); lws_ssl_elaborate_error(); return 1; } - SSL_set_fd(wsi->ssl, accept_fd); + SSL_set_fd(wsi->tls.ssl, accept_fd); - if (wsi->vhost->ssl_info_event_mask) - SSL_set_info_callback(wsi->ssl, lws_ssl_info_callback); + if (wsi->vhost->tls.ssl_info_event_mask) + SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); - SSL_set_sni_callback(wsi->ssl, lws_mbedtls_sni_cb, wsi->context); + SSL_set_sni_callback(wsi->tls.ssl, lws_mbedtls_sni_cb, wsi->context); return 0; } @@ -279,7 +279,7 @@ int lws_tls_server_abort_connection(struct lws *wsi) { __lws_tls_shutdown(wsi); - SSL_free(wsi->ssl); + SSL_free(wsi->tls.ssl); return 0; } @@ -290,7 +290,7 @@ lws_tls_server_accept(struct lws *wsi) union lws_tls_cert_info_results ir; int m, n; - n = SSL_accept(wsi->ssl); + n = SSL_accept(wsi->tls.ssl); if (n == 1) { if (strstr(wsi->vhost->name, ".invalid")) { @@ -309,7 +309,7 @@ lws_tls_server_accept(struct lws *wsi) return LWS_SSL_CAPABLE_DONE; } - m = SSL_get_error(wsi->ssl, n); + m = SSL_get_error(wsi->tls.ssl, n); lwsl_debug("%s: %p: accept SSL_get_error %d errno %d\n", __func__, wsi, m, errno); @@ -320,7 +320,7 @@ lws_tls_server_accept(struct lws *wsi) if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL) return LWS_SSL_CAPABLE_ERROR; - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) { + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { lwsl_info("%s: WANT_READ change_pollfd failed\n", __func__); return LWS_SSL_CAPABLE_ERROR; @@ -329,7 +329,7 @@ lws_tls_server_accept(struct lws *wsi) lwsl_info("SSL_ERROR_WANT_READ\n"); return LWS_SSL_CAPABLE_MORE_SERVICE_READ; } - if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) { + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { lwsl_debug("%s: WANT_WRITE\n", __func__); if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) { @@ -543,7 +543,7 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, } // lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf)); - n = SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx, + n = SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, lws_ptr_diff(p, buf), buf); if (n != 1) { lws_free(pkey_asn1); @@ -554,7 +554,7 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, //lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n); /* and to use our generated private key */ - n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->ssl_ctx, pkey_asn1, m); + n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->tls.ssl_ctx, pkey_asn1, m); lws_free(pkey_asn1); if (n != 1) { lwsl_err("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n", diff --git a/lib/tls/mbedtls/ssl.c b/lib/tls/mbedtls/ssl.c index 12c6c168..44eb0614 100644 --- a/lib/tls/mbedtls/ssl.c +++ b/lib/tls/mbedtls/ssl.c @@ -45,13 +45,13 @@ lws_ssl_destroy(struct lws_vhost *vhost) LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) return; - 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); + if (vhost->tls.ssl_ctx) + SSL_CTX_free(vhost->tls.ssl_ctx); + if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx) + SSL_CTX_free(vhost->tls.ssl_client_ctx); - if (vhost->x509_client_CA) - X509_free(vhost->x509_client_CA); + if (vhost->tls.x509_client_CA) + X509_free(vhost->tls.x509_client_CA); } LWS_VISIBLE int @@ -61,13 +61,13 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n = 0, m; - if (!wsi->ssl) + if (!wsi->tls.ssl) return lws_ssl_capable_read_no_ssl(wsi, buf, len); lws_stats_atomic_bump(context, pt, LWSSTATS_C_API_READ, 1); errno = 0; - n = SSL_read(wsi->ssl, buf, len); + n = SSL_read(wsi->tls.ssl, buf, len); #if defined(LWS_WITH_ESP32) if (!n && errno == ENOTCONN) { lwsl_debug("%p: SSL_read ENOTCONN\n", wsi); @@ -95,18 +95,18 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) } if (n < 0) { - m = SSL_get_error(wsi->ssl, n); + m = SSL_get_error(wsi->tls.ssl, n); lwsl_debug("%p: ssl err %d errno %d\n", wsi, m, errno); if (m == SSL_ERROR_ZERO_RETURN || m == SSL_ERROR_SYSCALL) return LWS_SSL_CAPABLE_ERROR; - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) { + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.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 (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) { + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { lwsl_debug("%s: WANT_WRITE\n", __func__); lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi); return LWS_SSL_CAPABLE_MORE_SERVICE; @@ -132,26 +132,26 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) */ if (n != len) goto bail; - if (!wsi->ssl) + if (!wsi->tls.ssl) goto bail; - if (!SSL_pending(wsi->ssl)) + if (!SSL_pending(wsi->tls.ssl)) goto bail; - if (wsi->pending_read_list_next) + if (wsi->tls.pending_read_list_next) return n; - if (wsi->pending_read_list_prev) + if (wsi->tls.pending_read_list_prev) return n; - if (pt->pending_read_list == wsi) + if (pt->tls.pending_read_list == wsi) return n; /* add us to the linked list of guys with pending ssl */ - if (pt->pending_read_list) - pt->pending_read_list->pending_read_list_prev = wsi; + if (pt->tls.pending_read_list) + pt->tls.pending_read_list->tls.pending_read_list_prev = wsi; - wsi->pending_read_list_next = pt->pending_read_list; - wsi->pending_read_list_prev = NULL; - pt->pending_read_list = wsi; + wsi->tls.pending_read_list_next = pt->tls.pending_read_list; + wsi->tls.pending_read_list_prev = NULL; + pt->tls.pending_read_list = wsi; return n; bail: @@ -163,10 +163,10 @@ bail: LWS_VISIBLE int lws_ssl_pending(struct lws *wsi) { - if (!wsi->ssl) + if (!wsi->tls.ssl) return 0; - return SSL_pending(wsi->ssl); + return SSL_pending(wsi->tls.ssl); } LWS_VISIBLE int @@ -174,22 +174,22 @@ lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len) { int n, m; - if (!wsi->ssl) + if (!wsi->tls.ssl) return lws_ssl_capable_write_no_ssl(wsi, buf, len); - n = SSL_write(wsi->ssl, buf, len); + n = SSL_write(wsi->tls.ssl, buf, len); if (n > 0) return n; - m = SSL_get_error(wsi->ssl, n); + m = SSL_get_error(wsi->tls.ssl, n); if (m != SSL_ERROR_SYSCALL) { - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) { + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { lwsl_notice("%s: want read\n", __func__); return LWS_SSL_CAPABLE_MORE_SERVICE; } - if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) { + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { lws_set_blocking_send(wsi); lwsl_notice("%s: want write\n", __func__); @@ -221,7 +221,7 @@ lws_ssl_info_callback(const SSL *ssl, int where, int ret) if (!wsi) return; - if (!(where & wsi->vhost->ssl_info_event_mask)) + if (!(where & wsi->vhost->tls.ssl_info_event_mask)) return; si.where = where; @@ -239,23 +239,23 @@ lws_ssl_close(struct lws *wsi) { lws_sockfd_type n; - if (!wsi->ssl) + if (!wsi->tls.ssl) return 0; /* not handled */ #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); + if (wsi->vhost->tls.ssl_info_event_mask) + SSL_set_info_callback(wsi->tls.ssl, NULL); #endif - n = SSL_get_fd(wsi->ssl); + n = SSL_get_fd(wsi->tls.ssl); if (!wsi->socket_is_permanently_unusable) - SSL_shutdown(wsi->ssl); + SSL_shutdown(wsi->tls.ssl); compatible_close(n); - SSL_free(wsi->ssl); - wsi->ssl = NULL; + SSL_free(wsi->tls.ssl); + wsi->tls.ssl = NULL; if (!lwsi_role_client(wsi) && wsi->context->simultaneous_ssl_restriction && @@ -274,11 +274,11 @@ lws_ssl_close(struct lws *wsi) void lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) { - if (vhost->ssl_ctx) - SSL_CTX_free(vhost->ssl_ctx); + if (vhost->tls.ssl_ctx) + SSL_CTX_free(vhost->tls.ssl_ctx); - if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx) - SSL_CTX_free(vhost->ssl_client_ctx); + if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx) + SSL_CTX_free(vhost->tls.ssl_client_ctx); #if defined(LWS_WITH_ACME) lws_tls_acme_sni_cert_destroy(vhost); #endif @@ -292,16 +292,16 @@ lws_ssl_context_destroy(struct lws_context *context) lws_tls_ctx * lws_tls_ctx_from_wsi(struct lws *wsi) { - if (!wsi->ssl) + if (!wsi->tls.ssl) return NULL; - return SSL_get_SSL_CTX(wsi->ssl); + return SSL_get_SSL_CTX(wsi->tls.ssl); } enum lws_ssl_capable_status __lws_tls_shutdown(struct lws *wsi) { - int n = SSL_shutdown(wsi->ssl); + int n = SSL_shutdown(wsi->tls.ssl); lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd); @@ -315,14 +315,14 @@ __lws_tls_shutdown(struct lws *wsi) return LWS_SSL_CAPABLE_MORE_SERVICE; default: /* fatal error, or WANT */ - n = SSL_get_error(wsi->ssl, n); + n = SSL_get_error(wsi->tls.ssl, n); if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) { - if (SSL_want_read(wsi->ssl)) { + if (SSL_want_read(wsi->tls.ssl)) { lwsl_debug("(wants read)\n"); __lws_change_pollfd(wsi, 0, LWS_POLLIN); return LWS_SSL_CAPABLE_MORE_SERVICE_READ; } - if (SSL_want_write(wsi->ssl)) { + if (SSL_want_write(wsi->tls.ssl)) { lwsl_debug("(wants write)\n"); __lws_change_pollfd(wsi, 0, LWS_POLLOUT); return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; @@ -466,7 +466,7 @@ LWS_VISIBLE LWS_EXTERN int lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type, union lws_tls_cert_info_results *buf, size_t len) { - mbedtls_x509_crt *x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->ssl_ctx); + mbedtls_x509_crt *x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->tls.ssl_ctx); return lws_tls_mbedtls_cert_info(x509, type, buf, len); } @@ -479,14 +479,14 @@ lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, wsi = lws_get_network_wsi(wsi); - x509 = ssl_get_peer_mbedtls_x509_crt(wsi->ssl); + x509 = ssl_get_peer_mbedtls_x509_crt(wsi->tls.ssl); if (!x509) return -1; switch (type) { case LWS_TLS_CERT_INFO_VERIFIED: - buf->verified = SSL_get_verify_result(wsi->ssl) == X509_V_OK; + buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK; return 0; default: return lws_tls_mbedtls_cert_info(x509, type, buf, len); @@ -494,3 +494,14 @@ lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, return -1; } + +static int +tops_fake_POLLIN_for_buffered_mbedtls(struct lws_context_per_thread *pt) +{ + return lws_tls_fake_POLLIN_for_buffered(pt); +} + +const struct lws_tls_ops tls_ops_mbedtls = { + /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_mbedtls, + +}; diff --git a/lib/tls/openssl/openssl-client.c b/lib/tls/openssl/openssl-client.c index 63ceb329..e1602eda 100644 --- a/lib/tls/openssl/openssl-client.c +++ b/lib/tls/openssl/openssl-client.c @@ -43,13 +43,13 @@ OpenSSL_client_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx) if ((err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && - wsi->use_ssl & LCCSCF_ALLOW_SELFSIGNED) { + wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED) { lwsl_notice("accepting self-signed certificate (verify_callback)\n"); X509_STORE_CTX_set_error(x509_ctx, X509_V_OK); return 1; // ok } else if ((err == X509_V_ERR_CERT_NOT_YET_VALID || err == X509_V_ERR_CERT_HAS_EXPIRED) && - wsi->use_ssl & LCCSCF_ALLOW_EXPIRED) { + wsi->tls.use_ssl & LCCSCF_ALLOW_EXPIRED) { if (err == X509_V_ERR_CERT_NOT_YET_VALID) lwsl_notice("accepting not yet valid certificate (verify_callback)\n"); else if (err == X509_V_ERR_CERT_HAS_EXPIRED) @@ -97,7 +97,7 @@ lws_ssl_client_bio_create(struct lws *wsi) #if defined(LWS_HAVE_SSL_set_alpn_protos) && \ defined(LWS_HAVE_SSL_get0_alpn_selected) uint8_t openssl_alpn[40]; - const char *alpn_comma = wsi->context->alpn_default; + const char *alpn_comma = wsi->context->tls.alpn_default; int n; #endif @@ -124,8 +124,8 @@ lws_ssl_client_bio_create(struct lws *wsi) p++; } - wsi->ssl = SSL_new(wsi->vhost->ssl_client_ctx); - if (!wsi->ssl) { + wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_client_ctx); + if (!wsi->tls.ssl) { lwsl_err("SSL_new failed: %s\n", ERR_error_string(lws_ssl_get_error(wsi, 0), NULL)); lws_ssl_elaborate_error(); @@ -133,13 +133,13 @@ lws_ssl_client_bio_create(struct lws *wsi) } #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); + if (wsi->vhost->tls.ssl_info_event_mask) + SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); #endif #if defined LWS_HAVE_X509_VERIFY_PARAM_set1_host - if (!(wsi->use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { - param = SSL_get0_param(wsi->ssl); + if (!(wsi->tls.use_ssl & LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK)) { + param = SSL_get0_param(wsi->tls.ssl); /* Enable automatic hostname checks */ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); @@ -150,12 +150,12 @@ lws_ssl_client_bio_create(struct lws *wsi) #if !defined(USE_WOLFSSL) #ifndef USE_OLD_CYASSL /* OpenSSL_client_verify_callback will be called @ SSL_connect() */ - SSL_set_verify(wsi->ssl, SSL_VERIFY_PEER, OpenSSL_client_verify_callback); + SSL_set_verify(wsi->tls.ssl, SSL_VERIFY_PEER, OpenSSL_client_verify_callback); #endif #endif #if !defined(USE_WOLFSSL) - SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + SSL_set_mode(wsi->tls.ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #endif /* * use server name indication (SNI), if supported, @@ -164,16 +164,16 @@ lws_ssl_client_bio_create(struct lws *wsi) #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL #ifdef CYASSL_SNI_HOST_NAME - CyaSSL_UseSNI(wsi->ssl, CYASSL_SNI_HOST_NAME, hostname, strlen(hostname)); + CyaSSL_UseSNI(wsi->tls.ssl, CYASSL_SNI_HOST_NAME, hostname, strlen(hostname)); #endif #else #ifdef WOLFSSL_SNI_HOST_NAME - wolfSSL_UseSNI(wsi->ssl, WOLFSSL_SNI_HOST_NAME, hostname, strlen(hostname)); + wolfSSL_UseSNI(wsi->tls.ssl, WOLFSSL_SNI_HOST_NAME, hostname, strlen(hostname)); #endif #endif #else #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name(wsi->ssl, hostname); + SSL_set_tlsext_host_name(wsi->tls.ssl, hostname); #endif #endif @@ -186,31 +186,31 @@ lws_ssl_client_bio_create(struct lws *wsi) * Otherwise the connect will simply fail with error code -155 */ #ifdef USE_OLD_CYASSL - if (wsi->use_ssl == 2) - CyaSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL); + if (wsi->tls.use_ssl == 2) + CyaSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL); #else - if (wsi->use_ssl == 2) - wolfSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL); + if (wsi->tls.use_ssl == 2) + wolfSSL_set_verify(wsi->tls.ssl, SSL_VERIFY_NONE, NULL); #endif #endif /* USE_WOLFSSL */ - wsi->client_bio = BIO_new_socket((int)(long long)wsi->desc.sockfd, BIO_NOCLOSE); - SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio); + wsi->tls.client_bio = BIO_new_socket((int)(long long)wsi->desc.sockfd, BIO_NOCLOSE); + SSL_set_bio(wsi->tls.ssl, wsi->tls.client_bio, wsi->tls.client_bio); #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL - CyaSSL_set_using_nonblock(wsi->ssl, 1); + CyaSSL_set_using_nonblock(wsi->tls.ssl, 1); #else - wolfSSL_set_using_nonblock(wsi->ssl, 1); + wolfSSL_set_using_nonblock(wsi->tls.ssl, 1); #endif #else - BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */ + BIO_set_nbio(wsi->tls.client_bio, 1); /* nonblocking */ #endif #if defined(LWS_HAVE_SSL_set_alpn_protos) && \ defined(LWS_HAVE_SSL_get0_alpn_selected) - if (wsi->vhost->alpn) - alpn_comma = wsi->vhost->alpn; + if (wsi->vhost->tls.alpn) + alpn_comma = wsi->vhost->tls.alpn; #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) if (lws_hdr_copy(wsi, hostname, sizeof(hostname), _WSI_TOKEN_CLIENT_ALPN) > 0) @@ -222,10 +222,10 @@ lws_ssl_client_bio_create(struct lws *wsi) n = lws_alpn_comma_to_openssl(alpn_comma, openssl_alpn, sizeof(openssl_alpn) - 1); - SSL_set_alpn_protos(wsi->ssl, openssl_alpn, n); + SSL_set_alpn_protos(wsi->tls.ssl, openssl_alpn, n); #endif - SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index, wsi); + SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index, wsi); return 0; } @@ -238,11 +238,11 @@ lws_tls_client_connect(struct lws *wsi) char a[32]; unsigned int len; #endif - int m, n = SSL_connect(wsi->ssl); + int m, n = SSL_connect(wsi->tls.ssl); if (n == 1) { #if defined(LWS_HAVE_SSL_set_alpn_protos) && defined(LWS_HAVE_SSL_get0_alpn_selected) - SSL_get0_alpn_selected(wsi->ssl, &prot, &len); + SSL_get0_alpn_selected(wsi->tls.ssl, &prot, &len); if (len >= sizeof(a)) len = sizeof(a) - 1; @@ -260,10 +260,10 @@ lws_tls_client_connect(struct lws *wsi) if (m == SSL_ERROR_SYSCALL) return LWS_SSL_CAPABLE_ERROR; - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) return LWS_SSL_CAPABLE_MORE_SERVICE_READ; - if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; if (!n) /* we don't know what he wants, but he says to retry */ @@ -282,7 +282,7 @@ lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len) int n; lws_latency_pre(wsi->context, wsi); - n = SSL_get_verify_result(wsi->ssl); + n = SSL_get_verify_result(wsi->tls.ssl); lws_latency(wsi->context, wsi, "SSL_get_verify_result LWS_CONNMODE..HANDSHAKE", n, n > 0); @@ -293,14 +293,14 @@ lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, int ebuf_len) if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT || n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && - (wsi->use_ssl & LCCSCF_ALLOW_SELFSIGNED)) { + (wsi->tls.use_ssl & LCCSCF_ALLOW_SELFSIGNED)) { lwsl_info("accepting self-signed certificate\n"); return 0; } if ((n == X509_V_ERR_CERT_NOT_YET_VALID || n == X509_V_ERR_CERT_HAS_EXPIRED) && - (wsi->use_ssl & LCCSCF_ALLOW_EXPIRED)) { + (wsi->tls.use_ssl & LCCSCF_ALLOW_EXPIRED)) { lwsl_info("accepting expired certificate\n"); return 0; } @@ -353,8 +353,8 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 1; } /* create context */ - vh->ssl_client_ctx = SSL_CTX_new(method); - if (!vh->ssl_client_ctx) { + vh->tls.ssl_client_ctx = SSL_CTX_new(method); + if (!vh->tls.ssl_client_ctx) { error = ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", error, ERR_error_string(error, @@ -363,32 +363,32 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, } #ifdef SSL_OP_NO_COMPRESSION - SSL_CTX_set_options(vh->ssl_client_ctx, SSL_OP_NO_COMPRESSION); + SSL_CTX_set_options(vh->tls.ssl_client_ctx, SSL_OP_NO_COMPRESSION); #endif - SSL_CTX_set_options(vh->ssl_client_ctx, + SSL_CTX_set_options(vh->tls.ssl_client_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); if (cipher_list) - SSL_CTX_set_cipher_list(vh->ssl_client_ctx, cipher_list); + SSL_CTX_set_cipher_list(vh->tls.ssl_client_ctx, cipher_list); #ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS if (!lws_check_opt(vh->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS)) /* loads OS default CA certs */ - SSL_CTX_set_default_verify_paths(vh->ssl_client_ctx); + SSL_CTX_set_default_verify_paths(vh->tls.ssl_client_ctx); #endif /* openssl init for cert verification (for client sockets) */ if (!ca_filepath) { if (!SSL_CTX_load_verify_locations( - vh->ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS)) + vh->tls.ssl_client_ctx, NULL, LWS_OPENSSL_CLIENT_CERTS)) lwsl_err("Unable to load SSL Client certs from %s " "(set by LWS_OPENSSL_CLIENT_CERTS) -- " "client ssl isn't going to work\n", LWS_OPENSSL_CLIENT_CERTS); } else if (!SSL_CTX_load_verify_locations( - vh->ssl_client_ctx, ca_filepath, NULL)) { + vh->tls.ssl_client_ctx, ca_filepath, NULL)) { lwsl_err( "Unable to load SSL Client certs " "file from %s -- client ssl isn't " @@ -410,7 +410,7 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, return 0; lwsl_notice("%s: doing cert filepath %s\n", __func__, cert_filepath); - n = SSL_CTX_use_certificate_chain_file(vh->ssl_client_ctx, + n = SSL_CTX_use_certificate_chain_file(vh->tls.ssl_client_ctx, cert_filepath); if (n < 1) { lwsl_err("problem %d getting cert '%s'\n", n, @@ -422,9 +422,9 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, } if (private_key_filepath) { lwsl_notice("%s: doing private key filepath\n", __func__); - lws_ssl_bind_passphrase(vh->ssl_client_ctx, info); + lws_ssl_bind_passphrase(vh->tls.ssl_client_ctx, info); /* set the private key from KeyFile */ - if (SSL_CTX_use_PrivateKey_file(vh->ssl_client_ctx, + if (SSL_CTX_use_PrivateKey_file(vh->tls.ssl_client_ctx, private_key_filepath, SSL_FILETYPE_PEM) != 1) { lwsl_err("use_PrivateKey_file '%s'\n", private_key_filepath); @@ -435,7 +435,7 @@ lws_tls_client_create_vhost_context(struct lws_vhost *vh, private_key_filepath); /* verify private key */ - if (!SSL_CTX_check_private_key(vh->ssl_client_ctx)) { + if (!SSL_CTX_check_private_key(vh->tls.ssl_client_ctx)) { lwsl_err("Private SSL key doesn't match cert\n"); return 1; } diff --git a/lib/tls/openssl/openssl-server.c b/lib/tls/openssl/openssl-server.c index 0158b370..8a6bf149 100644 --- a/lib/tls/openssl/openssl-server.c +++ b/lib/tls/openssl/openssl-server.c @@ -72,11 +72,11 @@ lws_tls_server_client_cert_verify_config(struct lws_vhost *vh) LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED)) verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; - SSL_CTX_set_session_id_context(vh->ssl_ctx, (uint8_t *)vh->context, + SSL_CTX_set_session_id_context(vh->tls.ssl_ctx, (uint8_t *)vh->context, sizeof(void *)); /* absolutely require the client cert */ - SSL_CTX_set_verify(vh->ssl_ctx, verify_options, OpenSSL_verify_callback); + SSL_CTX_set_verify(vh->tls.ssl_ctx, verify_options, OpenSSL_verify_callback); return 0; } @@ -100,7 +100,7 @@ lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg) vh = context->vhost_list; while (vh) { if (!vh->being_destroyed && - vh->ssl_ctx == SSL_get_SSL_CTX(ssl)) + vh->tls.ssl_ctx == SSL_get_SSL_CTX(ssl)) break; vh = vh->vhost_next; } @@ -128,7 +128,7 @@ lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg) lwsl_info("SNI: Found: %s:%d\n", servername, vh->listen_port); /* select the ssl ctx from the selected vhost for this conn */ - SSL_set_SSL_CTX(ssl, vhost->ssl_ctx); + SSL_set_SSL_CTX(ssl, vhost->tls.ssl_ctx); return SSL_TLSEXT_ERR_OK; } @@ -182,11 +182,11 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, * memory-buffer private key image is PEM. */ #ifndef USE_WOLFSSL - if (SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx, + if (SSL_CTX_use_certificate_ASN1(vhost->tls.ssl_ctx, (int)len_mem_cert, (uint8_t *)mem_cert) != 1) { #else - if (wolfSSL_CTX_use_certificate_buffer(vhost->ssl_ctx, + if (wolfSSL_CTX_use_certificate_buffer(vhost->tls.ssl_ctx, (uint8_t *)mem_cert, (int)len_mem_cert, WOLFSSL_FILETYPE_ASN1) != 1) { @@ -205,10 +205,10 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, return 1; } #ifndef USE_WOLFSSL - if (SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vhost->ssl_ctx, + if (SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, vhost->tls.ssl_ctx, p, (long)(long long)flen) != 1) { #else - if (wolfSSL_CTX_use_PrivateKey_buffer(vhost->ssl_ctx, + if (wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, flen, WOLFSSL_FILETYPE_ASN1) != 1) { #endif lwsl_notice("unable to use memory privkey\n"); @@ -220,7 +220,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, } /* set the local certificate from CertFile */ - m = SSL_CTX_use_certificate_chain_file(vhost->ssl_ctx, cert); + m = SSL_CTX_use_certificate_chain_file(vhost->tls.ssl_ctx, cert); if (m != 1) { error = ERR_get_error(); lwsl_err("problem getting cert '%s' %lu: %s\n", @@ -232,7 +232,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, if (n != LWS_TLS_EXTANT_ALTERNATIVE && private_key) { /* set the private key from KeyFile */ - if (SSL_CTX_use_PrivateKey_file(vhost->ssl_ctx, private_key, + if (SSL_CTX_use_PrivateKey_file(vhost->tls.ssl_ctx, private_key, SSL_FILETYPE_PEM) != 1) { error = ERR_get_error(); lwsl_err("ssl problem getting key '%s' %lu: %s\n", @@ -244,7 +244,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, } else { if (vhost->protocols[0].callback(wsi, LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, - vhost->ssl_ctx, NULL, 0)) { + vhost->tls.ssl_ctx, NULL, 0)) { lwsl_err("ssl private key not set\n"); return 1; @@ -253,15 +253,15 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi, check_key: /* verify private key */ - if (!SSL_CTX_check_private_key(vhost->ssl_ctx)) { + if (!SSL_CTX_check_private_key(vhost->tls.ssl_ctx)) { lwsl_err("Private SSL key doesn't match cert\n"); return 1; } #if defined(LWS_HAVE_OPENSSL_ECDH_H) - if (vhost->ecdh_curve[0]) - ecdh_curve = vhost->ecdh_curve; + if (vhost->tls.ecdh_curve[0]) + ecdh_curve = vhost->tls.ecdh_curve; ecdh_nid = OBJ_sn2nid(ecdh_curve); if (NID_undef == ecdh_nid) { @@ -274,10 +274,10 @@ check_key: lwsl_err("SSL: Unable to create curve '%s'", ecdh_curve); return 1; } - SSL_CTX_set_tmp_ecdh(vhost->ssl_ctx, ecdh); + SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, ecdh); EC_KEY_free(ecdh); - SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_SINGLE_ECDH_USE); + SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_ECDH_USE); lwsl_notice(" SSL ECDH curve '%s'\n", ecdh_curve); @@ -287,9 +287,9 @@ check_key: /* Get X509 certificate from ssl context */ #if !defined(LWS_WITH_BORINGSSL) #if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS) - x = sk_X509_value(vhost->ssl_ctx->extra_certs, 0); + x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0); #else - SSL_CTX_get_extra_chain_certs_only(vhost->ssl_ctx, &extra_certs); + SSL_CTX_get_extra_chain_certs_only(vhost->tls.ssl_ctx, &extra_certs); if (extra_certs) x = sk_X509_value(extra_certs, 0); else @@ -323,7 +323,7 @@ check_key: lwsl_err("%s: ECDH key is NULL \n", __func__); return 1; } - SSL_CTX_set_tmp_ecdh(vhost->ssl_ctx, EC_key); + SSL_CTX_set_tmp_ecdh(vhost->tls.ssl_ctx, EC_key); EC_KEY_free(EC_key); #else @@ -332,7 +332,7 @@ check_key: #if defined(LWS_HAVE_OPENSSL_ECDH_H) && !defined(LWS_WITH_BORINGSSL) post_ecdh: #endif - vhost->skipped_certs = 0; + vhost->tls.skipped_certs = 0; return 0; } @@ -352,8 +352,8 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, (char *)vhost->context->pt[0].serv_buf)); return 1; } - vhost->ssl_ctx = SSL_CTX_new(method); /* create context */ - if (!vhost->ssl_ctx) { + vhost->tls.ssl_ctx = SSL_CTX_new(method); /* create context */ + if (!vhost->tls.ssl_ctx) { error = ERR_get_error(); lwsl_err("problem creating ssl context %lu: %s\n", error, ERR_error_string(error, @@ -361,46 +361,46 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info, return 1; } - SSL_CTX_set_ex_data(vhost->ssl_ctx, openssl_SSL_CTX_private_data_index, + SSL_CTX_set_ex_data(vhost->tls.ssl_ctx, openssl_SSL_CTX_private_data_index, (char *)vhost->context); /* Disable SSLv2 and SSLv3 */ - SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #ifdef SSL_OP_NO_COMPRESSION - SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_NO_COMPRESSION); + SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_NO_COMPRESSION); #endif - SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_SINGLE_DH_USE); - SSL_CTX_set_options(vhost->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_SINGLE_DH_USE); + SSL_CTX_set_options(vhost->tls.ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); if (info->ssl_cipher_list) - SSL_CTX_set_cipher_list(vhost->ssl_ctx, info->ssl_cipher_list); + SSL_CTX_set_cipher_list(vhost->tls.ssl_ctx, info->ssl_cipher_list); #if !defined(OPENSSL_NO_TLSEXT) - SSL_CTX_set_tlsext_servername_callback(vhost->ssl_ctx, + SSL_CTX_set_tlsext_servername_callback(vhost->tls.ssl_ctx, lws_ssl_server_name_cb); - SSL_CTX_set_tlsext_servername_arg(vhost->ssl_ctx, vhost->context); + SSL_CTX_set_tlsext_servername_arg(vhost->tls.ssl_ctx, vhost->context); #endif if (info->ssl_ca_filepath && - !SSL_CTX_load_verify_locations(vhost->ssl_ctx, + !SSL_CTX_load_verify_locations(vhost->tls.ssl_ctx, info->ssl_ca_filepath, NULL)) { lwsl_err("%s: SSL_CTX_load_verify_locations unhappy\n", __func__); } if (info->ssl_options_set) - SSL_CTX_set_options(vhost->ssl_ctx, info->ssl_options_set); + SSL_CTX_set_options(vhost->tls.ssl_ctx, info->ssl_options_set); /* SSL_clear_options introduced in 0.9.8m */ #if (OPENSSL_VERSION_NUMBER >= 0x009080df) && !defined(USE_WOLFSSL) if (info->ssl_options_clear) - SSL_CTX_clear_options(vhost->ssl_ctx, info->ssl_options_clear); + SSL_CTX_clear_options(vhost->tls.ssl_ctx, info->ssl_options_clear); #endif - lwsl_info(" SSL options 0x%lX\n", (unsigned long)SSL_CTX_get_options(vhost->ssl_ctx)); - if (!vhost->use_ssl || !info->ssl_cert_filepath) + lwsl_info(" SSL options 0x%lX\n", (unsigned long)SSL_CTX_get_options(vhost->tls.ssl_ctx)); + if (!vhost->tls.use_ssl || !info->ssl_cert_filepath) return 0; - lws_ssl_bind_passphrase(vhost->ssl_ctx, info); + lws_ssl_bind_passphrase(vhost->tls.ssl_ctx, info); return lws_tls_server_certs_load(vhost, wsi, info->ssl_cert_filepath, info->ssl_private_key_filepath, @@ -415,8 +415,8 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) #endif errno = 0; - wsi->ssl = SSL_new(wsi->vhost->ssl_ctx); - if (wsi->ssl == NULL) { + wsi->tls.ssl = SSL_new(wsi->vhost->tls.ssl_ctx); + if (wsi->tls.ssl == NULL) { lwsl_err("SSL_new failed: %d (errno %d)\n", lws_ssl_get_error(wsi, 0), errno); @@ -424,24 +424,24 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) return 1; } - SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index, wsi); - SSL_set_fd(wsi->ssl, (int)(long long)accept_fd); + SSL_set_ex_data(wsi->tls.ssl, openssl_websocket_private_data_index, wsi); + SSL_set_fd(wsi->tls.ssl, (int)(long long)accept_fd); #ifdef USE_WOLFSSL #ifdef USE_OLD_CYASSL - CyaSSL_set_using_nonblock(wsi->ssl, 1); + CyaSSL_set_using_nonblock(wsi->tls.ssl, 1); #else - wolfSSL_set_using_nonblock(wsi->ssl, 1); + wolfSSL_set_using_nonblock(wsi->tls.ssl, 1); #endif #else - SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - bio = SSL_get_rbio(wsi->ssl); + SSL_set_mode(wsi->tls.ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + bio = SSL_get_rbio(wsi->tls.ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else lwsl_notice("NULL rbio\n"); - bio = SSL_get_wbio(wsi->ssl); + bio = SSL_get_wbio(wsi->tls.ssl); if (bio) BIO_set_nbio(bio, 1); /* nonblocking */ else @@ -449,8 +449,8 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) #endif #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); + if (wsi->vhost->tls.ssl_info_event_mask) + SSL_set_info_callback(wsi->tls.ssl, lws_ssl_info_callback); #endif return 0; @@ -459,8 +459,8 @@ lws_tls_server_new_nonblocking(struct lws *wsi, lws_sockfd_type accept_fd) int lws_tls_server_abort_connection(struct lws *wsi) { - SSL_shutdown(wsi->ssl); - SSL_free(wsi->ssl); + SSL_shutdown(wsi->tls.ssl); + SSL_free(wsi->tls.ssl); return 0; } @@ -469,7 +469,7 @@ enum lws_ssl_capable_status lws_tls_server_accept(struct lws *wsi) { union lws_tls_cert_info_results ir; - int m, n = SSL_accept(wsi->ssl); + int m, n = SSL_accept(wsi->tls.ssl); if (n == 1) { n = lws_tls_peer_cert_info(wsi, LWS_TLS_CERT_INFO_COMMON_NAME, &ir, @@ -487,7 +487,7 @@ lws_tls_server_accept(struct lws *wsi) if (m == SSL_ERROR_SYSCALL || m == SSL_ERROR_SSL) return LWS_SSL_CAPABLE_ERROR; - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) { + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { if (lws_change_pollfd(wsi, 0, LWS_POLLIN)) { lwsl_info("%s: WANT_READ change_pollfd failed\n", __func__); @@ -497,7 +497,7 @@ lws_tls_server_accept(struct lws *wsi) lwsl_info("SSL_ERROR_WANT_READ\n"); return LWS_SSL_CAPABLE_MORE_SERVICE_READ; } - if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) { + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { lwsl_debug("%s: WANT_WRITE\n", __func__); if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) { @@ -561,33 +561,33 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, if (!gens) return 1; - vhost->ss = lws_zalloc(sizeof(*vhost->ss), "sni cert"); - if (!vhost->ss) { + vhost->tls.ss = lws_zalloc(sizeof(*vhost->tls.ss), "sni cert"); + if (!vhost->tls.ss) { GENERAL_NAMES_free(gens); return 1; } - vhost->ss->x509 = X509_new(); - if (!vhost->ss->x509) + vhost->tls.ss->x509 = X509_new(); + if (!vhost->tls.ss->x509) goto bail; - ASN1_INTEGER_set(X509_get_serialNumber(vhost->ss->x509), 1); - X509_gmtime_adj(X509_get_notBefore(vhost->ss->x509), 0); - X509_gmtime_adj(X509_get_notAfter(vhost->ss->x509), 3600); + ASN1_INTEGER_set(X509_get_serialNumber(vhost->tls.ss->x509), 1); + X509_gmtime_adj(X509_get_notBefore(vhost->tls.ss->x509), 0); + X509_gmtime_adj(X509_get_notAfter(vhost->tls.ss->x509), 3600); - vhost->ss->pkey = EVP_PKEY_new(); - if (!vhost->ss->pkey) + vhost->tls.ss->pkey = EVP_PKEY_new(); + if (!vhost->tls.ss->pkey) goto bail0; - if (lws_tls_openssl_rsa_new_key(&vhost->ss->rsa, 4096)) + if (lws_tls_openssl_rsa_new_key(&vhost->tls.ss->rsa, 4096)) goto bail1; - if (!EVP_PKEY_assign_RSA(vhost->ss->pkey, vhost->ss->rsa)) + if (!EVP_PKEY_assign_RSA(vhost->tls.ss->pkey, vhost->tls.ss->rsa)) goto bail2; - X509_set_pubkey(vhost->ss->x509, vhost->ss->pkey); + X509_set_pubkey(vhost->tls.ss->x509, vhost->tls.ss->pkey); - name = X509_get_subject_name(vhost->ss->x509); + name = X509_get_subject_name(vhost->tls.ss->x509); X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char *)"GB", -1, -1, 0); X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, @@ -598,7 +598,7 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, lwsl_notice("failed to add CN\n"); goto bail2; } - X509_set_issuer_name(vhost->ss->x509, name); + X509_set_issuer_name(vhost->tls.ss->x509, name); /* add the SAN payloads */ @@ -612,7 +612,7 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, GENERAL_NAME_set0_value(gen, GEN_DNS, ia5); sk_GENERAL_NAME_push(gens, gen); - if (X509_add1_ext_i2d(vhost->ss->x509, NID_subject_alt_name, + if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name, gens, 0, X509V3_ADD_APPEND) != 1) goto bail2; @@ -630,7 +630,7 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, GENERAL_NAME_set0_value(gen, GEN_DNS, ia5); sk_GENERAL_NAME_push(gens, gen); - if (X509_add1_ext_i2d(vhost->ss->x509, NID_subject_alt_name, + if (X509_add1_ext_i2d(vhost->tls.ss->x509, NID_subject_alt_name, gens, 0, X509V3_ADD_APPEND) != 1) goto bail2; @@ -638,33 +638,33 @@ lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a, } /* sign it with our private key */ - if (!X509_sign(vhost->ss->x509, vhost->ss->pkey, EVP_sha256())) + if (!X509_sign(vhost->tls.ss->x509, vhost->tls.ss->pkey, EVP_sha256())) goto bail2; #if 0 {/* useful to take a sample of a working cert for mbedtls to crib */ FILE *fp = fopen("/tmp/acme-temp-cert", "w+"); - i2d_X509_fp(fp, vhost->ss->x509); + i2d_X509_fp(fp, vhost->tls.ss->x509); fclose(fp); } #endif /* tell the vhost to use our crafted certificate */ - SSL_CTX_use_certificate(vhost->ssl_ctx, vhost->ss->x509); + SSL_CTX_use_certificate(vhost->tls.ssl_ctx, vhost->tls.ss->x509); /* and to use our generated private key */ - SSL_CTX_use_PrivateKey(vhost->ssl_ctx, vhost->ss->pkey); + SSL_CTX_use_PrivateKey(vhost->tls.ssl_ctx, vhost->tls.ss->pkey); return 0; bail2: - RSA_free(vhost->ss->rsa); + RSA_free(vhost->tls.ss->rsa); bail1: - EVP_PKEY_free(vhost->ss->pkey); + EVP_PKEY_free(vhost->tls.ss->pkey); bail0: - X509_free(vhost->ss->x509); + X509_free(vhost->tls.ss->x509); bail: - lws_free(vhost->ss); + lws_free(vhost->tls.ss); GENERAL_NAMES_free(gens); return 1; @@ -673,12 +673,12 @@ bail: void lws_tls_acme_sni_cert_destroy(struct lws_vhost *vhost) { - if (!vhost->ss) + if (!vhost->tls.ss) return; - EVP_PKEY_free(vhost->ss->pkey); - X509_free(vhost->ss->x509); - lws_free_set_NULL(vhost->ss); + EVP_PKEY_free(vhost->tls.ss->pkey); + X509_free(vhost->tls.ss->x509); + lws_free_set_NULL(vhost->tls.ss); } static int diff --git a/lib/tls/openssl/ssl.c b/lib/tls/openssl/ssl.c index 1b7d998d..d92ea781 100644 --- a/lib/tls/openssl/ssl.c +++ b/lib/tls/openssl/ssl.c @@ -29,11 +29,11 @@ int lws_ssl_get_error(struct lws *wsi, int n) { int m; - if (!wsi->ssl) + if (!wsi->tls.ssl) return 99; - m = SSL_get_error(wsi->ssl, n); - lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->ssl, n, m, errno); + m = SSL_get_error(wsi->tls.ssl, n); + lwsl_debug("%s: %p %d -> %d (errno %d)\n", __func__, wsi->tls.ssl, n, m, errno); return m; } @@ -162,10 +162,10 @@ lws_ssl_destroy(struct lws_vhost *vhost) LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) return; - 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); + if (vhost->tls.ssl_ctx) + SSL_CTX_free(vhost->tls.ssl_ctx); + if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx) + SSL_CTX_free(vhost->tls.ssl_client_ctx); // after 1.1.0 no need #if (OPENSSL_VERSION_NUMBER < 0x10100000) @@ -198,13 +198,13 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; int n = 0, m; - if (!wsi->ssl) + if (!wsi->tls.ssl) return lws_ssl_capable_read_no_ssl(wsi, buf, len); lws_stats_atomic_bump(context, pt, LWSSTATS_C_API_READ, 1); errno = 0; - n = SSL_read(wsi->ssl, buf, len); + n = SSL_read(wsi->tls.ssl, buf, len); #if defined(LWS_WITH_ESP32) if (!n && errno == ENOTCONN) { lwsl_debug("%p: SSL_read ENOTCONN\n", wsi); @@ -236,12 +236,12 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) m == SSL_ERROR_SYSCALL) return LWS_SSL_CAPABLE_ERROR; - if (SSL_want_read(wsi->ssl)) { + if (SSL_want_read(wsi->tls.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 (SSL_want_write(wsi->ssl)) { + if (SSL_want_write(wsi->tls.ssl)) { lwsl_debug("%s: WANT_WRITE\n", __func__); lwsl_debug("%p: LWS_SSL_CAPABLE_MORE_SERVICE\n", wsi); return LWS_SSL_CAPABLE_MORE_SERVICE; @@ -267,26 +267,26 @@ lws_ssl_capable_read(struct lws *wsi, unsigned char *buf, int len) */ if (n != len) goto bail; - if (!wsi->ssl) + if (!wsi->tls.ssl) goto bail; - if (!SSL_pending(wsi->ssl)) + if (!SSL_pending(wsi->tls.ssl)) goto bail; - if (wsi->pending_read_list_next) + if (wsi->tls.pending_read_list_next) return n; - if (wsi->pending_read_list_prev) + if (wsi->tls.pending_read_list_prev) return n; - if (pt->pending_read_list == wsi) + if (pt->tls.pending_read_list == wsi) return n; /* add us to the linked list of guys with pending ssl */ - if (pt->pending_read_list) - pt->pending_read_list->pending_read_list_prev = wsi; + if (pt->tls.pending_read_list) + pt->tls.pending_read_list->tls.pending_read_list_prev = wsi; - wsi->pending_read_list_next = pt->pending_read_list; - wsi->pending_read_list_prev = NULL; - pt->pending_read_list = wsi; + wsi->tls.pending_read_list_next = pt->tls.pending_read_list; + wsi->tls.pending_read_list_prev = NULL; + pt->tls.pending_read_list = wsi; return n; bail: @@ -298,10 +298,10 @@ bail: LWS_VISIBLE int lws_ssl_pending(struct lws *wsi) { - if (!wsi->ssl) + if (!wsi->tls.ssl) return 0; - return SSL_pending(wsi->ssl); + return SSL_pending(wsi->tls.ssl); } LWS_VISIBLE int @@ -309,22 +309,22 @@ lws_ssl_capable_write(struct lws *wsi, unsigned char *buf, int len) { int n, m; - if (!wsi->ssl) + if (!wsi->tls.ssl) return lws_ssl_capable_write_no_ssl(wsi, buf, len); - n = SSL_write(wsi->ssl, buf, len); + n = SSL_write(wsi->tls.ssl, buf, len); if (n > 0) return n; m = lws_ssl_get_error(wsi, n); if (m != SSL_ERROR_SYSCALL) { - if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->ssl)) { + if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { lwsl_notice("%s: want read\n", __func__); return LWS_SSL_CAPABLE_MORE_SERVICE; } - if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->ssl)) { + if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { lws_set_blocking_send(wsi); lwsl_notice("%s: want write\n", __func__); @@ -363,7 +363,7 @@ lws_ssl_info_callback(const SSL *ssl, int where, int ret) if (!wsi) return; - if (!(where & wsi->vhost->ssl_info_event_mask)) + if (!(where & wsi->vhost->tls.ssl_info_event_mask)) return; si.where = where; @@ -381,23 +381,23 @@ lws_ssl_close(struct lws *wsi) { lws_sockfd_type n; - if (!wsi->ssl) + if (!wsi->tls.ssl) return 0; /* not handled */ #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); + if (wsi->vhost->tls.ssl_info_event_mask) + SSL_set_info_callback(wsi->tls.ssl, NULL); #endif - n = SSL_get_fd(wsi->ssl); + n = SSL_get_fd(wsi->tls.ssl); if (!wsi->socket_is_permanently_unusable) - SSL_shutdown(wsi->ssl); + SSL_shutdown(wsi->tls.ssl); compatible_close(n); - SSL_free(wsi->ssl); - wsi->ssl = NULL; + SSL_free(wsi->tls.ssl); + wsi->tls.ssl = NULL; if (wsi->context->simultaneous_ssl_restriction && wsi->context->simultaneous_ssl-- == @@ -419,11 +419,11 @@ lws_ssl_close(struct lws *wsi) void lws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) { - if (vhost->ssl_ctx) - SSL_CTX_free(vhost->ssl_ctx); + if (vhost->tls.ssl_ctx) + SSL_CTX_free(vhost->tls.ssl_ctx); - if (!vhost->user_supplied_ssl_ctx && vhost->ssl_client_ctx) - SSL_CTX_free(vhost->ssl_client_ctx); + if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx) + SSL_CTX_free(vhost->tls.ssl_client_ctx); #if defined(LWS_WITH_ACME) lws_tls_acme_sni_cert_destroy(vhost); #endif @@ -459,10 +459,10 @@ lws_ssl_context_destroy(struct lws_context *context) lws_tls_ctx * lws_tls_ctx_from_wsi(struct lws *wsi) { - if (!wsi->ssl) + if (!wsi->tls.ssl) return NULL; - return SSL_get_SSL_CTX(wsi->ssl); + return SSL_get_SSL_CTX(wsi->tls.ssl); } enum lws_ssl_capable_status @@ -470,7 +470,7 @@ __lws_tls_shutdown(struct lws *wsi) { int n; - n = SSL_shutdown(wsi->ssl); + n = SSL_shutdown(wsi->tls.ssl); lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd); switch (n) { case 1: /* successful completion */ @@ -482,14 +482,14 @@ __lws_tls_shutdown(struct lws *wsi) return LWS_SSL_CAPABLE_MORE_SERVICE; default: /* fatal error, or WANT */ - n = SSL_get_error(wsi->ssl, n); + n = SSL_get_error(wsi->tls.ssl, n); if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) { - if (SSL_want_read(wsi->ssl)) { + if (SSL_want_read(wsi->tls.ssl)) { lwsl_debug("(wants read)\n"); __lws_change_pollfd(wsi, 0, LWS_POLLIN); return LWS_SSL_CAPABLE_MORE_SERVICE_READ; } - if (SSL_want_write(wsi->ssl)) { + if (SSL_want_write(wsi->tls.ssl)) { lwsl_debug("(wants write)\n"); __lws_change_pollfd(wsi, 0, LWS_POLLOUT); return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; @@ -643,7 +643,7 @@ lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type, union lws_tls_cert_info_results *buf, size_t len) { #if defined(LWS_HAVE_SSL_CTX_get0_certificate) - X509 *x509 = SSL_CTX_get0_certificate(vhost->ssl_ctx); + X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx); return lws_tls_openssl_cert_info(x509, type, buf, len); #else @@ -662,7 +662,7 @@ lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, wsi = lws_get_network_wsi(wsi); - x509 = SSL_get_peer_certificate(wsi->ssl); + x509 = SSL_get_peer_certificate(wsi->tls.ssl); if (!x509) { lwsl_debug("no peer cert\n"); @@ -672,7 +672,7 @@ lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, switch (type) { case LWS_TLS_CERT_INFO_VERIFIED: - buf->verified = SSL_get_verify_result(wsi->ssl) == X509_V_OK; + buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK; break; default: rc = lws_tls_openssl_cert_info(x509, type, buf, len); @@ -682,3 +682,14 @@ lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, return rc; } + +static int +tops_fake_POLLIN_for_buffered_openssl(struct lws_context_per_thread *pt) +{ + return lws_tls_fake_POLLIN_for_buffered(pt); +} + +const struct lws_tls_ops tls_ops_openssl = { + /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_openssl, + +}; diff --git a/lib/tls/private.h b/lib/tls/private.h index 7e7ab8ba..20f9bd36 100644 --- a/lib/tls/private.h +++ b/lib/tls/private.h @@ -21,6 +21,8 @@ * This is included from private-libwebsockets.h if LWS_WITH_TLS */ +#if defined(LWS_WITH_TLS) + #if defined(USE_WOLFSSL) #if defined(USE_OLD_CYASSL) #if defined(_WIN32) @@ -79,18 +81,77 @@ #endif /* not ESP32 */ #endif /* not USE_WOLFSSL */ -typedef SSL lws_tls_conn; -typedef SSL_CTX lws_tls_ctx; -typedef BIO lws_tls_bio; -typedef X509 lws_tls_x509; - -#define LWS_SSL_ENABLED(context) (context->use_ssl) +#endif /* LWS_WITH_TLS */ enum lws_tls_extant { LWS_TLS_EXTANT_NO, LWS_TLS_EXTANT_YES, LWS_TLS_EXTANT_ALTERNATIVE }; + +struct lws_context_per_thread; + +struct lws_tls_ops { + int (*fake_POLLIN_for_buffered)(struct lws_context_per_thread *pt); +}; + +#if defined(LWS_WITH_TLS) + +typedef SSL lws_tls_conn; +typedef SSL_CTX lws_tls_ctx; +typedef BIO lws_tls_bio; +typedef X509 lws_tls_x509; + + +#define LWS_SSL_ENABLED(context) (context->tls.use_ssl) + +extern const struct lws_tls_ops tls_ops_openssl, tls_ops_mbedtls; + +struct lws_context_tls { + char alpn_discovered[32]; + const char *alpn_default; +}; + +struct lws_pt_tls { + struct lws *pending_read_list; /* linked list */ +}; + +struct lws_tls_ss_pieces; + +struct alpn_ctx { + uint8_t data[23]; + uint8_t len; +}; + +struct lws_vhost_tls { + lws_tls_ctx *ssl_ctx; + lws_tls_ctx *ssl_client_ctx; + const char *alpn; + struct lws_tls_ss_pieces *ss; /* for acme tls certs */ + char *alloc_cert_path; + char *key_path; +#if defined(LWS_WITH_MBEDTLS) + lws_tls_x509 *x509_client_CA; +#endif + char ecdh_curve[16]; + struct alpn_ctx alpn_ctx; + + int use_ssl; + int allow_non_ssl_on_ssl_port; + int ssl_info_event_mask; + + unsigned int user_supplied_ssl_ctx:1; + unsigned int skipped_certs:1; +}; + +struct lws_lws_tls { + lws_tls_conn *ssl; + lws_tls_bio *client_bio; + struct lws *pending_read_list_prev, *pending_read_list_next; + unsigned int use_ssl; + unsigned int redirect_to_https:1; +}; + LWS_EXTERN void lws_context_init_alpn(struct lws_vhost *vhost); LWS_EXTERN enum lws_tls_extant @@ -125,7 +186,7 @@ lws_ssl_client_connect2(struct lws *wsi, char *errbuf, int len); LWS_EXTERN void lws_ssl_elaborate_error(void); LWS_EXTERN int -lws_ssl_anybody_has_buffered_read_tsi(struct lws_context *context, int tsi); +lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt); LWS_EXTERN int lws_gate_accepts(struct lws_context *context, int on); LWS_EXTERN void @@ -211,3 +272,8 @@ lws_context_init_client_ssl(const struct lws_context_creation_info *info, LWS_EXTERN void lws_ssl_info_callback(const lws_tls_conn *ssl, int where, int ret); + +int +lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt); + +#endif \ No newline at end of file diff --git a/lib/tls/tls-client.c b/lib/tls/tls-client.c index bc10a99f..a122155e 100644 --- a/lib/tls/tls-client.c +++ b/lib/tls/tls-client.c @@ -115,14 +115,14 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) return 0; - if (vhost->ssl_client_ctx) + if (vhost->tls.ssl_client_ctx) return 0; if (info->provided_client_ssl_ctx) { /* use the provided OpenSSL context if given one */ - vhost->ssl_client_ctx = info->provided_client_ssl_ctx; + vhost->tls.ssl_client_ctx = info->provided_client_ssl_ctx; /* nothing for lib to delete */ - vhost->user_supplied_ssl_ctx = 1; + vhost->tls.user_supplied_ssl_ctx = 1; return 0; } @@ -144,7 +144,7 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info, vhost->protocols[0].callback(&wsi, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS, - vhost->ssl_client_ctx, NULL, 0); + vhost->tls.ssl_client_ctx, NULL, 0); return 0; } diff --git a/lib/tls/tls-server.c b/lib/tls/tls-server.c index 5cfa0b32..01e4ca63 100644 --- a/lib/tls/tls-server.c +++ b/lib/tls/tls-server.c @@ -45,18 +45,18 @@ lws_context_init_alpn(struct lws_vhost *vhost) { #if defined(LWS_WITH_MBEDTLS) || (defined(OPENSSL_VERSION_NUMBER) && \ OPENSSL_VERSION_NUMBER >= 0x10002000L) - const char *alpn_comma = vhost->context->alpn_default; + const char *alpn_comma = vhost->context->tls.alpn_default; - if (vhost->alpn) - alpn_comma = vhost->alpn; + if (vhost->tls.alpn) + alpn_comma = vhost->tls.alpn; lwsl_info(" Server '%s' advertising ALPN: %s\n", vhost->name, alpn_comma); - vhost->alpn_ctx.len = lws_alpn_comma_to_openssl(alpn_comma, - vhost->alpn_ctx.data, - sizeof(vhost->alpn_ctx.data) - 1); + vhost->tls.alpn_ctx.len = lws_alpn_comma_to_openssl(alpn_comma, + vhost->tls.alpn_ctx.data, + sizeof(vhost->tls.alpn_ctx.data) - 1); - SSL_CTX_set_alpn_select_cb(vhost->ssl_ctx, alpn_cb, &vhost->alpn_ctx); + SSL_CTX_set_alpn_select_cb(vhost->tls.ssl_ctx, alpn_cb, &vhost->tls.alpn_ctx); #else lwsl_err( " HTTP2 / ALPN configured but not supported by OpenSSL 0x%lx\n", @@ -73,7 +73,7 @@ lws_tls_server_conn_alpn(struct lws *wsi) char cstr[10]; unsigned len; - SSL_get0_alpn_selected(wsi->ssl, &name, &len); + SSL_get0_alpn_selected(wsi->tls.ssl, &name, &len); if (!len) { lwsl_info("no ALPN upgrade\n"); return 0; @@ -86,7 +86,7 @@ lws_tls_server_conn_alpn(struct lws *wsi) cstr[len] = '\0'; lwsl_info("negotiated '%s' using ALPN\n", cstr); - wsi->use_ssl |= LCCSCF_USE_SSL; + wsi->tls.use_ssl |= LCCSCF_USE_SSL; return lws_role_call_alpn_negotiated(wsi, (const char *)cstr); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L @@ -103,7 +103,7 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) { - vhost->use_ssl = 0; + vhost->tls.use_ssl = 0; return 0; } @@ -121,14 +121,14 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, if (info->port != CONTEXT_PORT_NO_LISTEN) { - vhost->use_ssl = lws_check_opt(vhost->options, + vhost->tls.use_ssl = lws_check_opt(vhost->options, LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX); - if (vhost->use_ssl && info->ssl_cipher_list) + if (vhost->tls.use_ssl && info->ssl_cipher_list) lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list); - if (vhost->use_ssl) + if (vhost->tls.use_ssl) lwsl_notice(" Using SSL mode\n"); else lwsl_notice(" Using non-SSL mode\n"); @@ -149,13 +149,13 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, if (lws_check_opt(info->options, LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT)) /* Normally SSL listener rejects non-ssl, optionally allow */ - vhost->allow_non_ssl_on_ssl_port = 1; + vhost->tls.allow_non_ssl_on_ssl_port = 1; /* * give user code a chance to load certs into the server * allowing it to verify incoming client certs */ - if (vhost->use_ssl) { + if (vhost->tls.use_ssl) { if (lws_tls_server_vhost_backend_init(info, vhost, &wsi)) return -1; @@ -163,11 +163,11 @@ lws_context_init_server_ssl(const struct lws_context_creation_info *info, if (vhost->protocols[0].callback(&wsi, LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, - vhost->ssl_ctx, vhost, 0)) + vhost->tls.ssl_ctx, vhost, 0)) return -1; } - if (vhost->use_ssl) + if (vhost->tls.use_ssl) lws_context_init_alpn(vhost); return 0; @@ -190,7 +190,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) switch (lwsi_state(wsi)) { case LRS_SSL_INIT: - if (wsi->ssl) + if (wsi->tls.ssl) lwsl_err("%s: leaking ssl\n", __func__); if (accept_fd == LWS_SOCK_INVALID) assert(0); @@ -246,7 +246,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) lws_latency_pre(context, wsi); - if (wsi->vhost->allow_non_ssl_on_ssl_port) { + if (wsi->vhost->tls.allow_non_ssl_on_ssl_port) { n = recv(wsi->desc.sockfd, (char *)pt->serv_buf, context->pt_serv_buf_size, MSG_PEEK); @@ -268,7 +268,7 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) * connection and try to handle as a HTTP * connection upgrade directly. */ - wsi->use_ssl = 0; + wsi->tls.use_ssl = 0; lws_tls_server_abort_connection(wsi); /* @@ -276,10 +276,10 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd) * when ssl is enabled and normally * mandatory */ - wsi->ssl = NULL; + wsi->tls.ssl = NULL; if (lws_check_opt(context->options, LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS)) - wsi->redirect_to_https = 1; + wsi->tls.redirect_to_https = 1; lwsl_debug("accepted as non-ssl\n"); goto accepted; } @@ -351,8 +351,8 @@ accepted: /* adapt our vhost to match the SNI SSL_CTX that was chosen */ vh = context->vhost_list; while (vh) { - if (!vh->being_destroyed && wsi->ssl && - vh->ssl_ctx == lws_tls_ctx_from_wsi(wsi)) { + if (!vh->being_destroyed && wsi->tls.ssl && + vh->tls.ssl_ctx == lws_tls_ctx_from_wsi(wsi)) { lwsl_info("setting wsi to vh %s\n", vh->name); wsi->vhost = vh; break; diff --git a/lib/tls/tls.c b/lib/tls/tls.c index 38394642..916b99f2 100644 --- a/lib/tls/tls.c +++ b/lib/tls/tls.c @@ -21,24 +21,29 @@ #include "private-libwebsockets.h" -int -lws_ssl_anybody_has_buffered_read_tsi(struct lws_context *context, int tsi) -{ - struct lws_context_per_thread *pt = &context->pt[tsi]; - struct lws *wsi, *wsi_next; +/* + * fakes POLLIN on all tls guys with buffered rx + * + * returns nonzero if any tls guys had POLLIN faked + */ - wsi = pt->pending_read_list; +int +lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt) +{ + struct lws *wsi, *wsi_next; + int ret = 0; + + wsi = pt->tls.pending_read_list; while (wsi) { - wsi_next = wsi->pending_read_list_next; + wsi_next = wsi->tls.pending_read_list_next; pt->fds[wsi->position_in_fds_table].revents |= pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN; - if (pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN) - return 1; + ret |= pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN; wsi = wsi_next; } - return 0; + return !!ret; } void @@ -47,26 +52,26 @@ __lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi) struct lws_context *context = wsi->context; struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; - if (!wsi->pending_read_list_prev && - !wsi->pending_read_list_next && - pt->pending_read_list != wsi) + if (!wsi->tls.pending_read_list_prev && + !wsi->tls.pending_read_list_next && + pt->tls.pending_read_list != wsi) /* we are not on the list */ return; /* point previous guy's next to our next */ - if (!wsi->pending_read_list_prev) - pt->pending_read_list = wsi->pending_read_list_next; + if (!wsi->tls.pending_read_list_prev) + pt->tls.pending_read_list = wsi->tls.pending_read_list_next; else - wsi->pending_read_list_prev->pending_read_list_next = - wsi->pending_read_list_next; + wsi->tls.pending_read_list_prev->tls.pending_read_list_next = + wsi->tls.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; + if (wsi->tls.pending_read_list_next) + wsi->tls.pending_read_list_next->tls.pending_read_list_prev = + wsi->tls.pending_read_list_prev; - wsi->pending_read_list_prev = NULL; - wsi->pending_read_list_next = NULL; + wsi->tls.pending_read_list_prev = NULL; + wsi->tls.pending_read_list_next = NULL; } void @@ -238,7 +243,7 @@ lws_tls_check_cert_lifetime(struct lws_vhost *v) struct lws_acme_cert_aging_args caa; int n; - if (v->ssl_ctx && !v->skipped_certs) { + if (v->tls.ssl_ctx && !v->tls.skipped_certs) { if (now < 1464083026) /* May 2016 */ /* our clock is wrong and we can't judge the certs */ @@ -410,7 +415,7 @@ lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert, if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) && (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) { lwsl_notice("Ignoring missing %s or %s\n", cert, private_key); - vhost->skipped_certs = 1; + vhost->tls.skipped_certs = 1; return LWS_TLS_EXTANT_NO; } @@ -439,14 +444,14 @@ lws_tls_cert_updated(struct lws_context *context, const char *certpath, lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) { wsi.vhost = v; - if (v->alloc_cert_path && v->key_path && - !strcmp(v->alloc_cert_path, certpath) && - !strcmp(v->key_path, keypath)) { + if (v->tls.alloc_cert_path && v->tls.key_path && + !strcmp(v->tls.alloc_cert_path, certpath) && + !strcmp(v->tls.key_path, keypath)) { lws_tls_server_certs_load(v, &wsi, certpath, keypath, mem_cert, len_mem_cert, mem_privkey, len_mem_privkey); - if (v->skipped_certs) + if (v->tls.skipped_certs) lwsl_notice("%s: vhost %s: cert unset\n", __func__, v->name); } @@ -462,13 +467,13 @@ lws_gate_accepts(struct lws_context *context, int on) struct lws_vhost *v = context->vhost_list; lwsl_notice("%s: on = %d\n", __func__, on); - context->ssl_gate_accepts = !on; + #if defined(LWS_WITH_STATS) context->updated = 1; #endif while (v) { - if (v->use_ssl && v->lserv_wsi && + if (v->tls.use_ssl && v->lserv_wsi && lws_change_pollfd(v->lserv_wsi, (LWS_POLLIN) * !on, (LWS_POLLIN) * on)) lwsl_notice("Unable to set accept POLLIN %d\n", on); diff --git a/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c b/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c index 983c526f..7fb811ee 100644 --- a/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c +++ b/minimal-examples/client-server/minimal-ws-proxy/protocol_lws_minimal.c @@ -17,6 +17,7 @@ #endif #include +#include /* one of these created for each message */ diff --git a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c index a5f3ed2b..fc0f19ba 100644 --- a/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c +++ b/minimal-examples/http-client/minimal-http-client-post/minimal-http-client-post.c @@ -240,7 +240,8 @@ int main(int argc, const char **argv) * OpenSSL uses the system trust store. mbedTLS has to be told which * CA to trust explicitly. */ - info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; + if (!lws_cmdline_option(argc, argv, "-l")) + info.client_ssl_ca_filepath = "./libwebsockets.org.cer"; #endif context = lws_create_context(&info); diff --git a/minimal-examples/selftests-library.sh b/minimal-examples/selftests-library.sh index feef8f89..88677c8f 100755 --- a/minimal-examples/selftests-library.sh +++ b/minimal-examples/selftests-library.sh @@ -42,10 +42,12 @@ spawn() { fi fi + QQ=`pwd` cd $SCRIPT_DIR cd $2 $3 $4 $5 > $LOGPATH/$MYTEST/serverside.log 2> $LOGPATH/$MYTEST/serverside.log & SPID=$! + cd $QQ sleep 0.5s # echo "launched prerequisite $SPID" } @@ -80,6 +82,7 @@ dotest() { R=`cat $2/$MYTEST/$T.result` cat $2/$MYTEST/$T.log | tail -n 3 > $2/$MYTEST/$T.time if [ $R -ne 0 ] ; then + pwd echo cat $2/$MYTEST/$T.log echo diff --git a/minimal-examples/selftests.sh b/minimal-examples/selftests.sh index 7c860419..ea8ceeb2 100755 --- a/minimal-examples/selftests.sh +++ b/minimal-examples/selftests.sh @@ -15,6 +15,10 @@ echo LOGGING_PATH=/tmp/logs +# for mebedtls, we need the CA certs in ./build where we run from + +cp ../minimal-examples/http-client/minimal-http-client-multi/warmcat.com.cer . +cp ../minimal-examples/http-client/minimal-http-client-post/libwebsockets.org.cer . MINEX=`dirname $0` MINEX=`realpath $MINEX` diff --git a/plugins/protocol_lws_sshd_demo.c b/plugins/protocol_lws_sshd_demo.c index 6e2af543..ad3d6ae0 100644 --- a/plugins/protocol_lws_sshd_demo.c +++ b/plugins/protocol_lws_sshd_demo.c @@ -28,6 +28,7 @@ #include #include +#include #define TEST_SERVER_KEY_PATH "/etc/lws-test-sshd-server-key" diff --git a/scripts/attack.sh b/scripts/attack.sh index 6fe21df6..a6946bbc 100755 --- a/scripts/attack.sh +++ b/scripts/attack.sh @@ -554,15 +554,17 @@ for i in \ /a/w/../a \ /path/to/dir/../other/dir \ ; do - -R=`rm -f /tmp/lwscap ; echo -n -e "GET $i HTTP/1.0\r\n\r\n" | $LWS_NC --server $SERVER --port $PORT 2>/dev/null > /tmp/lwscap; head -n1 /tmp/lwscap| cut -d' ' -f2` - +LEN=`stat $LOG -c %s` +rm -f /tmp/lwscap1 +echo -n -e "GET $i HTTP/1.0\r\n\r\n" | $LWS_NC --server $SERVER --port $PORT 2>/dev/null > /tmp/lwscap1 +R=`cat /tmp/lwscap1| head -n 1 | cut -d' ' -f 2` #cat $LOG #echo ==== $R if [ "$R" != "403" ]; then - U=`cat $LOG | grep Method: | tail -n 1 | cut -d"'" -f4 | sed "s|\\'||g"` + U=`dd if=$LOG bs=1 skip=$LEN 2>/dev/null| grep "Method:" | tr -s ' ' | cut -d"'" -f4` +#dd if=$LOG bs=1 skip=$LEN 2>/dev/null echo "- \"$i\" -> $R \"$U\"" >>/tmp/results else echo "- \"$i\" -> $R" >>/tmp/results diff --git a/scripts/travis_control.sh b/scripts/travis_control.sh index a5fe7e67..6603953b 100755 --- a/scripts/travis_control.sh +++ b/scripts/travis_control.sh @@ -1,9 +1,11 @@ #/bin/bash if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "osx" ]; then - mkdir build && cd build && - cmake -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" $CMAKE_ARGS .. && - cmake --build . + if [ "$LWS_METHOD" != "mbedtls" ] ; then + mkdir build && cd build && + cmake -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" $CMAKE_ARGS .. && + cmake --build . + fi else if [ "$COVERITY_SCAN_BRANCH" != 1 -a "$TRAVIS_OS_NAME" = "linux" ]; then mkdir build && cd build && @@ -20,12 +22,22 @@ else else if [ "$LWS_METHOD" = "smp" ] ; then cmake -DLWS_OPENSSL_LIBRARIES="/usr/local/lib/libssl.so;/usr/local/lib/libcrypto.so" \ - -DLWS_OPENSSL_INCLUDE_DIRS="/usr/local/include/openssl" $CMAKE_ARGS .. && + -DLWS_OPENSSL_INCLUDE_DIRS="/usr/local/include/openssl" $CMAKE_ARGS .. && cmake --build . && ../scripts/h2load-smp.sh else - cmake $CMAKE_ARGS .. && - cmake --build . + if [ "$LWS_METHOD" = "mbedtls" ] ; then + cmake $CMAKE_ARGS .. && + cmake --build . && + sudo make install && + ../minimal-examples/selftests.sh && + ../scripts/h2spec.sh && + ../scripts/h2load.sh && + ../scripts/attack.sh + else + cmake $CMAKE_ARGS .. && + cmake --build . + fi fi fi fi diff --git a/scripts/travis_install.sh b/scripts/travis_install.sh index 4cbc0023..c52bb444 100755 --- a/scripts/travis_install.sh +++ b/scripts/travis_install.sh @@ -8,7 +8,7 @@ then if [ "$LWS_METHOD" == "lwsws" ]; then - sudo apt-get install -y -qq realpath libjemalloc1 libev4 + sudo apt-get install -y -qq realpath libjemalloc1 libev4 libuv-dev sudo apt-get remove python-six sudo pip install six>=1.9 sudo pip install Twisted==16.0.0 @@ -21,6 +21,16 @@ then sudo update-ca-certificates fi + if [ "$LWS_METHOD" == "mbedtls" ]; + then + sudo apt-get install -y -qq realpath libjemalloc1 libev4 libuv-dev + wget https://libwebsockets.org/openssl-1.1.0-trusty.tar.bz2 -O/tmp/openssl.tar.bz2 + cd / + sudo tar xf /tmp/openssl.tar.bz2 + sudo ldconfig + sudo update-ca-certificates + fi + if [ "$LWS_METHOD" == "smp" ]; then sudo apt-get install -y -qq realpath libjemalloc1 libev4