mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-30 00:00:16 +01:00
tls: client: session cache synthetic cb
This commit is contained in:
parent
f1ff43ddea
commit
3ae611cdca
9 changed files with 139 additions and 14 deletions
|
@ -59,6 +59,20 @@ be treated with caution.
|
|||
Filling, expiring and consulting the session cache for client connections is
|
||||
performed automatically.
|
||||
|
||||
### tls library differences
|
||||
|
||||
Mbedtls supports clientside session caching in lws, but it does not have a
|
||||
session message arrival callback to synchronize updating the client session
|
||||
cache like openssl does.
|
||||
|
||||
Separately, the session cb in boringssl is reportedly nonfunctional at the
|
||||
moment.
|
||||
|
||||
To solve both cases, lws will schedule a check for the session at +500ms after
|
||||
the tls negotiation completed, and for the case the connection doesn't last
|
||||
500ms or the server is slow issuing the message, also attempt to update the
|
||||
cache at the time the tls connection object is closing.
|
||||
|
||||
### Session namespacing in lws
|
||||
|
||||
Internally sessions are referred to by a vhostname.hostname.port tuple.
|
||||
|
|
|
@ -268,6 +268,28 @@ bail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(LWS_TLS_SYNTHESIZE_CB)
|
||||
|
||||
/*
|
||||
* On openssl, there is an async cb coming when the server issues the session
|
||||
* information on the link, so we can pick it up and update the cache at the
|
||||
* right time.
|
||||
*
|
||||
* On mbedtls and some version at least of borning ssl, this cb is either not
|
||||
* part of the tls library apis or fails to arrive.
|
||||
*/
|
||||
|
||||
void
|
||||
lws_sess_cache_synth_cb(lws_sorted_usec_list_t *sul)
|
||||
{
|
||||
struct lws_lws_tls *tls = lws_container_of(sul, struct lws_lws_tls,
|
||||
sul_cb_synth);
|
||||
struct lws *wsi = lws_container_of(tls, struct lws, tls);
|
||||
|
||||
lws_tls_session_new_mbedtls(wsi);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
lws_tls_session_cache(struct lws_vhost *vh, uint32_t ttl)
|
||||
{
|
||||
|
|
|
@ -255,6 +255,15 @@ lws_ssl_close(struct lws *wsi)
|
|||
SSL_set_info_callback(wsi->tls.ssl, NULL);
|
||||
#endif
|
||||
|
||||
#if defined(LWS_TLS_SYNTHESIZE_CB)
|
||||
lws_sul_cancel(&wsi->tls.sul_cb_synth);
|
||||
/*
|
||||
* ... check the session in case it did not live long enough to get
|
||||
* the scheduled callback to sample it
|
||||
*/
|
||||
lws_sess_cache_synth_cb(&wsi->tls.sul_cb_synth);
|
||||
#endif
|
||||
|
||||
n = SSL_get_fd(wsi->tls.ssl);
|
||||
if (!wsi->socket_is_permanently_unusable)
|
||||
SSL_shutdown(wsi->tls.ssl);
|
||||
|
|
|
@ -499,6 +499,12 @@ lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t elen)
|
|||
|
||||
lws_role_call_alpn_negotiated(wsi, (const char *)a);
|
||||
#endif
|
||||
#if defined(LWS_TLS_SYNTHESIZE_CB)
|
||||
lws_sul_schedule(wsi->a.context, wsi->tsi,
|
||||
&wsi->tls.sul_cb_synth,
|
||||
lws_sess_cache_synth_cb, 500 * LWS_US_PER_MS);
|
||||
#endif
|
||||
|
||||
lwsl_info("client connect OK\n");
|
||||
lws_openssl_describe_cipher(wsi);
|
||||
return LWS_SSL_CAPABLE_DONE;
|
||||
|
|
|
@ -91,9 +91,22 @@ lws_tls_reuse_session(struct lws *wsi)
|
|||
}
|
||||
|
||||
lwsl_tlssess("%s: %s\n", __func__, (const char *)&ts[1]);
|
||||
wsi->tls_session_reused = 1;
|
||||
|
||||
SSL_set_session(wsi->tls.ssl, ts->session);
|
||||
if (!SSL_set_session(wsi->tls.ssl, ts->session)) {
|
||||
lwsl_err("%s: session not set for %s\n", __func__, tag);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
#if !defined(USE_WOLFSSL)
|
||||
/* extend session lifetime */
|
||||
SSL_SESSION_set_time(ts->session,
|
||||
#if defined(OPENSSL_IS_BORINGSSL)
|
||||
(unsigned long)
|
||||
#else
|
||||
(long)
|
||||
#endif
|
||||
time(NULL));
|
||||
#endif
|
||||
|
||||
/* keep our session list sorted in lru -> mru order */
|
||||
|
||||
|
@ -144,7 +157,6 @@ lws_tls_session_expiry_cb(lws_sorted_usec_list_t *sul)
|
|||
struct lws_vhost *vh = lws_container_of(ts->list.owner,
|
||||
struct lws_vhost, tls_sessions);
|
||||
|
||||
lws_sul_cancel(&ts->sul_ttl);
|
||||
lws_context_lock(vh->context, __func__); /* -------------- cx { */
|
||||
lws_vhost_lock(vh); /* -------------- vh { */
|
||||
__lws_tls_session_destroy(ts);
|
||||
|
@ -280,6 +292,47 @@ bail:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(LWS_TLS_SYNTHESIZE_CB)
|
||||
|
||||
/*
|
||||
* On openssl, there is an async cb coming when the server issues the session
|
||||
* information on the link, so we can pick it up and update the cache at the
|
||||
* right time.
|
||||
*
|
||||
* On mbedtls and some version at least of borning ssl, this cb is either not
|
||||
* part of the tls library apis or fails to arrive.
|
||||
*
|
||||
* This synthetic cb is called instead for those build cases, scheduled for
|
||||
* +500ms after the tls negotiation completed.
|
||||
*/
|
||||
|
||||
void
|
||||
lws_sess_cache_synth_cb(lws_sorted_usec_list_t *sul)
|
||||
{
|
||||
struct lws_lws_tls *tls = lws_container_of(sul, struct lws_lws_tls,
|
||||
sul_cb_synth);
|
||||
struct lws *wsi = lws_container_of(tls, struct lws, tls);
|
||||
SSL_SESSION *sess;
|
||||
|
||||
if (lws_tls_session_is_reused(wsi))
|
||||
return;
|
||||
|
||||
sess = SSL_get1_session(tls->ssl);
|
||||
if (!sess)
|
||||
return;
|
||||
|
||||
if (!SSL_SESSION_is_resumable(sess) || /* not worth caching, or... */
|
||||
!lws_tls_session_new_cb(tls->ssl, sess)) { /* ...cb didn't keep it */
|
||||
/*
|
||||
* For now the policy if no session message after the wait,
|
||||
* is just let it be. Typically the session info is sent
|
||||
* early.
|
||||
*/
|
||||
SSL_SESSION_free(sess);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
lws_tls_session_cache(struct lws_vhost *vh, uint32_t ttl)
|
||||
{
|
||||
|
@ -363,7 +416,7 @@ lws_tls_session_dump_load(struct lws_vhost *vh, const char *host, uint16_t port,
|
|||
{
|
||||
struct lws_tls_session_dump d;
|
||||
lws_tls_sco_t *ts;
|
||||
SSL_SESSION *sess;
|
||||
SSL_SESSION *sess = NULL; /* allow it to "bail" early */
|
||||
void *v;
|
||||
|
||||
if (vh->options & LWS_SERVER_OPTION_DISABLE_TLS_SESSION_CACHE)
|
||||
|
|
|
@ -449,6 +449,15 @@ lws_ssl_close(struct lws *wsi)
|
|||
SSL_set_info_callback(wsi->tls.ssl, NULL);
|
||||
#endif
|
||||
|
||||
#if defined(LWS_TLS_SYNTHESIZE_CB)
|
||||
lws_sul_cancel(&wsi->tls.sul_cb_synth);
|
||||
/*
|
||||
* ... check the session in case it did not live long enough to get
|
||||
* the scheduled callback to sample it
|
||||
*/
|
||||
lws_sess_cache_synth_cb(&wsi->tls.sul_cb_synth);
|
||||
#endif
|
||||
|
||||
n = SSL_get_fd(wsi->tls.ssl);
|
||||
if (!wsi->socket_is_permanently_unusable)
|
||||
SSL_shutdown(wsi->tls.ssl);
|
||||
|
|
|
@ -118,6 +118,11 @@ enum lws_tls_extant {
|
|||
|
||||
#if defined(LWS_WITH_TLS)
|
||||
|
||||
#if defined(LWS_WITH_TLS_SESSIONS) && defined(LWS_WITH_CLIENT) && \
|
||||
(defined(LWS_WITH_MBEDTLS) || defined(OPENSSL_IS_BORINGSSL))
|
||||
#define LWS_TLS_SYNTHESIZE_CB 1
|
||||
#endif
|
||||
|
||||
int
|
||||
lws_tls_restrict_borrow(struct lws_context *context);
|
||||
|
||||
|
|
|
@ -75,12 +75,15 @@ struct lws_vhost_tls {
|
|||
};
|
||||
|
||||
struct lws_lws_tls {
|
||||
lws_tls_conn *ssl;
|
||||
lws_tls_bio *client_bio;
|
||||
struct lws_dll2 dll_pending_tls;
|
||||
char err_helper[32];
|
||||
unsigned int use_ssl;
|
||||
unsigned int redirect_to_https:1;
|
||||
lws_tls_conn *ssl;
|
||||
lws_tls_bio *client_bio;
|
||||
#if defined(LWS_TLS_SYNTHESIZE_CB)
|
||||
lws_sorted_usec_list_t sul_cb_synth;
|
||||
#endif
|
||||
struct lws_dll2 dll_pending_tls;
|
||||
char err_helper[32];
|
||||
unsigned int use_ssl;
|
||||
unsigned int redirect_to_https:1;
|
||||
};
|
||||
|
||||
|
||||
|
@ -95,6 +98,10 @@ lws_ssl_pending(struct lws *wsi);
|
|||
int LWS_WARN_UNUSED_RESULT
|
||||
lws_server_socket_service_ssl(struct lws *new_wsi, lws_sockfd_type accept_fd,
|
||||
char is_pollin);
|
||||
|
||||
void
|
||||
lws_sess_cache_synth_cb(lws_sorted_usec_list_t *sul);
|
||||
|
||||
int
|
||||
lws_ssl_close(struct lws *wsi);
|
||||
void
|
||||
|
|
|
@ -51,9 +51,6 @@ if (requirements)
|
|||
|
||||
|
||||
add_test(NAME http-client-warmcat-h1 COMMAND lws-minimal-http-client --h1)
|
||||
set_tests_properties(${mytests} PROPERTIES
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client
|
||||
TIMEOUT 20)
|
||||
|
||||
if (has_fault_injection)
|
||||
|
||||
|
@ -138,7 +135,10 @@ if (requirements)
|
|||
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
set_tests_properties(${mytests} PROPERTIES
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/minimal-examples/http-client/minimal-http-client
|
||||
TIMEOUT 20)
|
||||
|
||||
if (DEFINED ENV{SAI_OVN})
|
||||
set_tests_properties(${mytests} PROPERTIES
|
||||
|
|
Loading…
Add table
Reference in a new issue