diff --git a/README.test-apps.md b/README.test-apps.md index 221adc7a..3b76052a 100644 --- a/README.test-apps.md +++ b/README.test-apps.md @@ -78,6 +78,16 @@ same time as drawing random circles in the mirror protocol; if you connect to the test server using a browser at the same time you will be able to see the circles being drawn. +The test client supports SSL too, use + +```bash +$ libwebsockets-test-client localhost --ssl -s +``` + +the -s tells it to accept the default selfsigned cert from the server, +otherwise it will strictly fail the connection if there is no CA cert to +validate the server's certificate. + Choosing between test server variations --------------------------------------- diff --git a/lib/client-handshake.c b/lib/client-handshake.c index c7e220ee..0135df50 100644 --- a/lib/client-handshake.c +++ b/lib/client-handshake.c @@ -112,8 +112,10 @@ lws_client_connect_2(struct lws *wsi) ai.ai_socktype = SOCK_STREAM; ai.ai_flags = AI_CANONNAME; - if (getaddrinfo(ads, NULL, &ai, &result)) + if (getaddrinfo(ads, NULL, &ai, &result)) { + lwsl_err("getaddrinfo failed\n"); goto oom4; + } res = result; while (!p && res) { @@ -127,6 +129,7 @@ lws_client_connect_2(struct lws *wsi) } if (!p) { + lwsl_err("Couldn't identify address\n"); freeaddrinfo(result); goto oom4; } @@ -170,6 +173,9 @@ lws_client_connect_2(struct lws *wsi) * handling as oom4 does. We have to run the whole close flow. */ + if (!wsi->protocol) + wsi->protocol = &wsi->vhost->protocols[0]; + wsi->protocol->callback(wsi, LWS_CALLBACK_WSI_CREATE, wsi->user_space, NULL, 0); @@ -278,6 +284,11 @@ lws_client_connect_2(struct lws *wsi) oom4: /* we're closing, losing some rx is OK */ wsi->u.hdr.ah->rxpos = wsi->u.hdr.ah->rxlen; + //lwsl_err("%d\n", wsi->mode); + if (wsi->mode == LWSCM_HTTP_CLIENT) + wsi->vhost->protocols[0].callback(wsi, + LWS_CALLBACK_CLIENT_CONNECTION_ERROR, + wsi->user_space, NULL, 0); /* take care that we might be inserted in fds already */ if (wsi->position_in_fds_table != -1) goto failed; diff --git a/lib/client.c b/lib/client.c index 15579426..63f9f808 100644 --- a/lib/client.c +++ b/lib/client.c @@ -152,8 +152,11 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi, lws_ssl_client_bio_create(wsi); if (wsi->use_ssl) { - if (!lws_ssl_client_connect1(wsi)) + n = lws_ssl_client_connect1(wsi); + if (!n) return 0; + if (n < 0) + goto bail3; } else wsi->ssl = NULL; @@ -162,8 +165,11 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi, case LWSCM_WSCL_WAITING_SSL: if (wsi->use_ssl) { - if (!lws_ssl_client_connect2(wsi)) + n = lws_ssl_client_connect2(wsi); + if (!n) return 0; + if (n < 0) + goto bail3; } else wsi->ssl = NULL; #endif @@ -279,6 +285,9 @@ lws_client_socket_service(struct lws_context *context, struct lws *wsi, bail3: lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n"); + wsi->vhost->protocols[0].callback(wsi, + LWS_CALLBACK_CLIENT_CONNECTION_ERROR, + wsi->user_space, NULL, 0); lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return -1; diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c index b34430bf..60da78ef 100644 --- a/lib/libwebsockets.c +++ b/lib/libwebsockets.c @@ -380,12 +380,13 @@ just_kill_connection: * the actual close. */ if (wsi->state != LWSS_SHUTDOWN && + wsi->state != LWSS_CLIENT_UNCONNECTED && reason != LWS_CLOSE_STATUS_NOSTATUS_CONTEXT_DESTROY && !wsi->socket_is_permanently_unusable) { - lwsl_info("%s: shutting down connection: %p (sock %d)\n", __func__, wsi, wsi->sock); + lwsl_info("%s: shutting down connection: %p (sock %d, state %d)\n", __func__, wsi, wsi->sock, wsi->state); n = shutdown(wsi->sock, SHUT_WR); if (n) - lwsl_debug("closing: shutdown ret %d\n", LWS_ERRNO); + lwsl_debug("closing: shutdown (state %d) ret %d\n", wsi->state, LWS_ERRNO); // This causes problems with disconnection when the events are half closing connection // FD_READ | FD_CLOSE (33) diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index df2bbf64..7e131a62 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -1583,6 +1583,8 @@ LWS_EXTERN int lws_ssl_client_connect1(struct lws *wsi); LWS_EXTERN int lws_ssl_client_connect2(struct lws *wsi); +LWS_EXTERN void +lws_ssl_elaborate_error(void); #ifndef LWS_NO_SERVER LWS_EXTERN int lws_context_init_server_ssl(struct lws_context_creation_info *info, diff --git a/lib/service.c b/lib/service.c index a838c7c4..fcafd99d 100644 --- a/lib/service.c +++ b/lib/service.c @@ -343,6 +343,11 @@ lws_service_timeout_check(struct lws *wsi, unsigned int sec) * cleanup like flush partials. */ wsi->socket_is_permanently_unusable = 1; + if (wsi->mode == LWSCM_WSCL_WAITING_SSL) + wsi->vhost->protocols[0].callback(wsi, + LWS_CALLBACK_CLIENT_CONNECTION_ERROR, + wsi->user_space, NULL, 0); + lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); return 1; diff --git a/lib/ssl-client.c b/lib/ssl-client.c index 14fc99c0..10fe444a 100644 --- a/lib/ssl-client.c +++ b/lib/ssl-client.c @@ -167,7 +167,7 @@ some_wait: char *sb = p; lwsl_err("SSL connect error %lu: %s\n", n, ERR_error_string(n, sb)); - return 0; + return -1; } #endif #endif @@ -248,7 +248,7 @@ lws_ssl_client_connect2(struct lws *wsi) if (n != SSL_ERROR_NONE) { lwsl_err("SSL connect error %lu: %s\n", n, ERR_error_string(n, sb)); - return 0; + return -1; } #endif #endif @@ -277,9 +277,9 @@ lws_ssl_client_connect2(struct lws *wsi) } 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; + lws_ssl_elaborate_error(); + lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS); + return -1; } } #endif /* USE_WOLFSSL */ diff --git a/lib/ssl.c b/lib/ssl.c index 2be1a0a2..0a028bb1 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -70,6 +70,26 @@ int lws_ssl_get_error(struct lws *wsi, int n) #endif } +void +lws_ssl_elaborate_error(void) +{ +#if defined(LWS_USE_POLARSSL) +#else +#if defined(LWS_USE_MBEDTLS) +#else + + char buf[256]; + u_long err; + + while ((err = ERR_get_error()) != 0) { + ERR_error_string_n(err, buf, sizeof(buf)); + lwsl_err("*** %s\n", buf); + } +#endif +#endif +} + + #if defined(LWS_USE_POLARSSL) #else #if defined(LWS_USE_MBEDTLS) @@ -612,21 +632,7 @@ go_again: lwsl_err("SSL_accept failed skt %u: %s\n", wsi->sock, ERR_error_string(m, NULL)); -#if defined(LWS_USE_POLARSSL) -#else -#if defined(LWS_USE_MBEDTLS) -#else - { - char buf[256]; - u_long err; - - while ((err = ERR_get_error()) != 0) { - ERR_error_string_n(err, buf, sizeof(buf)); - lwsl_err("*** %s\n", buf); - } - } -#endif -#endif + lws_ssl_elaborate_error(); goto fail; accepted: diff --git a/test-server/test-client.c b/test-server/test-client.c index 7d667611..688c513e 100644 --- a/test-server/test-client.c +++ b/test-server/test-client.c @@ -17,7 +17,7 @@ * may be proprietary. So unlike the library itself, they are licensed * Public Domain. */ - + #include "lws_config.h" #include @@ -433,7 +433,8 @@ int main(int argc, char **argv) if (!strcmp(prot, "http") || !strcmp(prot, "ws")) use_ssl = 0; if (!strcmp(prot, "https") || !strcmp(prot, "wss")) - use_ssl = 1; + if (!use_ssl) + use_ssl = 1; /* * create the websockets context. This tracks open connections and @@ -476,6 +477,11 @@ int main(int argc, char **argv) #endif #endif #endif + + if (use_ssl == 1) + lwsl_notice(" Cert must validate correctly (use -s to allow selfsigned)\n"); + else + lwsl_notice(" Selfsigned certs allowed\n"); } context = lws_create_context(&info);