client fix reaction to tls failure
authorAndy Green <andy@warmcat.com>
Mon, 2 May 2016 23:26:10 +0000 (07:26 +0800)
committerAndy Green <andy@warmcat.com>
Mon, 2 May 2016 23:26:10 +0000 (07:26 +0800)
https://github.com/warmcat/libwebsockets/issues/508

Signed-off-by: Andy Green <andy@warmcat.com>
README.test-apps.md
lib/client-handshake.c
lib/client.c
lib/libwebsockets.c
lib/private-libwebsockets.h
lib/service.c
lib/ssl-client.c
lib/ssl.c
test-server/test-client.c

index 221adc7a66555dd7a36e654bf1b8eb53a14f807e..3b76052a80dada5763f342c41d08db035a1fa098 100644 (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
 ---------------------------------------
index c7e220eed7e77122d9c80cd0373bd250c339e325..0135df50675e5d662e286a22a673b53f4531c056 100644 (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;
index 155794260b7cfe6047f9b12d9475a95ad90bc35d..63f9f8084319e37e5b5bce37e72d4de6222a5093 100644 (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;
 
index b34430bf61459837b395019a27f848d3afbf1348..60da78efda3c5adb2641abc17196a15e3e88a2cc 100644 (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)
index df2bbf647921ba81baa599dcd6ef14e1fab9153d..7e131a62d200aadeea3182a9c1203fc51b876c13 100644 (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,
index a838c7c41af2f04a9a591f5a5e80c9f61b5d412b..fcafd99d7a318d1d293a0eca1888c01122a40b76 100644 (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;
index 14fc99c048abe437b03162a4ce7e5a897114af88..10fe444a3cd4f745d508668f61508b40704ed19a 100644 (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 */
index 2be1a0a272467f77ba616480491ae3fea6e32ce9..0a028bb13aa7afbb69a8e28098d4daeb101f73e0 100644 (file)
--- 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:
index 7d667611460e5d93caa06143076f8ddb26d867b3..688c513e21492a28a42d1f2050042cbe60f55bdb 100644 (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);