MEDIUM: ssl: allow to register callbacks for SSL/TLS protocol messages

This patch adds the ability to register callbacks for SSL/TLS protocol
messages by using the function ssl_sock_register_msg_callback().

All registered callback functions will be called when observing received
or sent SSL/TLS protocol messages.
This commit is contained in:
Dragan Dosen 2020-05-08 18:30:00 +02:00 committed by William Lallemand
parent 5ce3c14aa9
commit 1e7ed04665
3 changed files with 75 additions and 1 deletions

View File

@ -103,6 +103,12 @@ void ssl_async_fd_free(int fd);
#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
(k), SSL_MAX_SSL_SESSION_ID_LENGTH);
/* Registers the function <func> in order to be called on SSL/TLS protocol
* message processing.
*/
int ssl_sock_register_msg_callback(ssl_sock_msg_callback_func func);
#endif /* USE_OPENSSL */
#endif /* _PROTO_SSL_SOCK_H */

View File

@ -31,6 +31,8 @@
#include <common/mini-clist.h>
#include <common/openssl-compat.h>
struct connection;
struct pkey_info {
uint8_t sig; /* TLSEXT_signature_[rsa,ecdsa,...] */
uint16_t bits; /* key size in bits */
@ -202,6 +204,18 @@ struct issuer_chain {
char *path;
};
typedef void (*ssl_sock_msg_callback_func)(struct connection *conn,
int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl);
/* This structure contains a function pointer <func> that is called
* when observing received or sent SSL/TLS protocol messages, such as
* handshake messages or other events that can occur during processing.
*/
struct ssl_sock_msg_callback {
ssl_sock_msg_callback_func func;
struct list list; /* list of registered callbacks */
};
#endif /* USE_OPENSSL */
#endif /* _TYPES_SSL_SOCK_H */

View File

@ -629,6 +629,46 @@ static struct eb_root *sh_ssl_sess_tree; /* ssl shared session tree */
#define sh_ssl_sess_tree_lookup(k) (struct sh_ssl_sess_hdr *)ebmb_lookup(sh_ssl_sess_tree, \
(k), SSL_MAX_SSL_SESSION_ID_LENGTH);
/* List head of all registered SSL/TLS protocol message callbacks. */
struct list ssl_sock_msg_callbacks = LIST_HEAD_INIT(ssl_sock_msg_callbacks);
/* Registers the function <func> in order to be called on SSL/TLS protocol
* message processing. It will return 0 if the function <func> is not set
* or if it fails to allocate memory.
*/
int ssl_sock_register_msg_callback(ssl_sock_msg_callback_func func)
{
struct ssl_sock_msg_callback *cbk;
if (!func)
return 0;
cbk = calloc(1, sizeof(*cbk));
if (!cbk) {
ha_alert("out of memory in ssl_sock_register_msg_callback().\n");
return 0;
}
cbk->func = func;
LIST_ADDQ(&ssl_sock_msg_callbacks, &cbk->list);
return 1;
}
/* Used to free all SSL/TLS protocol message callbacks that were
* registered by using ssl_sock_register_msg_callback().
*/
static void ssl_sock_unregister_msg_callbacks(void)
{
struct ssl_sock_msg_callback *cbk, *cbkback;
list_for_each_entry_safe(cbk, cbkback, &ssl_sock_msg_callbacks, list) {
LIST_DEL(&cbk->list);
free(cbk);
}
}
/*
* This function gives the detail of the SSL error. It is used only
* if the debug mode and the verbose mode are activated. It dump all
@ -1887,11 +1927,13 @@ void ssl_sock_parse_clienthello(int write_p, int version, int content_type,
/* Callback is called for ssl protocol analyse */
void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
{
struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
struct ssl_sock_msg_callback *cbk;
#ifdef TLS1_RT_HEARTBEAT
/* test heartbeat received (write_p is set to 0
for a received record) */
if ((content_type == TLS1_RT_HEARTBEAT) && (write_p == 0)) {
struct connection *conn = SSL_get_ex_data(ssl, ssl_app_data_index);
struct ssl_sock_ctx *ctx = conn->xprt_ctx;
const unsigned char *p = buf;
unsigned int payload;
@ -1928,6 +1970,13 @@ void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf
#endif
if (global_ssl.capture_cipherlist > 0)
ssl_sock_parse_clienthello(write_p, version, content_type, buf, len, ssl);
/* Try to call all callback functions that were registered by using
* ssl_sock_register_msg_callback().
*/
list_for_each_entry(cbk, &ssl_sock_msg_callbacks, list) {
cbk->func(conn, write_p, version, content_type, buf, len, ssl);
}
}
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
@ -13100,6 +13149,11 @@ static void __ssl_sock_init(void)
BIO_meth_set_gets(ha_meth, ha_ssl_gets);
HA_SPIN_INIT(&ckch_lock);
/* Try to free all callbacks that were registered by using
* ssl_sock_register_msg_callback().
*/
hap_register_post_deinit(ssl_sock_unregister_msg_callbacks);
}
/* Compute and register the version string */