Skip to content

Commit

Permalink
Add Keylog file with env variable SSLKEYLOGFILE (for openssl)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gael COLIN committed Nov 6, 2024
1 parent 53c97bc commit c028b41
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 0 deletions.
84 changes: 84 additions & 0 deletions src/session_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <ctype.h>
#include <poll.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
Expand All @@ -43,6 +44,83 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>

#define SSLKEYLOGFILE_ENV "SSLKEYLOGFILE"
/* The fp for the open SSLKEYLOGFILE, or NULL if not open */
static volatile FILE *keylog_file_fp = NULL;
static volatile uint32_t keylog_tls_sessions = 0;
static pthread_mutex_t keylog_mutex = PTHREAD_MUTEX_INITIALIZER;

static int
nc_tls_keylog_open(void)
{
char *keylog_file_name;

keylog_file_name = getenv(SSLKEYLOGFILE_ENV);

if (keylog_file_name) {
pthread_mutex_lock(&keylog_mutex);
keylog_tls_sessions++;
DBL(NULL, "TID %lu create tls session: number %d", (long unsigned int)pthread_self(), keylog_tls_sessions);
if (!keylog_file_fp) {
keylog_file_fp = fopen(keylog_file_name, "a");
DBL(NULL, "TID %lu open keylog file %s", (long unsigned int)pthread_self(), keylog_file_name);
if (keylog_file_fp) {
if (setvbuf((FILE *) keylog_file_fp, NULL, _IOLBF, 4096)) {
fclose((FILE *) keylog_file_fp);
keylog_file_fp = NULL;
}
}
}
pthread_mutex_unlock(&keylog_mutex);
}
return keylog_file_fp != NULL;
}

static void
nc_tls_keylog_close(void)
{
if (keylog_file_fp) {
pthread_mutex_lock(&keylog_mutex);
keylog_tls_sessions--;
DBL(NULL, "TID %lu remove tls session: number %d", (long unsigned int)pthread_self(), keylog_tls_sessions);
if (keylog_tls_sessions == 0) {
DBL(NULL, "TID %lu close keylog file", (long unsigned int)pthread_self());
fclose((FILE *) keylog_file_fp);
keylog_file_fp = NULL;
}
pthread_mutex_unlock(&keylog_mutex);
}
}

static void
nc_tls_keylog_write_line(const SSL *UNUSED(ssl), const char *line)
{
/* The current maximum valid keylog line length LF and NUL is 195. */
size_t linelen;
char buf[256];

if (!keylog_file_fp || !line) {
return;
}

linelen = strlen(line);
if ((linelen == 0) || (linelen > sizeof(buf) - 2)) {
/* Empty line or too big to fit in a LF and NUL. */
return;
}

memcpy(buf, line, linelen);
if (line[linelen - 1] != '\n') {
buf[linelen++] = '\n';
}
buf[linelen] = '\0';

/* Using fputs here instead of fprintf since libcurl's fprintf replacement
may not be thread-safe. */
fputs(buf, (FILE *)keylog_file_fp);
return;
}

void *
nc_tls_session_new_wrap(void *tls_cfg)
{
Expand All @@ -54,13 +132,19 @@ nc_tls_session_new_wrap(void *tls_cfg)
return NULL;
}

if (nc_tls_keylog_open()) {
SSL_CTX_set_keylog_callback(tls_cfg, nc_tls_keylog_write_line);
}

return session;
}

void
nc_tls_session_destroy_wrap(void *tls_session)
{
SSL_free(tls_session);

nc_tls_keylog_close();
}

void *
Expand Down
64 changes: 64 additions & 0 deletions tests/test_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

int TEST_PORT = 10050;
const char *TEST_PORT_STR = "10050";
const char *KEYLOG_FILE = "keylog.txt";

static void *
client_thread(void *arg)
Expand Down Expand Up @@ -54,6 +55,50 @@ client_thread(void *arg)
return NULL;
}

#ifndef HAVE_MBEDTLS

/** test keylog.txt file */
static void
assert_keylog_file()
{
FILE *file;
char line[256];
const char *lines_types[] = {
"SERVER_HANDSHAKE_TRAFFIC_SECRET",
"CLIENT_HANDSHAKE_TRAFFIC_SECRET",
"EXPORTER_SECRET",
"SERVER_TRAFFIC_SECRET_0",
"CLIENT_TRAFFIC_SECRET_0"
};
int lines_types_count[] = {0, 0, 0, 0, 0};

fprintf(stderr, "Checking keylog file\n");

if (!getenv("SSLKEYLOGFILE")) {
return;
}

file = fopen(KEYLOG_FILE, "r");
assert_non_null(file);

while (fgets(line, sizeof(line), file)) {
assert_true(strlen(line) > 32);
for (int i = 0; i < 5; i++) {
if (strncmp(line, lines_types[i], strlen(lines_types[i])) == 0) {
lines_types_count[i]++;
}
}
}
for (int i = 0; i < 5; i++) {
assert_int_equal(lines_types_count[i], 2);
}

fclose(file);
remove(KEYLOG_FILE);
}

#endif

static void
test_nc_tls(void **state)
{
Expand All @@ -70,6 +115,10 @@ test_nc_tls(void **state)
for (i = 0; i < 2; i++) {
pthread_join(tids[i], NULL);
}

#ifndef HAVE_MBEDTLS
assert_keylog_file();
#endif
}

static int
Expand Down Expand Up @@ -115,11 +164,25 @@ setup_f(void **state)
return 0;
}

static int
setup_f_with_keylog(void **state)
{
setenv("SSLKEYLOGFILE", KEYLOG_FILE, 1);
return setup_f(state);
}

static void
test_nc_tls_with_keylog(void **state)
{
test_nc_tls(state);
}

int
main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown(test_nc_tls, setup_f, ln2_glob_test_teardown),
cmocka_unit_test_setup_teardown(test_nc_tls_with_keylog, setup_f_with_keylog, ln2_glob_test_teardown)
};

/* try to get ports from the environment, otherwise use the default */
Expand All @@ -128,5 +191,6 @@ main(void)
}

setenv("CMOCKA_TEST_ABORT", "1", 1);
setenv("SSLKEYLOGFILE", KEYLOG_FILE, 1);
return cmocka_run_group_tests(tests, NULL, NULL);
}

0 comments on commit c028b41

Please sign in to comment.