diff --git a/README.coding.md b/README.coding.md index c1c4a3fc..7cc55e21 100644 --- a/README.coding.md +++ b/README.coding.md @@ -321,6 +321,20 @@ if left `NULL`, then the "DEFAULT" set of ciphers are all possible to select. You can also set it to `"ALL"` to allow everything (including insecure ciphers). +@section sslcerts Passing your own cert information direct to SSL_CTX + +For most users it's enough to pass the SSL certificate and key information by +giving filepaths to the info.ssl_cert_filepath and info.ssl_private_key_filepath +members when creating the vhost. + +If you want to control that from your own code instead, you can do so by leaving +the related info members NULL, and setting the info.options flag +LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX at vhost creation time. That will create +the vhost SSL_CTX without any certificate, and allow you to use the callback +LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS to add your certificate to +the SSL_CTX directly. The vhost SSL_CTX * is in the user parameter in that +callback. + @section clientasync Async nature of client connections When you call `lws_client_connect_info(..)` and get a `wsi` back, it does not diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 9a08a05f..125db9e6 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -1865,6 +1865,13 @@ enum lws_context_options { * listen socket at a time. This is automatically selected if you * have multiple service threads. */ + LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX = (1 << 24), + /**< (VH) Force setting up the vhost SSL_CTX, even though the user + * code doesn't explicitly provide a cert in the info struct. It + * implies the user code is going to provide a cert at the + * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS callback, which + * provides the vhost SSL_CTX * in the user parameter. + */ /****** add new things just above ---^ ******/ }; diff --git a/lib/ssl-server.c b/lib/ssl-server.c index 2a768b2e..0e2d60c6 100644 --- a/lib/ssl-server.c +++ b/lib/ssl-server.c @@ -198,9 +198,22 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, vhost->use_ssl = 0; return 0; } + + /* + * If he is giving a cert filepath, take it as a sign he wants to use + * it on this vhost. User code can leave the cert filepath NULL and + * set the LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX option itself, in + * which case he's expected to set up the cert himself at + * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which + * provides the vhost SSL_CTX * in the user parameter. + */ + if (info->ssl_cert_filepath) + info->options |= LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; + if (info->port != CONTEXT_PORT_NO_LISTEN) { - vhost->use_ssl = info->ssl_cert_filepath != NULL; + vhost->use_ssl = lws_check_opt(info->options, + LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX); if (vhost->use_ssl && info->ssl_cipher_list) lwsl_notice(" SSL ciphers: '%s'\n", info->ssl_cipher_list); @@ -341,11 +354,19 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, SSL_CTX_clear_options(vhost->ssl_ctx, info->ssl_options_clear); #endif - lwsl_info(" SSL options 0x%lX\n", - SSL_CTX_get_options(vhost->ssl_ctx)); + lwsl_info(" SSL options 0x%lX\n", SSL_CTX_get_options(vhost->ssl_ctx)); - if (vhost->use_ssl) { - /* openssl init for server sockets */ + if (vhost->use_ssl && info->ssl_cert_filepath) { + /* + * The user code can choose to either pass the cert and + * key filepaths using the info members like this, or it can + * leave them NULL; force the vhost SSL_CTX init using the info + * options flag LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; and + * set up the cert himself using the user callback + * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which + * happened just above and has the vhost SSL_CTX * in the user + * parameter. + */ #if !defined(LWS_USE_MBEDTLS) /* set the local certificate from CertFile */ n = SSL_CTX_use_certificate_chain_file(vhost->ssl_ctx, @@ -430,6 +451,8 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, return 1; } #endif + } + if (vhost->use_ssl) { if (lws_context_ssl_init_ecdh(vhost)) return 1;