diff --git a/lib/libwebsockets.h b/lib/libwebsockets.h index 81d4ca9b..9ed8a11f 100644 --- a/lib/libwebsockets.h +++ b/lib/libwebsockets.h @@ -213,6 +213,8 @@ enum libwebsocket_callback_reasons { LWS_CALLBACK_LOCK_POLL, LWS_CALLBACK_UNLOCK_POLL, + LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, + LWS_CALLBACK_USER = 1000, /* user code can use any including / above */ }; @@ -699,6 +701,15 @@ struct libwebsocket_extension; * verify the validity of certificates returned by clients. @user * is the server's OpenSSL SSL_CTX* * + * LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY: if configured for + * including OpenSSL support but no private key file has been specified + * (ssl_private_key_filepath is NULL), this callback is called to + * allow the user to set the private key directly via libopenssl + * and perform further operations if required; this might be useful + * in situations where the private key is not directly accessible by + * the OS, for example if it is stored on a smartcard + * @user is the server's OpenSSL SSL_CTX* + * * LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: if the * libwebsockets context was created with the option * LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT, then this @@ -1001,8 +1012,10 @@ struct libwebsocket_extension { * @ssl_cert_filepath: If libwebsockets was compiled to use ssl, and you want * to listen using SSL, set to the filepath to fetch the * server cert from, otherwise NULL for unencrypted - * @ssl_private_key_filepath: filepath to private key if wanting SSL mode, - * else ignored + * @ssl_private_key_filepath: filepath to private key if wanting SSL mode; + * if this is set to NULL but sll_cert_filepath is set, the + * OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY callback is called to allow + * setting of the private key directly via openSSL library calls * @ssl_ca_filepath: CA certificate filepath or NULL * @ssl_cipher_list: List of valid ciphers to use (eg, * "RC4-MD5:RC4-SHA:AES128-SHA:AES256-SHA:HIGH:!DSS:!aNULL" diff --git a/lib/ssl.c b/lib/ssl.c index f9e88483..cfee6de7 100644 --- a/lib/ssl.c +++ b/lib/ssl.c @@ -84,8 +84,8 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, if (info->port != CONTEXT_PORT_NO_LISTEN) { - context->use_ssl = info->ssl_cert_filepath != NULL && - info->ssl_private_key_filepath != NULL; + context->use_ssl = info->ssl_cert_filepath != NULL; + #ifdef USE_CYASSL lwsl_notice(" Compiled with CYASSL support\n"); #else @@ -190,18 +190,29 @@ lws_context_init_server_ssl(struct lws_context_creation_info *info, return 1; } lws_ssl_bind_passphrase(context->ssl_ctx, info); - /* set the private key from KeyFile */ - if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx, - info->ssl_private_key_filepath, + + if (info->ssl_private_key_filepath != NULL) { + /* set the private key from KeyFile */ + if (SSL_CTX_use_PrivateKey_file(context->ssl_ctx, + info->ssl_private_key_filepath, SSL_FILETYPE_PEM) != 1) { - error = ERR_get_error(); - lwsl_err("ssl problem getting key '%s' %lu: %s\n", - info->ssl_private_key_filepath, - error, - ERR_error_string(error, - (char *)context->service_buffer)); - return 1; + error = ERR_get_error(); + lwsl_err("ssl problem getting key '%s' %lu: %s\n", + info->ssl_private_key_filepath, + error, + ERR_error_string(error, + (char *)context->service_buffer)); + return 1; + } } + else { + if (context->protocols[0].callback(context, NULL, + LWS_CALLBACK_OPENSSL_CONTEXT_REQUIRES_PRIVATE_KEY, + context->ssl_ctx, NULL, 0)) + lwsl_err("ssl private key not set\n"); + return 1; + } + /* verify private key */ if (!SSL_CTX_check_private_key(context->ssl_ctx)) { lwsl_err("Private SSL key doesn't match cert\n");