LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT to default to runtime ssl disable

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>
This commit is contained in:
Andy Green 2016-03-23 09:22:11 +08:00
parent f107e4bb85
commit c6fd360160
13 changed files with 77 additions and 36 deletions

View file

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

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

View 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");

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

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

View 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.

View 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

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

View file

@ -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;
#ifdef USE_WOLFSSL
#ifdef USE_OLD_CYASSL
lwsl_notice(" Compiled with CyaSSL support\n");
#else
lwsl_notice(" Compiled with wolfSSL support\n");
#endif
#else
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;
#ifdef USE_WOLFSSL
#ifdef USE_OLD_CYASSL
lwsl_notice(" Compiled with CyaSSL support\n");
#else
lwsl_notice(" Compiled with wolfSSL support\n");
#endif
#else
lwsl_notice(" Compiled with OpenSSL support\n");
#endif
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;
}

View 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");

View 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

View 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");

View 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");