SET(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LWS_INSTALL_LIB_DIR}${LIB_SUFFIX}")
include(CheckFunctionExists)
+include(CheckSymbolExists)
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckLibraryExists)
set(realloc rpl_realloc)
endif()
-# Generate the lws_config.h that includes all the public compilation settings.
-configure_file(
- "${PROJECT_SOURCE_DIR}/lws_config.h.in"
- "${PROJECT_BINARY_DIR}/lws_config.h")
-
-# Generate the lws_config.h that includes all the private compilation settings.
-configure_file(
- "${PROJECT_SOURCE_DIR}/lws_config_private.h.in"
- "${PROJECT_BINARY_DIR}/lws_config_private.h")
if (MSVC)
# Turn off stupid microsoft security warnings.
target_link_libraries(${lib} ${LIB_LIST})
endforeach()
+set (temp ${CMAKE_REQUIRED_LIBRARIES})
+set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST})
+CHECK_FUNCTION_EXISTS(SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param)
+set(CMAKE_REQUIRED_LIBRARIES ${temp})
+# Generate the lws_config.h that includes all the public compilation settings.
+configure_file(
+ "${PROJECT_SOURCE_DIR}/lws_config.h.in"
+ "${PROJECT_BINARY_DIR}/lws_config.h")
+
+# Generate the lws_config.h that includes all the private compilation settings.
+configure_file(
+ "${PROJECT_SOURCE_DIR}/lws_config_private.h.in"
+ "${PROJECT_BINARY_DIR}/lws_config_private.h")
+
+
+
#
# Test applications
#
message(" LWS_MAX_SMP = ${LWS_MAX_SMP}")
message(" LWS_WITH_CGI = ${LWS_WITH_CGI}")
message(" LWS_HAVE_OPENSSL_ECDH_H = ${LWS_HAVE_OPENSSL_ECDH_H}")
+message(" LWS_HAVE_SSL_CTX_set1_param = ${LWS_HAVE_SSL_CTX_set1_param}")
message(" LWS_WITH_HTTP_PROXY = ${LWS_WITH_HTTP_PROXY}")
message(" LIBHUBBUB_LIBRARIES = ${LIBHUBBUB_LIBRARIES}")
message(" PLUGINS = ${PLUGINS_LIST}")
/* SSL server using ECDH certificate */
#cmakedefine LWS_SSL_SERVER_WITH_ECDH_CERT
+#cmakedefine LWS_HAVE_SSL_CTX_set1_param
/* CGI apis */
#cmakedefine LWS_WITH_CGI
#include "../lib/libwebsockets.h"
+#ifdef LWS_OPENSSL_SUPPORT
+#include <openssl/err.h>
+#endif
+
static int deny_deflate, deny_mux, longlived, mirror_lifetime;
static struct lws *wsi_dumb, *wsi_mirror;
static volatile int force_exit;
static unsigned int opts;
+#if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
+static char crl_path[1024] = "";
+#endif
/*
* This demo shows how to connect multiple websockets simultaneously to a
force_exit = 1;
break;
+#if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
+ case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
+ if (crl_path[0]) {
+ /* Enable CRL checking of the server certificate */
+ X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
+ X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
+ SSL_CTX_set1_param((SSL_CTX*)user, param);
+ X509_STORE *store = SSL_CTX_get_cert_store((SSL_CTX*)user);
+ X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ int n = X509_load_cert_crl_file(lookup, crl_path, X509_FILETYPE_PEM);
+ X509_VERIFY_PARAM_free(param);
+ if (n != 1) {
+ char errbuf[256];
+ n = ERR_get_error();
+ lwsl_err("LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: SSL error: %s (%d)\n", ERR_error_string(n, errbuf), n);
+ return 1;
+ }
+ }
+ break;
+#endif
+
default:
break;
}
{ "undeflated", no_argument, NULL, 'u' },
{ "nomux", no_argument, NULL, 'n' },
{ "longlived", no_argument, NULL, 'l' },
+ { "ssl-cert", required_argument, NULL, 'C' },
+ { "ssl-key", required_argument, NULL, 'K' },
+ { "ssl-ca", required_argument, NULL, 'A' },
+#if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
+ { "ssl-crl", required_argument, NULL, 'R' },
+#endif
{ NULL, 0, 0, 0 }
};
struct lws_context *context;
const char *prot, *p;
char path[300];
+ char cert_path[1024] = "";
+ char key_path[1024] = "";
+ char ca_path[1024] = "";
memset(&info, 0, sizeof info);
goto usage;
while (n >= 0) {
- n = getopt_long(argc, argv, "nuv:hsp:d:l", options, NULL);
+ n = getopt_long(argc, argv, "nuv:hsp:d:lC:K:A:", options, NULL);
if (n < 0)
continue;
switch (n) {
case 'n':
deny_mux = 1;
break;
+ case 'C':
+ strncpy(cert_path, optarg, sizeof cert_path);
+ break;
+ case 'K':
+ strncpy(key_path, optarg, sizeof key_path);
+ break;
+ case 'A':
+ strncpy(ca_path, optarg, sizeof ca_path);
+ break;
+#if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
+ case 'R':
+ strncpy(crl_path, optarg, sizeof crl_path);
+ break;
+#endif
case 'h':
goto usage;
}
info.gid = -1;
info.uid = -1;
- if (use_ssl)
+ if (use_ssl) {
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
+ /*
+ * If the server wants us to present a valid SSL client certificate
+ * then we can set it up here.
+ */
+
+ if (cert_path[0])
+ info.ssl_cert_filepath = cert_path;
+ if (key_path[0])
+ info.ssl_private_key_filepath = key_path;
+
+ /*
+ * A CA cert and CRL can be used to validate the cert send by the server
+ */
+ if (ca_path[0])
+ info.ssl_ca_filepath = ca_path;
+#if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
+ else if (crl_path[0])
+ lwsl_notice("WARNING, providing a CRL requires a CA cert!\n");
+#endif
+ }
+
context = lws_create_context(&info);
if (context == NULL) {
fprintf(stderr, "Creating libwebsocket context failed\n");
* using this protocol, including the sender
*/
+#ifdef LWS_OPENSSL_SUPPORT
+#include <openssl/err.h>
+#endif
+
+#if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
+/* location of the certificate revocation list */
+char crl_path[1024] = "";
+#endif
+
extern int debug_level;
enum demo_protocols {
break;
+#if defined(LWS_OPENSSL_SUPPORT)
+ case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
+ /* Verify the client certificate */
+ if (!len || (SSL_get_verify_result((SSL*)in) != X509_V_OK)) {
+ int err = X509_STORE_CTX_get_error((X509_STORE_CTX*)user);
+ int depth = X509_STORE_CTX_get_error_depth((X509_STORE_CTX*)user);
+ const char* msg = X509_verify_cert_error_string(err);
+ lwsl_err("LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION: SSL error: %s (%d), depth: %d\n", msg, err, depth);
+ return 1;
+ }
+ break;
+#if defined(LWS_HAVE_SSL_CTX_set1_param)
+ case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS:
+ if (crl_path[0]) {
+ /* Enable CRL checking */
+ X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
+ X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
+ SSL_CTX_set1_param((SSL_CTX*)user, param);
+ X509_STORE *store = SSL_CTX_get_cert_store((SSL_CTX*)user);
+ X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
+ n = X509_load_cert_crl_file(lookup, crl_path, X509_FILETYPE_PEM);
+ X509_VERIFY_PARAM_free(param);
+ if (n != 1) {
+ char errbuf[256];
+ n = ERR_get_error();
+ lwsl_err("LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS: SSL error: %s (%d)\n", ERR_error_string(n, errbuf), n);
+ return 1;
+ }
+ }
+ break;
+#endif
+#endif
+
default:
break;
}
{ "ssl-cert", required_argument, NULL, 'C' },
{ "ssl-key", required_argument, NULL, 'K' },
{ "ssl-ca", required_argument, NULL, 'A' },
+#if defined(LWS_OPENSSL_SUPPORT)
+ { "ssl-verify-client", no_argument, NULL, 'v' },
+#if defined(LWS_HAVE_SSL_CTX_set1_param)
+ { "ssl-crl", required_argument, NULL, 'R' },
+#endif
+#endif
{ "libev", no_argument, NULL, 'e' },
#ifndef LWS_NO_DAEMONIZE
{ "daemonize", no_argument, NULL, 'D' },
info.port = 7681;
while (n >= 0) {
- n = getopt_long(argc, argv, "eci:hsap:d:Dr:C:K:A:u:g:", options, NULL);
+ n = getopt_long(argc, argv, "eci:hsap:d:Dr:C:K:A:R:vu:g:", options, NULL);
if (n < 0)
continue;
switch (n) {
case 'A':
strncpy(ca_path, optarg, sizeof ca_path);
break;
+#if defined(LWS_OPENSSL_SUPPORT)
+ case 'v':
+ use_ssl = 1;
+ opts |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT;
+ break;
+#if defined(LWS_HAVE_SSL_CTX_set1_param)
+ case 'R':
+ strncpy(crl_path, optarg, sizeof crl_path);
+ break;
+#endif
+#endif
case 'h':
fprintf(stderr, "Usage: test-server "
"[--port=<p>] [--ssl] "
extern volatile int force_exit;
extern struct lws_context *context;
extern char *resource_path;
+#if defined(LWS_OPENSSL_SUPPORT) && defined(LWS_HAVE_SSL_CTX_set1_param)
+extern char crl_path[1024];
+#endif
extern void test_server_lock(int care);
extern void test_server_unlock(int care);