rustls: Add support for SSLKEYLOGFILE

With rustls-ffi 0.15+ we can set up a callback for writing TLS secrets
hooked up to call Curl_tls_keylog_write. To make sure the associated
file is cleaned up we update the Curl_ssl struct for the rustls-ffi vtls
backend to have a cleanup callback.

Closes #16828
This commit is contained in:
Yedaya Katsman 2024-10-21 23:28:28 +03:00 committed by Daniel Stenberg
parent 9ad2d8c557
commit 1d31f2592f
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
3 changed files with 52 additions and 3 deletions

View file

@ -102,7 +102,7 @@ If you set this environment variable to a filename, curl stores TLS secrets
from its connections in that file when invoked to enable you to analyze the
TLS traffic in real time using network analyzing tools such as Wireshark. This
works with the following TLS backends: OpenSSL, LibreSSL (TLS 1.2 max),
BoringSSL, GnuTLS and wolfSSL.
BoringSSL, GnuTLS, wolfSSL and Rustls.
## `USERPROFILE` <dir>
On Windows, this variable is used when trying to find the home directory. If

View file

@ -27,7 +27,8 @@
defined(USE_GNUTLS) || \
defined(USE_WOLFSSL) || \
(defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
defined(USE_QUICHE)
defined(USE_QUICHE) || \
defined(USE_RUSTLS)
#include "keylog.h"
#include <curl/curl.h>

View file

@ -38,6 +38,7 @@
#include "vtls.h"
#include "vtls_int.h"
#include "rustls.h"
#include "keylog.h"
#include "strerror.h"
#include "cipher_suite.h"
#include "x509asn1.h"
@ -518,6 +519,19 @@ add_ciphers:
*selected_size = count;
}
static void
cr_keylog_log_cb(struct rustls_str label,
const uint8_t *client_random, size_t client_random_len,
const uint8_t *secret, size_t secret_len)
{
char clabel[KEYLOG_LABEL_MAXLEN];
(void)client_random_len;
DEBUGASSERT(client_random_len == CLIENT_RANDOM_SIZE);
/* Turning a "rustls_str" into a null delimited "c" string */
msnprintf(clabel, label.len + 1, "%.*s", (int)label.len, label.data);
Curl_tls_keylog_write(clabel, client_random, secret, secret_len);
}
static CURLcode
init_config_builder(struct Curl_easy *data,
const struct ssl_primary_config *conn_config,
@ -774,6 +788,29 @@ cleanup:
return result;
}
static CURLcode
init_config_builder_keylog(struct Curl_easy *data,
struct rustls_client_config_builder *builder)
{
rustls_result rr;
Curl_tls_keylog_open();
if(!Curl_tls_keylog_enabled()) {
return CURLE_OK;
}
rr = rustls_client_config_builder_set_key_log(builder,
cr_keylog_log_cb,
NULL);
if(rr != RUSTLS_RESULT_OK) {
rustls_failf(data, rr, "rustls_client_config_builder_set_key_log");
Curl_tls_keylog_close();
return map_error(rr);
}
return CURLE_OK;
}
static CURLcode
cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
struct rustls_ssl_backend_data *const backend)
@ -819,6 +856,12 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
}
}
result = init_config_builder_keylog(data, config_builder);
if(result != CURLE_OK) {
rustls_client_config_builder_free(config_builder);
return result;
}
rr = rustls_client_config_builder_build(
config_builder,
&backend->config);
@ -1125,6 +1168,11 @@ cr_random(struct Curl_easy *data, unsigned char *entropy, size_t length)
return map_error(rresult);
}
static void cr_cleanup(void)
{
Curl_tls_keylog_close();
}
const struct Curl_ssl Curl_ssl_rustls = {
{ CURLSSLBACKEND_RUSTLS, "rustls" },
SSLSUPP_CAINFO_BLOB | /* supports */
@ -1135,7 +1183,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
sizeof(struct rustls_ssl_backend_data),
NULL, /* init */
NULL, /* cleanup */
cr_cleanup, /* cleanup */
cr_version, /* version */
cr_shutdown, /* shutdown */
cr_data_pending, /* data_pending */