set (temp ${CMAKE_REQUIRED_LIBRARIES})
set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIST})
CHECK_FUNCTION_EXISTS(SSL_CTX_set1_param LWS_HAVE_SSL_CTX_set1_param)
+CHECK_FUNCTION_EXISTS(SSL_set_info_callback LWS_HAVE_SSL_SET_INFO_CALLBACK)
CHECK_FUNCTION_EXISTS(X509_VERIFY_PARAM_set1_host LWS_HAVE_X509_VERIFY_PARAM_set1_host)
if (LWS_WITH_ESP32)
set(LWS_HAVE_TLS_CLIENT_METHOD 1)
to build in support and select it at runtime.
+@section sslinfo SSL info callbacks
+
+OpenSSL allows you to receive callbacks for various events defined in a
+bitmask in openssl/ssl.h. The events include stuff like TLS Alerts.
+
+By default, lws doesn't register for these callbacks.
+
+However if you set the info.ssl_info_event_mask to nonzero (ie, set some
+of the bits in it like `SSL_CB_ALERT` at vhost creation time, then
+connections to that vhost will call back using LWS_CALLBACK_SSL_INFO
+for the wsi, and the `in` parameter will be pointing to a struct of
+related args:
+
+```
+struct lws_ssl_info {
+ int where;
+ int ret;
+};
+```
+
+The default callback handler in lws has a handler for LWS_CALLBACK_SSL_INFO
+which prints the related information, You can test it using the switch
+-S -s on `libwebsockets-test-server-v2.0`.
+
+Returning nonzero from the callback will close the wsi.
+
@section smp SMP / Multithreaded service
SMP support is integrated into LWS without any internal threading. It's
"sent %d only %d went", n, args->len);
return n;
#endif
+
+ case LWS_CALLBACK_SSL_INFO:
+ {
+ struct lws_ssl_info *si = in;
+
+ lwsl_notice("LWS_CALLBACK_SSL_INFO: where: 0x%x, ret: 0x%x\n",
+ si->where, si->ret);
+ }
+ break;
+
default:
break;
}
vh->options = info->options;
vh->pvo = info->pvo;
vh->headers = info->headers;
+ vh->ssl_info_event_mask = info->ssl_info_event_mask;
if (info->keepalive_timeout)
vh->keepalive_timeout = info->keepalive_timeout;
else
*/
///@{
+struct lws_ssl_info {
+ int where;
+ int ret;
+};
/*
* NOTE: These public enums are part of the abi. If you want to add one,
/**< RAW mode file is writeable */
LWS_CALLBACK_RAW_CLOSE_FILE = 66,
/**< RAW mode wsi that adopted a file is closing */
+ LWS_CALLBACK_SSL_INFO = 67,
+ /**< SSL connections only. An event you registered an
+ * interest in at the vhost has occurred on a connection
+ * using the vhost. @in is a pointer to a
+ * struct lws_ssl_info containing information about the
+ * event*/
/****** add new things just above ---^ ******/
* members added above will see 0 (default) even if the app
* was not built against the newer headers.
*/
+ int ssl_info_event_mask;
+ /**< VHOST: mask of ssl events to be reported on LWS_CALLBACK_SSL_INFO
+ * callback for connections on this vhost. The mask values are of
+ * the form SSL_CB_ALERT, defined in openssl/ssl.h. The default of
+ * 0 means no info events will be reported.
+ */
void *_unused[8]; /**< dummy */
};
PENDING_TIMEOUT_AWAITING_SOCKS_GREETING_REPLY = 19,
PENDING_TIMEOUT_AWAITING_SOCKS_CONNECT_REPLY = 20,
PENDING_TIMEOUT_AWAITING_SOCKS_AUTH_REPLY = 21,
+ PENDING_TIMEOUT_KILLED_BY_SSL_INFO = 22,
/****** add new things just above ---^ ******/
};
int ka_probes;
int ka_interval;
int keepalive_timeout;
+ int ssl_info_event_mask;
#ifdef LWS_WITH_ACCESS_LOG
int log_fd;
#endif
#else
#define LWS_UNIX_SOCK_ENABLED(vhost) (0)
#endif
+
enum uri_path_states {
URIPS_IDLE,
URIPS_SEEN_SLASH,
LWS_EXTERN int
lws_context_init_client_ssl(struct lws_context_creation_info *info,
struct lws_vhost *vhost);
+
+LWS_EXTERN void
+lws_ssl_info_callback(const SSL *ssl, int where, int ret);
+
#else
#define lws_context_init_client_ssl(_a, _b) (0)
#endif
return -1;
}
+#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
+ if (wsi->vhost->ssl_info_event_mask)
+ SSL_set_info_callback(wsi->ssl, lws_ssl_info_callback);
+#endif
+
#if defined LWS_HAVE_X509_VERIFY_PARAM_set1_host
X509_VERIFY_PARAM *param;
(void)param;
return 0;
}
+void
+lws_ssl_info_callback(const SSL *ssl, int where, int ret)
+{
+ struct lws *wsi;
+ struct lws_context *context;
+ struct lws_ssl_info si;
+
+ context = (struct lws_context *)SSL_CTX_get_ex_data(
+ SSL_get_SSL_CTX(ssl),
+ openssl_SSL_CTX_private_data_index);
+ if (!context)
+ return;
+ wsi = wsi_from_fd(context, SSL_get_fd(ssl));
+ if (!wsi)
+ return;
+
+ if (!(where & wsi->vhost->ssl_info_event_mask))
+ return;
+
+ si.where = where;
+ si.ret = ret;
+
+ if (user_callback_handle_rxflow(wsi->protocol->callback,
+ wsi, LWS_CALLBACK_SSL_INFO,
+ wsi->user_space, &si, 0))
+ lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1);
+}
+
+
LWS_VISIBLE int
lws_ssl_close(struct lws *wsi)
{
if (!wsi->ssl)
return 0; /* not handled */
+#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
+ /* kill ssl callbacks, becausse we will remove the fd from the
+ * table linking it to the wsi
+ */
+ if (wsi->vhost->ssl_info_event_mask)
+ SSL_set_info_callback(wsi->ssl, NULL);
+#endif
+
n = SSL_get_fd(wsi->ssl);
SSL_shutdown(wsi->ssl);
compatible_close(n);
compatible_close(accept_fd);
goto fail;
}
+#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK)
+ if (wsi->vhost->ssl_info_event_mask)
+ SSL_set_info_callback(wsi->ssl, lws_ssl_info_callback);
+#endif
if (context->simultaneous_ssl_restriction &&
++context->simultaneous_ssl == context->simultaneous_ssl_restriction)
/* that was the last allowed SSL connection */
#cmakedefine LWS_HAVE_TLS_CLIENT_METHOD
#cmakedefine LWS_HAVE_TLSV1_2_CLIENT_METHOD
+#cmakedefine LWS_HAVE_SSL_SET_INFO_CALLBACK
${LWS_SIZEOFPTR_CODE}
{ "debug", required_argument, NULL, 'd' },
{ "port", required_argument, NULL, 'p' },
{ "ssl", no_argument, NULL, 's' },
+ { "ssl-alerts", no_argument, NULL, 'S' },
{ "allow-non-ssl", no_argument, NULL, 'a' },
{ "interface", required_argument, NULL, 'i' },
{ "ssl-cert", required_argument, NULL, 'C' },
info.port = 7681;
while (n >= 0) {
- n = getopt_long(argc, argv, "i:hsap:d:Dr:C:K:A:R:vu:g:",
+ n = getopt_long(argc, argv, "i:hsap:d:Dr:C:K:A:R:vu:g:S",
(struct option *)options, NULL);
if (n < 0)
continue;
case 's':
use_ssl = 1;
break;
+ case 'S':
+#if defined(LWS_OPENSSL_SUPPORT)
+ info.ssl_info_event_mask |= SSL_CB_ALERT;
+#endif
+ break;
case 'a':
opts |= LWS_SERVER_OPTION_ALLOW_NON_SSL_ON_SSL_PORT;
break;