WIP/MINOR: ssl: add sample fetches for keylog in frontend

OpenSSL 1.1.1 provides a callback registering function
SSL_CTX_set_keylog_callback, which allows one to receive a string
containing the keys to deciphers TLSv1.3.

Unfortunately it is not possible to store this data in binary form and
we can only get this information using the callback. Which means that we
need to store it until the connection is closed.

This patches add 2 pools, the first one, pool_head_ssl_keylog is used to
store a struct ssl_keylog which will be inserted as a ex_data in a SSL *.
The second one is pool_head_ssl_keylog_str which will be used to store
the hexadecimal strings.

To enable the capture of the keys, you need to set "tune.ssl.keylog on"
in your configuration.

The following fetches were implemented:

ssl_fc_client_early_traffic_secret,
ssl_fc_client_handshake_traffic_secret,
ssl_fc_server_handshake_traffic_secret,
ssl_fc_client_traffic_secret_0,
ssl_fc_server_traffic_secret_0,
ssl_fc_exporter_secret,
ssl_fc_early_exporter_secret
This commit is contained in:
William Lallemand 2020-07-06 11:41:30 +02:00 committed by William Lallemand
parent 46a030cdda
commit 7d42ef5b22
6 changed files with 392 additions and 0 deletions

View File

@ -704,6 +704,7 @@ The following keywords are supported in the "global" section :
- tune.sndbuf.client - tune.sndbuf.client
- tune.sndbuf.server - tune.sndbuf.server
- tune.ssl.cachesize - tune.ssl.cachesize
- tune.ssl.keylog
- tune.ssl.lifetime - tune.ssl.lifetime
- tune.ssl.force-private-cache - tune.ssl.force-private-cache
- tune.ssl.maxrecord - tune.ssl.maxrecord
@ -2157,6 +2158,44 @@ tune.ssl.force-private-cache
this case, adding a first layer of hash-based load balancing before the SSL this case, adding a first layer of hash-based load balancing before the SSL
layer might limit the impact of the lack of session sharing. layer might limit the impact of the lack of session sharing.
tune.ssl.keylog { on | off }
This option activates the logging of the TLS keys. It should be used with
care as it will consume more memory per SSL session and could decrease
performances. This is disabled by default.
These sample fetches should be used to generate the SSLKEYLOGFILE that is
required to decipher traffic with wireshark.
https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
The SSLKEYLOG is a series of lines which are formatted this way:
<Label> <space> <ClientRandom> <space> <Secret>
The ClientRandom is provided by the %[ssl_fc_client_random,hex] sample
fetch, the secret and the Label could be find in the array below. You need
to generate a SSLKEYLOGFILE with all the labels in this array.
The following sample fetches are hexadecimal strings and does not need to be
converted.
SSLKEYLOGFILE Label | Sample fetches for the Secrets
--------------------------------|-----------------------------------------
CLIENT_EARLY_TRAFFIC_SECRET | %[ssl_fc_client_early_traffic_secret]
CLIENT_HANDSHAKE_TRAFFIC_SECRET | %[ssl_fc_client_handshake_traffic_secret]
SERVER_HANDSHAKE_TRAFFIC_SECRET | %[ssl_fc_server_handshake_traffic_secret]
CLIENT_TRAFFIC_SECRET_0 | %[ssl_fc_client_traffic_secret_0]
SERVER_TRAFFIC_SECRET_0 | %[ssl_fc_server_traffic_secret_0]
EARLY_EXPORTER_SECRET | %[ssl_fc_exporter_secret]
EXPORTER_SECRET | %[ssl_fc_early_exporter_secret]
This is only available with OpenSSL 1.1.1, and useful with TLS1.3 session.
If you want to generate the content of a SSLKEYLOGFILE with TLS < 1.3, you
only need this line:
"CLIENT_RANDOM %[ssl_fc_client_random,hex] %[ssl_fc_session_key,hex]"
tune.ssl.lifetime <timeout> tune.ssl.lifetime <timeout>
Sets how long a cached SSL session may remain valid. This time is expressed Sets how long a cached SSL session may remain valid. This time is expressed
in seconds and defaults to 300 (5 min). It is important to understand that it in seconds and defaults to 300 (5 min). It is important to understand that it
@ -17020,6 +17059,51 @@ ssl_fc_client_random : binary
was made over an SSL/TLS transport layer. It is useful to to decrypt traffic was made over an SSL/TLS transport layer. It is useful to to decrypt traffic
sent using ephemeral ciphers. This requires OpenSSL >= 1.1.0, or BoringSSL. sent using ephemeral ciphers. This requires OpenSSL >= 1.1.0, or BoringSSL.
ssl_fc_client_early_traffic_secret : string
Return the CLIENT_EARLY_TRAFFIC_SECRET as an hexadecimal string for the
front connection when the incoming connection was made over a TLS 1.3
transport layer.
Require OpenSSL >= 1.1.1. This is one of the keys dumped by the OpenSSL
keylog callback to generate the SSLKEYLOGFILE. The SSL Key logging must be
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_client_handshake_traffic_secret : string
Return the CLIENT_HANDSHAKE_TRAFFIC_SECRET as an hexadecimal string for the
front connection when the incoming connection was made over a TLS 1.3
transport layer.
Require OpenSSL >= 1.1.1. This is one of the keys dumped by the OpenSSL
keylog callback to generate the SSLKEYLOGFILE. The SSL Key logging must be
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_client_traffic_secret_0 : string
Return the CLIENT_TRAFFIC_SECRET_0 as an hexadecimal string for the
front connection when the incoming connection was made over a TLS 1.3
transport layer.
Require OpenSSL >= 1.1.1. This is one of the keys dumped by the OpenSSL
keylog callback to generate the SSLKEYLOGFILE. The SSL Key logging must be
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_exporter_secret : string
Return the EXPORTER_SECRET as an hexadecimal string for the
front connection when the incoming connection was made over a TLS 1.3
transport layer.
Require OpenSSL >= 1.1.1. This is one of the keys dumped by the OpenSSL
keylog callback to generate the SSLKEYLOGFILE. The SSL Key logging must be
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_early_exporter_secret : string
Return the EARLY_EXPORTER_SECRET as an hexadecimal string for the
front connection when the incoming connection was made over an TLS 1.3
transport layer.
Require OpenSSL >= 1.1.1. This is one of the keys dumped by the OpenSSL
keylog callback to generate the SSLKEYLOGFILE. The SSL Key logging must be
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_has_crt : boolean ssl_fc_has_crt : boolean
Returns true if a client certificate is present in an incoming connection over Returns true if a client certificate is present in an incoming connection over
SSL/TLS transport layer. Useful if 'verify' statement is set to 'optional'. SSL/TLS transport layer. Useful if 'verify' statement is set to 'optional'.
@ -17064,6 +17148,24 @@ ssl_fc_unique_id : binary
returns the TLS unique ID as defined in RFC5929 section 3. The unique id returns the TLS unique ID as defined in RFC5929 section 3. The unique id
can be encoded to base64 using the converter: "ssl_bc_unique_id,base64". can be encoded to base64 using the converter: "ssl_bc_unique_id,base64".
ssl_fc_server_handshake_traffic_secret : string
Return the SERVER_HANDSHAKE_TRAFFIC_SECRET as an hexadecimal string for the
front connection when the incoming connection was made over a TLS 1.3
transport layer.
Require OpenSSL >= 1.1.1. This is one of the keys dumped by the OpenSSL
keylog callback to generate the SSLKEYLOGFILE. The SSL Key logging must be
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_server_traffic_secret_0 : string
Return the SERVER_TRAFFIC_SECRET_0 as an hexadecimal string for the
front connection when the incoming connection was made over an TLS 1.3
transport layer.
Require OpenSSL >= 1.1.1. This is one of the keys dumped by the OpenSSL
keylog callback to generate the SSLKEYLOGFILE. The SSL Key logging must be
activated with "tune.ssl.keylog on" in the global section. See also
"tune.ssl.keylog"
ssl_fc_server_random : binary ssl_fc_server_random : binary
Returns the server random of the front connection when the incoming connection Returns the server random of the front connection when the incoming connection
was made over an SSL/TLS transport layer. It is useful to to decrypt traffic was made over an SSL/TLS transport layer. It is useful to to decrypt traffic

View File

@ -226,6 +226,26 @@ struct ssl_capture {
char ciphersuite[0]; char ciphersuite[0];
}; };
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
#define SSL_KEYLOG_MAX_SECRET_SIZE 129
struct ssl_keylog {
/*
* https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
*/
char *client_random;
/* TLS 1.3 */
char *client_early_traffic_secret;
char *client_handshake_traffic_secret;
char *server_handshake_traffic_secret;
char *client_traffic_secret_0;
char *server_traffic_secret_0;
char *exporter_secret;
char *early_exporter_secret;
};
#endif
struct ssl_sock_ctx { struct ssl_sock_ctx {
struct connection *conn; struct connection *conn;
SSL *ssl; SSL *ssl;
@ -268,6 +288,7 @@ struct global_ssl {
unsigned int default_dh_param; /* SSL maximum DH parameter size */ unsigned int default_dh_param; /* SSL maximum DH parameter size */
int ctx_cache; /* max number of entries in the ssl_ctx cache. */ int ctx_cache; /* max number of entries in the ssl_ctx cache. */
int capture_cipherlist; /* Size of the cipherlist buffer. */ int capture_cipherlist; /* Size of the cipherlist buffer. */
int keylog; /* activate keylog */
int extra_files; /* which files not defined in the configuration file are we looking for */ int extra_files; /* which files not defined in the configuration file are we looking for */
}; };

View File

@ -46,6 +46,9 @@ extern unsigned int openssl_engines_initialized;
extern int nb_engines; extern int nb_engines;
extern struct xprt_ops ssl_sock; extern struct xprt_ops ssl_sock;
extern int ssl_capture_ptr_index; extern int ssl_capture_ptr_index;
extern int ssl_keylog_index;
extern struct pool_head *pool_head_ssl_keylog;
extern struct pool_head *pool_head_ssl_keylog_str;
int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *, SSL_CTX *ctx, char **err); int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *, SSL_CTX *ctx, char **err);
int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf); int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf);

View File

@ -317,6 +317,44 @@ static int ssl_parse_global_capture_cipherlist(char **args, int section_type, st
return 0; return 0;
} }
/* init the SSLKEYLOGFILE pool */
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
static int ssl_parse_global_keylog(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, const char *file, int line,
char **err)
{
if (too_many_args(1, args, err, NULL))
return -1;
if (strcmp(args[1], "on") == 0)
global_ssl.keylog = 1;
else if (strcmp(args[1], "off") == 0)
global_ssl.keylog = 0;
else {
memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
return -1;
}
if (pool_head_ssl_keylog) /* already configured */
return 0;
pool_head_ssl_keylog = create_pool("ssl-keylogfile", sizeof(struct ssl_keylog), MEM_F_SHARED);
if (!pool_head_ssl_keylog) {
memprintf(err, "Out of memory error.");
return -1;
}
pool_head_ssl_keylog_str = create_pool("ssl-keylogfile-str", sizeof(char) * SSL_KEYLOG_MAX_SECRET_SIZE, MEM_F_SHARED);
if (!pool_head_ssl_keylog_str) {
memprintf(err, "Out of memory error.");
return -1;
}
return 0;
}
#endif
/* parse "ssl.force-private-cache". /* parse "ssl.force-private-cache".
* Returns <0 on alert, >0 on warning, 0 on success. * Returns <0 on alert, >0 on warning, 0 on success.
*/ */
@ -1820,6 +1858,9 @@ static struct cfg_kw_list cfg_kws = {ILH, {
{ CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int }, { CFG_GLOBAL, "tune.ssl.maxrecord", ssl_parse_global_int },
{ CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int }, { CFG_GLOBAL, "tune.ssl.ssl-ctx-cache-size", ssl_parse_global_int },
{ CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist }, { CFG_GLOBAL, "tune.ssl.capture-cipherlist-size", ssl_parse_global_capture_cipherlist },
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
{ CFG_GLOBAL, "tune.ssl.keylog", ssl_parse_global_keylog },
#endif
{ CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers }, { CFG_GLOBAL, "ssl-default-bind-ciphers", ssl_parse_global_ciphers },
{ CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers }, { CFG_GLOBAL, "ssl-default-server-ciphers", ssl_parse_global_ciphers },
#if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER)) #if ((HA_OPENSSL_VERSION_NUMBER >= 0x1000200fL) || defined(LIBRESSL_VERSION_NUMBER))

View File

@ -1108,6 +1108,63 @@ smp_fetch_ssl_fc_cl_xxh64(const struct arg *args, struct sample *smp, const char
return 1; return 1;
} }
/* Dump the SSL keylog, it only works with "tune.ssl.keylog 1" */
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
static int smp_fetch_ssl_x_keylog(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct connection *conn;
struct ssl_keylog *keylog;
SSL *ssl;
char *src = NULL;
const char *sfx;
conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) :
smp->strm ? cs_conn(objt_cs(smp->strm->si[1].end)) : NULL;
if (conn->flags & CO_FL_WAIT_XPRT) {
smp->flags |= SMP_F_MAY_CHANGE;
return 0;
}
ssl = ssl_sock_get_ssl_object(conn);
if (!ssl)
return 0;
keylog = SSL_get_ex_data(ssl, ssl_keylog_index);
if (!keylog)
return 0;
sfx = kw + strlen("ssl_xx_");
if (strcmp(sfx, "client_early_traffic_secret") == 0) {
src = keylog->client_early_traffic_secret;
} else if (strcmp(sfx, "client_handshake_traffic_secret") == 0) {
src = keylog->client_handshake_traffic_secret;
} else if (strcmp(sfx, "server_handshake_traffic_secret") == 0) {
src = keylog->server_handshake_traffic_secret;
} else if (strcmp(sfx, "client_traffic_secret_0") == 0) {
src = keylog->client_traffic_secret_0;
} else if (strcmp(sfx, "server_traffic_secret_0") == 0) {
src = keylog->server_traffic_secret_0;
} else if (strcmp(sfx, "exporter_secret") == 0) {
src = keylog->exporter_secret;
} else if (strcmp(sfx, "early_exporter_secret") == 0) {
src = keylog->early_exporter_secret;
}
if (!src || !*src)
return 0;
smp->data.u.str.area = src;
smp->data.type = SMP_T_STR;
smp->flags |= SMP_F_CONST;
smp->data.u.str.data = strlen(smp->data.u.str.area);
return 1;
/* log-format "CLIENT_RANDOM %[ssl_fc_client_random,hex] %[ssl_fc_session_key,hex]" */
}
#endif
static int static int
smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private) smp_fetch_ssl_fc_cl_str(const struct arg *args, struct sample *smp, const char *kw, void *private)
{ {
@ -1379,6 +1436,17 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
{ "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI }, { "ssl_fc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
{ "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI }, { "ssl_fc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5CLI },
#endif #endif
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
{ "ssl_fc_client_early_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_client_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_server_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_client_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_server_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
{ "ssl_fc_early_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
#endif
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
{ "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, { "ssl_fc_sni", smp_fetch_ssl_fc_sni, 0, NULL, SMP_T_STR, SMP_USE_L5CLI },
#endif #endif

View File

@ -129,6 +129,9 @@ struct global_ssl global_ssl = {
.ctx_cache = DEFAULT_SSL_CTX_CACHE, .ctx_cache = DEFAULT_SSL_CTX_CACHE,
.capture_cipherlist = 0, .capture_cipherlist = 0,
.extra_files = SSL_GF_ALL, .extra_files = SSL_GF_ALL,
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
.keylog = 0
#endif
}; };
static BIO_METHOD *ha_meth; static BIO_METHOD *ha_meth;
@ -433,6 +436,12 @@ struct pool_head *pool_head_ssl_capture = NULL;
int ssl_capture_ptr_index = -1; int ssl_capture_ptr_index = -1;
static int ssl_app_data_index = -1; static int ssl_app_data_index = -1;
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
int ssl_keylog_index = -1;
struct pool_head *pool_head_ssl_keylog = NULL;
struct pool_head *pool_head_ssl_keylog_str = NULL;
#endif
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0) #if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference); struct list tlskeys_reference = LIST_HEAD_INIT(tlskeys_reference);
#endif #endif
@ -505,6 +514,12 @@ static void ssl_sock_parse_clienthello(struct connection *conn, int write_p, int
int content_type, const void *buf, size_t len, int content_type, const void *buf, size_t len,
SSL *ssl); SSL *ssl);
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
static void ssl_init_keylog(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl);
#endif
/* List head of all registered SSL/TLS protocol message callbacks. */ /* List head of all registered SSL/TLS protocol message callbacks. */
struct list ssl_sock_msg_callbacks = LIST_HEAD_INIT(ssl_sock_msg_callbacks); struct list ssl_sock_msg_callbacks = LIST_HEAD_INIT(ssl_sock_msg_callbacks);
@ -544,6 +559,13 @@ static int ssl_sock_register_msg_callbacks(void)
if (!ssl_sock_register_msg_callback(ssl_sock_parse_clienthello)) if (!ssl_sock_register_msg_callback(ssl_sock_parse_clienthello))
return ERR_ABORT; return ERR_ABORT;
} }
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
if (global_ssl.keylog > 0) {
if (!ssl_sock_register_msg_callback(ssl_init_keylog))
return ERR_ABORT;
}
#endif
return 0; return 0;
} }
@ -1680,6 +1702,30 @@ static void ssl_sock_parse_clienthello(struct connection *conn, int write_p, int
SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture); SSL_set_ex_data(ssl, ssl_capture_ptr_index, capture);
} }
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
static void ssl_init_keylog(struct connection *conn, int write_p, int version,
int content_type, const void *buf, size_t len,
SSL *ssl)
{
struct ssl_keylog *keylog;
if (SSL_get_ex_data(ssl, ssl_keylog_index))
return;
keylog = pool_alloc(pool_head_ssl_keylog);
if (!keylog)
return;
memset(keylog, 0, sizeof(*keylog));
if (!SSL_set_ex_data(ssl, ssl_keylog_index, keylog)) {
pool_free(pool_head_ssl_keylog, keylog);
return;
}
}
#endif
/* Callback is called for ssl protocol analyse */ /* 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) void ssl_sock_msgcbk(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
{ {
@ -4020,6 +4066,88 @@ void ssl_set_shctx(SSL_CTX *ctx)
SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb); SSL_CTX_sess_set_remove_cb(ctx, sh_ssl_sess_remove_cb);
} }
/*
* https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
*
* The format is:
* * <Label> <space> <ClientRandom> <space> <Secret>
* We only need to copy the secret as there is a sample fetch for the ClientRandom
*/
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
void SSL_CTX_keylog(const SSL *ssl, const char *line)
{
struct ssl_keylog *keylog;
char *lastarg = NULL;
char *dst = NULL;
keylog = SSL_get_ex_data(ssl, ssl_keylog_index);
if (!keylog)
return;
lastarg = strrchr(line, ' ');
if (lastarg == NULL || ++lastarg == NULL)
return;
dst = pool_alloc(pool_head_ssl_keylog_str);
if (!dst)
return;
strncpy(dst, lastarg, SSL_KEYLOG_MAX_SECRET_SIZE-1);
dst[SSL_KEYLOG_MAX_SECRET_SIZE-1] = '\0';
if (strncmp(line, "CLIENT_RANDOM ", strlen("CLIENT RANDOM ")) == 0) {
if (keylog->client_random)
goto error;
keylog->client_random = dst;
} else if (strncmp(line, "CLIENT_EARLY_TRAFFIC_SECRET ", strlen("CLIENT_EARLY_TRAFFIC_SECRET ")) == 0) {
if (keylog->client_early_traffic_secret)
goto error;
keylog->client_early_traffic_secret = dst;
} else if (strncmp(line, "CLIENT_HANDSHAKE_TRAFFIC_SECRET ", strlen("CLIENT_HANDSHAKE_TRAFFIC_SECRET ")) == 0) {
if(keylog->client_handshake_traffic_secret)
goto error;
keylog->client_handshake_traffic_secret = dst;
} else if (strncmp(line, "SERVER_HANDSHAKE_TRAFFIC_SECRET ", strlen("SERVER_HANDSHAKE_TRAFFIC_SECRET ")) == 0) {
if (keylog->server_handshake_traffic_secret)
goto error;
keylog->server_handshake_traffic_secret = dst;
} else if (strncmp(line, "CLIENT_TRAFFIC_SECRET_0 ", strlen("CLIENT_TRAFFIC_SECRET_0 ")) == 0) {
if (keylog->client_traffic_secret_0)
goto error;
keylog->client_traffic_secret_0 = dst;
} else if (strncmp(line, "SERVER_TRAFFIC_SECRET_0 ", strlen("SERVER_TRAFFIC_SECRET_0 ")) == 0) {
if (keylog->server_traffic_secret_0)
goto error;
keylog->server_traffic_secret_0 = dst;
} else if (strncmp(line, "EARLY_EXPORTER_SECRET ", strlen("EARLY_EXPORTER_SECRET ")) == 0) {
if (keylog->early_exporter_secret)
goto error;
keylog->early_exporter_secret = dst;
} else if (strncmp(line, "EXPORTER_SECRET ", strlen("EXPORTER_SECRET ")) == 0) {
if (keylog->exporter_secret)
goto error;
keylog->exporter_secret = dst;
} else {
goto error;
}
return;
error:
pool_free(pool_head_ssl_keylog_str, dst);
return;
}
#endif
/* /*
* This function applies the SSL configuration on a SSL_CTX * This function applies the SSL configuration on a SSL_CTX
* It returns an error code and fills the <err> buffer * It returns an error code and fills the <err> buffer
@ -4182,6 +4310,9 @@ int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_conf *ssl_
#if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L #if HA_OPENSSL_VERSION_NUMBER >= 0x00907000L
SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk); SSL_CTX_set_msg_callback(ctx, ssl_sock_msgcbk);
#endif #endif
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
SSL_CTX_set_keylog_callback(ctx, SSL_CTX_keylog);
#endif
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) #if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
ssl_conf_cur = NULL; ssl_conf_cur = NULL;
@ -6591,6 +6722,29 @@ static void ssl_sock_capture_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *
pool_free(pool_head_ssl_capture, ptr); pool_free(pool_head_ssl_capture, ptr);
} }
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
static void ssl_sock_keylog_free_func(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, long argl, void *argp)
{
struct ssl_keylog *keylog;
if (!ptr)
return;
keylog = ptr;
pool_free(pool_head_ssl_keylog_str, keylog->client_random);
pool_free(pool_head_ssl_keylog_str, keylog->client_early_traffic_secret);
pool_free(pool_head_ssl_keylog_str, keylog->client_handshake_traffic_secret);
pool_free(pool_head_ssl_keylog_str, keylog->server_handshake_traffic_secret);
pool_free(pool_head_ssl_keylog_str, keylog->client_traffic_secret_0);
pool_free(pool_head_ssl_keylog_str, keylog->server_traffic_secret_0);
pool_free(pool_head_ssl_keylog_str, keylog->exporter_secret);
pool_free(pool_head_ssl_keylog_str, keylog->early_exporter_secret);
pool_free(pool_head_ssl_keylog, ptr);
}
#endif
__attribute__((constructor)) __attribute__((constructor))
static void __ssl_sock_init(void) static void __ssl_sock_init(void)
{ {
@ -6630,6 +6784,9 @@ static void __ssl_sock_init(void)
#endif #endif
ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); ssl_app_data_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func); ssl_capture_ptr_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_capture_free_func);
#if (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
ssl_keylog_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, ssl_sock_keylog_free_func);
#endif
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
ENGINE_load_builtin_engines(); ENGINE_load_builtin_engines();
hap_register_post_check(ssl_check_async_engine_count); hap_register_post_check(ssl_check_async_engine_count);