LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT to default to runtime ssl disable
authorAndy Green <andy@warmcat.com>
Wed, 23 Mar 2016 01:22:11 +0000 (09:22 +0800)
committerAndy Green <andy@warmcat.com>
Wed, 23 Mar 2016 01:22:11 +0000 (09:22 +0800)
https://github.com/warmcat/libwebsockets/issues/468

Adds lws_check_opt() to regularize multibit flag checking.

There's a new context creation flag LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT,
this is included automatically if you give any other SSL-related option flag.
If you give no SSL-related option flag, nor this one directly, then even
though SSL support may be compiled in, it is never initialized nor used for the
whole lifetime of the lws context.

Conversely in order to prepare the context to use SSL, even though, eg, you
are not listening on SSL but will use SSL client connections later, you can
give this flag explicitly to make sure SSL is initialized.

Signed-off-by: Andy Green <andy@warmcat.com>
13 files changed:
changelog
lib/client-parser.c
lib/context.c
lib/libev.c
lib/libuv.c
lib/libwebsockets.h
lib/private-libwebsockets.h
lib/server.c
lib/ssl.c
test-server/test-client.c
test-server/test-echo.c
test-server/test-fraggle.c
test-server/test-ping.c

index 101f57a..9c598a1 100644 (file)
--- a/changelog
+++ b/changelog
@@ -90,6 +90,16 @@ to your original connection.
 additional library, "libhubbub".  This allows lws to do html rewriting on the
 fly, adjusting proxied urls in a lightweight and fast way.
 
+11) There's a new context creation flag LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT,
+this is included automatically if you give any other SSL-related option flag.
+If you give no SSL-related option flag, nor this one directly, then even
+though SSL support may be compiled in, it is never initialized nor used for the
+whole lifetime of the lws context.
+
+Conversely in order to prepare the context to use SSL, even though, eg, you
+are not listening on SSL but will use SSL client connections later, you must
+give this flag explicitly to make sure SSL is initialized.
+
 
 User API additions
 ------------------
index 704a424..4036941 100644 (file)
@@ -64,9 +64,9 @@ int lws_client_rx_sm(struct lws *wsi, unsigned char c)
                        case LWSWSOPC_TEXT_FRAME:
                                wsi->u.ws.rsv_first_msg = (c & 0x70);
                                wsi->u.ws.continuation_possible = 1;
-                               wsi->u.ws.check_utf8 =
-                                       !!(wsi->context->options &
-                                          LWS_SERVER_OPTION_VALIDATE_UTF8);
+                               wsi->u.ws.check_utf8 = lws_check_opt(
+                                       wsi->context->options,
+                                       LWS_SERVER_OPTION_VALIDATE_UTF8);
                                wsi->u.ws.utf8 = 0;
                                break;
                        case LWSWSOPC_BINARY_FRAME:
@@ -344,7 +344,8 @@ spill:
                switch (wsi->u.ws.opcode) {
                case LWSWSOPC_CLOSE:
                        pp = (unsigned char *)&wsi->u.ws.rx_ubuf[LWS_PRE];
-                       if (wsi->context->options & LWS_SERVER_OPTION_VALIDATE_UTF8 &&
+                       if (lws_check_opt(wsi->context->options,
+                                         LWS_SERVER_OPTION_VALIDATE_UTF8) &&
                            wsi->u.ws.rx_ubuf_head > 2 &&
                            lws_check_utf8(&wsi->u.ws.utf8, pp + 2,
                                           wsi->u.ws.rx_ubuf_head - 2))
index 2574f22..884e123 100644 (file)
@@ -84,7 +84,7 @@ lws_create_context(struct lws_context_creation_info *info)
        lwsl_notice("Libwebsockets version: %s\n", library_version);
 #if LWS_POSIX
 #ifdef LWS_USE_IPV6
-       if (!(info->options & LWS_SERVER_OPTION_DISABLE_IPV6))
+       if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_IPV6))
                lwsl_notice("IPV6 compiled in and enabled\n");
        else
                lwsl_notice("IPV6 compiled in but disabled\n");
index 8b33ed7..1743093 100644 (file)
@@ -23,7 +23,7 @@
 
 void lws_feature_status_libev(struct lws_context_creation_info *info)
 {
-       if (info->options & LWS_SERVER_OPTION_LIBEV)
+       if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV))
                lwsl_notice("libev support compiled in and enabled\n");
        else
                lwsl_notice("libev support compiled in but disabled\n");
@@ -137,7 +137,7 @@ lws_libev_destroyloop(struct lws_context *context, int tsi)
 {
        struct lws_context_per_thread *pt = &context->pt[tsi];
 
-       if (!(context->options & LWS_SERVER_OPTION_LIBEV))
+       if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEV))
                return;
 
        if (!pt->io_loop_ev)
index abea756..92d44ee 100644 (file)
@@ -24,7 +24,7 @@
 void
 lws_feature_status_libuv(struct lws_context_creation_info *info)
 {
-       if (info->options & LWS_SERVER_OPTION_LIBUV)
+       if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV))
                lwsl_notice("libuv support compiled in and enabled\n");
        else
                lwsl_notice("libuv support compiled in but disabled\n");
@@ -160,7 +160,7 @@ lws_libuv_destroyloop(struct lws_context *context, int tsi)
        struct lws_context_per_thread *pt = &context->pt[tsi];
        int m;
 
-       if (!(context->options & LWS_SERVER_OPTION_LIBUV))
+       if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
                return;
 
        if (!pt->io_loop_uv)
index a43d773..c6359ed 100644 (file)
@@ -290,22 +290,29 @@ struct lws;
  * add it at where specified so existing users are unaffected.
  */
 enum lws_context_options {
-       LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT     = (1 << 1),
+       LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT     = (1 << 1) |
+                                                                 (1 << 12),
        LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME            = (1 << 2),
-       LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT             = (1 << 3),
+       LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT             = (1 << 3) |
+                                                                 (1 << 12),
        LWS_SERVER_OPTION_LIBEV                                 = (1 << 4),
        LWS_SERVER_OPTION_DISABLE_IPV6                          = (1 << 5),
        LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS                   = (1 << 6),
        LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED                = (1 << 7),
        LWS_SERVER_OPTION_VALIDATE_UTF8                         = (1 << 8),
-       LWS_SERVER_OPTION_SSL_ECDH                              = (1 << 9),
+       LWS_SERVER_OPTION_SSL_ECDH                              = (1 << 9) |
+                                                                 (1 << 12),
        LWS_SERVER_OPTION_LIBUV                                 = (1 << 10),
        LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS                = (1 << 11) |
-                                                                 (1 << 3),
+                                                                 (1 << 3) |
+                                                                 (1 << 12),
+       LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT                    = (1 << 12),
 
        /****** add new things just above ---^ ******/
 };
 
+#define lws_check_opt(c, f) (((c) & (f)) == (f))
+
 /*
  * NOTE: These public enums are part of the abi.  If you want to add one,
  * add it at where specified so existing users are unaffected.
index 3021b12..58e8b70 100644 (file)
@@ -724,7 +724,7 @@ LWS_EXTERN void
 lws_libev_destroyloop(struct lws_context *context, int tsi);
 LWS_EXTERN void
 lws_libev_run(const struct lws_context *context, int tsi);
-#define LWS_LIBEV_ENABLED(context) (context->options & LWS_SERVER_OPTION_LIBEV)
+#define LWS_LIBEV_ENABLED(context) lws_check_opt(context->options, LWS_SERVER_OPTION_LIBEV)
 LWS_EXTERN void lws_feature_status_libev(struct lws_context_creation_info *info);
 #else
 #define lws_libev_accept(_a, _b) ((void) 0)
@@ -752,7 +752,7 @@ LWS_EXTERN void
 lws_libuv_run(const struct lws_context *context, int tsi);
 LWS_EXTERN void
 lws_libuv_destroyloop(struct lws_context *context, int tsi);
-#define LWS_LIBUV_ENABLED(context) (context->options & LWS_SERVER_OPTION_LIBUV)
+#define LWS_LIBUV_ENABLED(context) lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)
 LWS_EXTERN void lws_feature_status_libuv(struct lws_context_creation_info *info);
 #else
 #define lws_libuv_accept(_a, _b) ((void) 0)
@@ -772,7 +772,7 @@ LWS_EXTERN void lws_feature_status_libuv(struct lws_context_creation_info *info)
 
 #ifdef LWS_USE_IPV6
 #define LWS_IPV6_ENABLED(context) \
-       (!(context->options & LWS_SERVER_OPTION_DISABLE_IPV6))
+       (!lws_check_opt(context->options, LWS_SERVER_OPTION_DISABLE_IPV6))
 #else
 #define LWS_IPV6_ENABLED(context) (0)
 #endif
index 5a19a16..48cbc31 100644 (file)
@@ -1287,7 +1287,7 @@ LWS_VISIBLE void
 lws_server_get_canonical_hostname(struct lws_context *context,
                                  struct lws_context_creation_info *info)
 {
-       if (info->options & LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME)
+       if (lws_check_opt(info->options, LWS_SERVER_OPTION_SKIP_SERVER_CANONICAL_NAME))
                return;
 #if LWS_POSIX
        /* find canonical hostname */
index c817a9a..c21271d 100644 (file)
--- a/lib/ssl.c
+++ b/lib/ssl.c
@@ -92,12 +92,12 @@ static int
 lws_context_ssl_init_ecdh(struct lws_context *context)
 {
 #ifdef LWS_SSL_SERVER_WITH_ECDH_CERT
-       int KeyType;
        EC_KEY *EC_key = NULL;
-       X509 *x;
        EVP_PKEY *pkey;
+       int KeyType;
+       X509 *x;
 
-       if (!(context->options & LWS_SERVER_OPTION_SSL_ECDH))
+       if (!lws_check_opt(context->options, LWS_SERVER_OPTION_SSL_ECDH))
                return 0;
 
        lwsl_notice(" Using ECDH certificate support\n");
@@ -179,20 +179,25 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info,
        int error;
        int n;
 
-       if (info->port != CONTEXT_PORT_NO_LISTEN) {
-
-               context->use_ssl = info->ssl_cert_filepath != NULL;
-
 #ifdef USE_WOLFSSL
 #ifdef USE_OLD_CYASSL
-               lwsl_notice(" Compiled with CyaSSL support\n");
+       lwsl_notice(" Compiled with CyaSSL support\n");
 #else
-               lwsl_notice(" Compiled with wolfSSL support\n");
+       lwsl_notice(" Compiled with wolfSSL support\n");
 #endif
 #else
-               lwsl_notice(" Compiled with OpenSSL support\n");
+       lwsl_notice(" Compiled with OpenSSL support\n");
 #endif
 
+       if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
+               lwsl_notice(" SSL disabled: no LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT\n");
+               return 0;
+       }
+
+       if (info->port != CONTEXT_PORT_NO_LISTEN) {
+
+               context->use_ssl = info->ssl_cert_filepath != NULL;
+
                if (info->ssl_cipher_list)
                        lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list);
 
@@ -258,10 +263,10 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info,
 
        /* as a server, are we requiring clients to identify themselves? */
 
-       if (info->options & LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT) {
+       if (lws_check_opt(info->options, LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT)) {
                int verify_options = SSL_VERIFY_PEER;
 
-               if (!(info->options & LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
+               if (!lws_check_opt(info->options, LWS_SERVER_OPTION_PEER_CERT_NOT_REQUIRED))
                        verify_options |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
 
                SSL_CTX_set_session_id_context(context->ssl_ctx,
@@ -291,7 +296,7 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info,
                        LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS,
                                               context->ssl_ctx, NULL, 0);
 
-       if (info->options & LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT)
+       if (lws_check_opt(info->options, LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT))
                /* Normally SSL listener rejects non-ssl, optionally allow */
                context->allow_non_ssl_on_ssl_port = 1;
 
@@ -357,6 +362,9 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info,
 LWS_VISIBLE void
 lws_ssl_destroy(struct lws_context *context)
 {
+       if (!lws_check_opt(context->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
+               return;
+
        if (context->ssl_ctx)
                SSL_CTX_free(context->ssl_ctx);
        if (!context->user_supplied_ssl_ctx && context->ssl_client_ctx)
@@ -394,6 +402,9 @@ int lws_context_init_client_ssl(struct lws_context_creation_info *info,
        SSL_METHOD *method;
        struct lws wsi;
 
+       if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
+               return 0;
+
        if (info->provided_client_ssl_ctx) {
                /* use the provided OpenSSL context if given one */
                context->ssl_client_ctx = info->provided_client_ssl_ctx;
@@ -441,7 +452,7 @@ int lws_context_init_client_ssl(struct lws_context_creation_info *info,
                                                info->ssl_cipher_list);
 
 #ifdef LWS_SSL_CLIENT_USE_OS_CA_CERTS
-       if (!(info->options & LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
+       if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
                /* loads OS default CA certs */
                SSL_CTX_set_default_verify_paths(context->ssl_client_ctx);
 #endif
@@ -757,8 +768,8 @@ lws_server_socket_service_ssl(struct lws *wsi, lws_sockfd_type accept_fd)
                                SSL_shutdown(wsi->ssl);
                                SSL_free(wsi->ssl);
                                wsi->ssl = NULL;
-                               if (context->options &
-                                   LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS)
+                               if (lws_check_opt(context->options,
+                                   LWS_SERVER_OPTION_REDIRECT_HTTP_TO_HTTPS))
                                        wsi->redirect_to_https = 1;
                                goto accepted;
                        }
index 93c92aa..b35260d 100644 (file)
@@ -362,6 +362,9 @@ int main(int argc, char **argv)
        info.gid = -1;
        info.uid = -1;
 
+       if (use_ssl)
+               info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+
        context = lws_create_context(&info);
        if (context == NULL) {
                fprintf(stderr, "Creating libwebsocket context failed\n");
index 6c1729e..75390f6 100644 (file)
@@ -438,6 +438,9 @@ int main(int argc, char **argv)
        info.gid = -1;
        info.uid = -1;
        info.options = opts | LWS_SERVER_OPTION_VALIDATE_UTF8;
+
+       if (use_ssl)
+               info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
 #ifndef LWS_NO_EXTENSIONS
        info.extensions = exts;
 #endif
index 51b5903..2137e7b 100644 (file)
@@ -336,6 +336,9 @@ int main(int argc, char **argv)
        info.uid = -1;
        info.options = opts;
 
+       if (use_ssl)
+               info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+
        context = lws_create_context(&info);
        if (context == NULL) {
                fprintf(stderr, "libwebsocket init failed\n");
index ff2d8e3..640bc9d 100644 (file)
@@ -441,6 +441,9 @@ int main(int argc, char **argv)
        info.gid = -1;
        info.uid = -1;
 
+       if (use_ssl)
+               info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+
        context = lws_create_context(&info);
        if (context == NULL) {
                fprintf(stderr, "Creating libwebsocket context failed\n");