client fix reaction to tls failure

https://github.com/warmcat/libwebsockets/issues/508

Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
Andy Green 2016-05-03 07:26:10 +08:00
parent cae57ad98d
commit f1fd882d57
9 changed files with 77 additions and 27 deletions

View file

@ -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
---------------------------------------

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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,

View file

@ -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;

View file

@ -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 */

View file

@ -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:

View file

@ -17,7 +17,7 @@
* may be proprietary. So unlike the library itself, they are licensed
* Public Domain.
*/
#include "lws_config.h"
#include <stdio.h>
@ -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);