ssl migrate client pieces to ssl.c
Some ssl-specific code was still hiding out in client.c instead of going in ssl.c Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
parent
cd0c696a0d
commit
eefb13a0a7
3 changed files with 229 additions and 189 deletions
191
lib/client.c
191
lib/client.c
|
@ -148,125 +148,12 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi,
|
||||||
#ifdef LWS_OPENSSL_SUPPORT
|
#ifdef LWS_OPENSSL_SUPPORT
|
||||||
/* we can retry this... just cook the SSL BIO the first time */
|
/* we can retry this... just cook the SSL BIO the first time */
|
||||||
|
|
||||||
if (wsi->use_ssl && !wsi->ssl) {
|
if (wsi->use_ssl && !wsi->ssl)
|
||||||
#if defined(CYASSL_SNI_HOST_NAME) || defined(WOLFSSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
|
lws_ssl_client_bio_create(wsi);
|
||||||
const char *hostname = lws_hdr_simple_ptr(wsi,
|
|
||||||
_WSI_TOKEN_CLIENT_HOST);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wsi->ssl = SSL_new(wsi->vhost->ssl_client_ctx);
|
|
||||||
#ifndef USE_WOLFSSL
|
|
||||||
SSL_set_mode(wsi->ssl,
|
|
||||||
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* use server name indication (SNI), if supported,
|
|
||||||
* when establishing connection
|
|
||||||
*/
|
|
||||||
#ifdef USE_WOLFSSL
|
|
||||||
#ifdef USE_OLD_CYASSL
|
|
||||||
#ifdef CYASSL_SNI_HOST_NAME
|
|
||||||
CyaSSL_UseSNI(wsi->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));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
|
||||||
SSL_set_tlsext_host_name(wsi->ssl, hostname);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USE_WOLFSSL
|
|
||||||
/*
|
|
||||||
* wolfSSL/CyaSSL does certificate verification differently
|
|
||||||
* from OpenSSL.
|
|
||||||
* If we should ignore the certificate, we need to set
|
|
||||||
* this before SSL_new and SSL_connect is called.
|
|
||||||
* 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);
|
|
||||||
#else
|
|
||||||
if (wsi->use_ssl == 2)
|
|
||||||
wolfSSL_set_verify(wsi->ssl,
|
|
||||||
SSL_VERIFY_NONE, NULL);
|
|
||||||
#endif
|
|
||||||
#endif /* USE_WOLFSSL */
|
|
||||||
|
|
||||||
wsi->client_bio =
|
|
||||||
BIO_new_socket(wsi->sock, BIO_NOCLOSE);
|
|
||||||
SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
|
|
||||||
|
|
||||||
#ifdef USE_WOLFSSL
|
|
||||||
#ifdef USE_OLD_CYASSL
|
|
||||||
CyaSSL_set_using_nonblock(wsi->ssl, 1);
|
|
||||||
#else
|
|
||||||
wolfSSL_set_using_nonblock(wsi->ssl, 1);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SSL_set_ex_data(wsi->ssl,
|
|
||||||
openssl_websocket_private_data_index,
|
|
||||||
context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wsi->use_ssl) {
|
if (wsi->use_ssl) {
|
||||||
lws_latency_pre(context, wsi);
|
if (!lws_ssl_client_connect1(wsi))
|
||||||
n = SSL_connect(wsi->ssl);
|
|
||||||
lws_latency(context, wsi,
|
|
||||||
"SSL_connect LWSCM_WSCL_ISSUE_HANDSHAKE", n, n > 0);
|
|
||||||
|
|
||||||
if (n < 0) {
|
|
||||||
n = SSL_get_error(wsi->ssl, n);
|
|
||||||
|
|
||||||
if (n == SSL_ERROR_WANT_READ)
|
|
||||||
goto some_wait;
|
|
||||||
|
|
||||||
if (n == SSL_ERROR_WANT_WRITE) {
|
|
||||||
/*
|
|
||||||
* wants us to retry connect due to
|
|
||||||
* state of the underlying ssl layer...
|
|
||||||
* but since it may be stalled on
|
|
||||||
* blocked write, no incoming data may
|
|
||||||
* arrive to trigger the retry.
|
|
||||||
* Force (possibly many times if the SSL
|
|
||||||
* state persists in returning the
|
|
||||||
* condition code, but other sockets
|
|
||||||
* are getting serviced inbetweentimes)
|
|
||||||
* us to get called back when writable.
|
|
||||||
*/
|
|
||||||
lwsl_info("%s: WANT_WRITE... retrying\n", __func__);
|
|
||||||
lws_callback_on_writable(wsi);
|
|
||||||
some_wait:
|
|
||||||
wsi->mode = LWSCM_WSCL_WAITING_SSL;
|
|
||||||
|
|
||||||
return 0; /* no error */
|
|
||||||
}
|
|
||||||
n = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n <= 0) {
|
|
||||||
/*
|
|
||||||
* retry if new data comes until we
|
|
||||||
* run into the connection timeout or win
|
|
||||||
*/
|
|
||||||
n = ERR_get_error();
|
|
||||||
if (n != SSL_ERROR_NONE) {
|
|
||||||
lwsl_err("SSL connect error %lu: %s\n",
|
|
||||||
n, ERR_error_string(n, sb));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
wsi->ssl = NULL;
|
wsi->ssl = NULL;
|
||||||
|
|
||||||
|
@ -275,78 +162,8 @@ some_wait:
|
||||||
case LWSCM_WSCL_WAITING_SSL:
|
case LWSCM_WSCL_WAITING_SSL:
|
||||||
|
|
||||||
if (wsi->use_ssl) {
|
if (wsi->use_ssl) {
|
||||||
if (wsi->mode == LWSCM_WSCL_WAITING_SSL) {
|
if (!lws_ssl_client_connect2(wsi))
|
||||||
lws_latency_pre(context, wsi);
|
|
||||||
n = SSL_connect(wsi->ssl);
|
|
||||||
lws_latency(context, wsi,
|
|
||||||
"SSL_connect LWSCM_WSCL_WAITING_SSL",
|
|
||||||
n, n > 0);
|
|
||||||
|
|
||||||
if (n < 0) {
|
|
||||||
n = SSL_get_error(wsi->ssl, n);
|
|
||||||
|
|
||||||
if (n == SSL_ERROR_WANT_READ)
|
|
||||||
goto some_wait;
|
|
||||||
|
|
||||||
if (n == SSL_ERROR_WANT_WRITE) {
|
|
||||||
/*
|
|
||||||
* wants us to retry connect due to
|
|
||||||
* state of the underlying ssl layer...
|
|
||||||
* but since it may be stalled on
|
|
||||||
* blocked write, no incoming data may
|
|
||||||
* arrive to trigger the retry.
|
|
||||||
* Force (possibly many times if the SSL
|
|
||||||
* state persists in returning the
|
|
||||||
* condition code, but other sockets
|
|
||||||
* are getting serviced inbetweentimes)
|
|
||||||
* us to get called back when writable.
|
|
||||||
*/
|
|
||||||
lwsl_info("SSL_connect WANT_WRITE... retrying\n");
|
|
||||||
lws_callback_on_writable(wsi);
|
|
||||||
|
|
||||||
goto some_wait;
|
|
||||||
}
|
|
||||||
n = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n <= 0) {
|
|
||||||
/*
|
|
||||||
* retry if new data comes until we
|
|
||||||
* run into the connection timeout or win
|
|
||||||
*/
|
|
||||||
n = ERR_get_error();
|
|
||||||
if (n != SSL_ERROR_NONE) {
|
|
||||||
lwsl_err("SSL connect error %lu: %s\n",
|
|
||||||
n, ERR_error_string(n, sb));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef USE_WOLFSSL
|
|
||||||
/*
|
|
||||||
* See comment above about wolfSSL certificate
|
|
||||||
* verification
|
|
||||||
*/
|
|
||||||
lws_latency_pre(context, wsi);
|
|
||||||
n = SSL_get_verify_result(wsi->ssl);
|
|
||||||
lws_latency(context, wsi,
|
|
||||||
"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
|
|
||||||
n, n > 0);
|
|
||||||
|
|
||||||
if (n != X509_V_OK) {
|
|
||||||
if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
|
|
||||||
n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) {
|
|
||||||
lwsl_notice("accepting self-signed certificate\n");
|
|
||||||
} else {
|
|
||||||
lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s\n",
|
|
||||||
n, ERR_error_string(n, sb));
|
|
||||||
lws_close_free_wsi(wsi,
|
|
||||||
LWS_CLOSE_STATUS_NOSTATUS);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* USE_WOLFSSL */
|
|
||||||
} else
|
} else
|
||||||
wsi->ssl = NULL;
|
wsi->ssl = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1511,6 +1511,12 @@ LWS_EXTERN void
|
||||||
lws_ssl_context_destroy(struct lws_context *context);
|
lws_ssl_context_destroy(struct lws_context *context);
|
||||||
LWS_VISIBLE void
|
LWS_VISIBLE void
|
||||||
lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi);
|
lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi);
|
||||||
|
LWS_EXTERN int
|
||||||
|
lws_ssl_client_bio_create(struct lws *wsi);
|
||||||
|
LWS_EXTERN int
|
||||||
|
lws_ssl_client_connect1(struct lws *wsi);
|
||||||
|
LWS_EXTERN int
|
||||||
|
lws_ssl_client_connect2(struct lws *wsi);
|
||||||
#ifndef LWS_NO_SERVER
|
#ifndef LWS_NO_SERVER
|
||||||
LWS_EXTERN int
|
LWS_EXTERN int
|
||||||
lws_context_init_server_ssl(struct lws_context_creation_info *info,
|
lws_context_init_server_ssl(struct lws_context_creation_info *info,
|
||||||
|
|
217
lib/ssl.c
217
lib/ssl.c
|
@ -471,6 +471,223 @@ lws_decode_ssl_error(void)
|
||||||
|
|
||||||
#ifndef LWS_NO_CLIENT
|
#ifndef LWS_NO_CLIENT
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_ssl_client_bio_create(struct lws *wsi)
|
||||||
|
{
|
||||||
|
struct lws_context *context = wsi->context;
|
||||||
|
#if defined(CYASSL_SNI_HOST_NAME) || defined(WOLFSSL_SNI_HOST_NAME) || defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
|
||||||
|
const char *hostname = lws_hdr_simple_ptr(wsi, _WSI_TOKEN_CLIENT_HOST);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wsi->ssl = SSL_new(wsi->vhost->ssl_client_ctx);
|
||||||
|
#ifndef USE_WOLFSSL
|
||||||
|
SSL_set_mode(wsi->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* use server name indication (SNI), if supported,
|
||||||
|
* when establishing connection
|
||||||
|
*/
|
||||||
|
#ifdef USE_WOLFSSL
|
||||||
|
#ifdef USE_OLD_CYASSL
|
||||||
|
#ifdef CYASSL_SNI_HOST_NAME
|
||||||
|
CyaSSL_UseSNI(wsi->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));
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
|
||||||
|
SSL_set_tlsext_host_name(wsi->ssl, hostname);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_WOLFSSL
|
||||||
|
/*
|
||||||
|
* wolfSSL/CyaSSL does certificate verification differently
|
||||||
|
* from OpenSSL.
|
||||||
|
* If we should ignore the certificate, we need to set
|
||||||
|
* this before SSL_new and SSL_connect is called.
|
||||||
|
* 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);
|
||||||
|
#else
|
||||||
|
if (wsi->use_ssl == 2)
|
||||||
|
wolfSSL_set_verify(wsi->ssl, SSL_VERIFY_NONE, NULL);
|
||||||
|
#endif
|
||||||
|
#endif /* USE_WOLFSSL */
|
||||||
|
|
||||||
|
wsi->client_bio = BIO_new_socket(wsi->sock, BIO_NOCLOSE);
|
||||||
|
SSL_set_bio(wsi->ssl, wsi->client_bio, wsi->client_bio);
|
||||||
|
|
||||||
|
#ifdef USE_WOLFSSL
|
||||||
|
#ifdef USE_OLD_CYASSL
|
||||||
|
CyaSSL_set_using_nonblock(wsi->ssl, 1);
|
||||||
|
#else
|
||||||
|
wolfSSL_set_using_nonblock(wsi->ssl, 1);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
BIO_set_nbio(wsi->client_bio, 1); /* nonblocking */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SSL_set_ex_data(wsi->ssl, openssl_websocket_private_data_index,
|
||||||
|
context);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_ssl_client_connect1(struct lws *wsi)
|
||||||
|
{
|
||||||
|
struct lws_context *context = wsi->context;
|
||||||
|
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
|
||||||
|
char *p = (char *)&pt->serv_buf[0];
|
||||||
|
char *sb = p;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
lws_latency_pre(context, wsi);
|
||||||
|
n = SSL_connect(wsi->ssl);
|
||||||
|
lws_latency(context, wsi,
|
||||||
|
"SSL_connect LWSCM_WSCL_ISSUE_HANDSHAKE", n, n > 0);
|
||||||
|
|
||||||
|
if (n < 0) {
|
||||||
|
n = SSL_get_error(wsi->ssl, n);
|
||||||
|
|
||||||
|
if (n == SSL_ERROR_WANT_READ)
|
||||||
|
goto some_wait;
|
||||||
|
|
||||||
|
if (n == SSL_ERROR_WANT_WRITE) {
|
||||||
|
/*
|
||||||
|
* wants us to retry connect due to
|
||||||
|
* state of the underlying ssl layer...
|
||||||
|
* but since it may be stalled on
|
||||||
|
* blocked write, no incoming data may
|
||||||
|
* arrive to trigger the retry.
|
||||||
|
* Force (possibly many times if the SSL
|
||||||
|
* state persists in returning the
|
||||||
|
* condition code, but other sockets
|
||||||
|
* are getting serviced inbetweentimes)
|
||||||
|
* us to get called back when writable.
|
||||||
|
*/
|
||||||
|
lwsl_info("%s: WANT_WRITE... retrying\n", __func__);
|
||||||
|
lws_callback_on_writable(wsi);
|
||||||
|
some_wait:
|
||||||
|
wsi->mode = LWSCM_WSCL_WAITING_SSL;
|
||||||
|
|
||||||
|
return 0; /* no error */
|
||||||
|
}
|
||||||
|
n = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n <= 0) {
|
||||||
|
/*
|
||||||
|
* retry if new data comes until we
|
||||||
|
* run into the connection timeout or win
|
||||||
|
*/
|
||||||
|
n = ERR_get_error();
|
||||||
|
if (n != SSL_ERROR_NONE) {
|
||||||
|
lwsl_err("SSL connect error %lu: %s\n",
|
||||||
|
n, ERR_error_string(n, sb));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_ssl_client_connect2(struct lws *wsi)
|
||||||
|
{
|
||||||
|
struct lws_context *context = wsi->context;
|
||||||
|
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
|
||||||
|
char *p = (char *)&pt->serv_buf[0];
|
||||||
|
char *sb = p;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (wsi->mode == LWSCM_WSCL_WAITING_SSL) {
|
||||||
|
lws_latency_pre(context, wsi);
|
||||||
|
n = SSL_connect(wsi->ssl);
|
||||||
|
lws_latency(context, wsi,
|
||||||
|
"SSL_connect LWSCM_WSCL_WAITING_SSL", n, n > 0);
|
||||||
|
|
||||||
|
if (n < 0) {
|
||||||
|
n = SSL_get_error(wsi->ssl, n);
|
||||||
|
|
||||||
|
if (n == SSL_ERROR_WANT_READ) {
|
||||||
|
wsi->mode = LWSCM_WSCL_WAITING_SSL;
|
||||||
|
|
||||||
|
return 0; /* no error */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == SSL_ERROR_WANT_WRITE) {
|
||||||
|
/*
|
||||||
|
* wants us to retry connect due to
|
||||||
|
* state of the underlying ssl layer...
|
||||||
|
* but since it may be stalled on
|
||||||
|
* blocked write, no incoming data may
|
||||||
|
* arrive to trigger the retry.
|
||||||
|
* Force (possibly many times if the SSL
|
||||||
|
* state persists in returning the
|
||||||
|
* condition code, but other sockets
|
||||||
|
* are getting serviced inbetweentimes)
|
||||||
|
* us to get called back when writable.
|
||||||
|
*/
|
||||||
|
lwsl_info("SSL_connect WANT_WRITE... retrying\n");
|
||||||
|
lws_callback_on_writable(wsi);
|
||||||
|
|
||||||
|
wsi->mode = LWSCM_WSCL_WAITING_SSL;
|
||||||
|
|
||||||
|
return 0; /* no error */
|
||||||
|
}
|
||||||
|
n = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n <= 0) {
|
||||||
|
/*
|
||||||
|
* retry if new data comes until we
|
||||||
|
* run into the connection timeout or win
|
||||||
|
*/
|
||||||
|
n = ERR_get_error();
|
||||||
|
if (n != SSL_ERROR_NONE) {
|
||||||
|
lwsl_err("SSL connect error %lu: %s\n",
|
||||||
|
n, ERR_error_string(n, sb));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef USE_WOLFSSL
|
||||||
|
/*
|
||||||
|
* See comment above about wolfSSL certificate
|
||||||
|
* verification
|
||||||
|
*/
|
||||||
|
lws_latency_pre(context, wsi);
|
||||||
|
n = SSL_get_verify_result(wsi->ssl);
|
||||||
|
lws_latency(context, wsi,
|
||||||
|
"SSL_get_verify_result LWS_CONNMODE..HANDSHAKE",
|
||||||
|
n, n > 0);
|
||||||
|
|
||||||
|
if (n != X509_V_OK) {
|
||||||
|
if ((n == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT ||
|
||||||
|
n == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) && wsi->use_ssl == 2) {
|
||||||
|
lwsl_notice("accepting self-signed certificate\n");
|
||||||
|
} else {
|
||||||
|
lwsl_err("server's cert didn't look good, X509_V_ERR = %d: %s\n",
|
||||||
|
n, ERR_error_string(n, sb));
|
||||||
|
lws_close_free_wsi(wsi,
|
||||||
|
LWS_CLOSE_STATUS_NOSTATUS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* USE_WOLFSSL */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int lws_context_init_client_ssl(struct lws_context_creation_info *info,
|
int lws_context_init_client_ssl(struct lws_context_creation_info *info,
|
||||||
struct lws_vhost *vhost)
|
struct lws_vhost *vhost)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue