Skip to content

Commit 6511378

Browse files
author
Dmitri Tikhonov
committed
Release 2.27.0
- [API] Remove keylog callbacks. See issue #188. - Add a bit more ALPN logging.
1 parent 292abba commit 6511378

File tree

10 files changed

+119
-176
lines changed

10 files changed

+119
-176
lines changed

CHANGELOG

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2020-12-31
2+
- 2.27.0
3+
- [API] Remove keylog callbacks. See issue #188.
4+
- Add a bit more ALPN logging.
5+
16
2020-12-23
27
- 2.26.2
38
- [BUGFIX] Do not drop incoming data when STOP_SENDING is received.

bin/prog.c

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838
#include "prog.h"
3939

4040
static int prog_stopped;
41+
static const char *s_keylog_dir;
4142

4243
static SSL_CTX * get_ssl_ctx (void *, const struct sockaddr *);
44+
static void keylog_log_line (const SSL *, const char *);
4345

4446
static const struct lsquic_packout_mem_if pmi = {
4547
.pmi_allocate = pba_allocate,
@@ -81,7 +83,7 @@ prog_init (struct prog *prog, unsigned flags,
8183
= prog;
8284
prog->prog_api.ea_pmi = &pmi;
8385
prog->prog_api.ea_pmi_ctx = &prog->prog_pba;
84-
prog->prog_api.ea_get_ssl_ctx = flags & LSENG_SERVER ? get_ssl_ctx : NULL;
86+
prog->prog_api.ea_get_ssl_ctx = get_ssl_ctx;
8587
#if LSQUIC_PREFERRED_ADDR
8688
if (getenv("LSQUIC_PREFERRED_ADDR4") || getenv("LSQUIC_PREFERRED_ADDR6"))
8789
prog->prog_flags |= PROG_SEARCH_ADDRS;
@@ -356,7 +358,7 @@ prog_set_opt (struct prog *prog, int opt, const char *arg)
356358
return -1;
357359
}
358360
}
359-
prog->prog_keylog_dir = optarg;
361+
s_keylog_dir = optarg;
360362
if (prog->prog_settings.es_ql_bits)
361363
{
362364
LSQ_NOTICE("QL loss bits turned off because of -G. If you want "
@@ -425,29 +427,41 @@ get_ssl_ctx (void *peer_ctx, const struct sockaddr *unused)
425427

426428

427429
static int
428-
prog_init_server (struct prog *prog)
430+
prog_init_ssl_ctx (struct prog *prog)
429431
{
430-
struct service_port *sport;
431432
unsigned char ticket_keys[48];
432433

433434
prog->prog_ssl_ctx = SSL_CTX_new(TLS_method());
434-
if (prog->prog_ssl_ctx)
435+
if (!prog->prog_ssl_ctx)
435436
{
436-
SSL_CTX_set_min_proto_version(prog->prog_ssl_ctx, TLS1_3_VERSION);
437-
SSL_CTX_set_max_proto_version(prog->prog_ssl_ctx, TLS1_3_VERSION);
438-
SSL_CTX_set_default_verify_paths(prog->prog_ssl_ctx);
439-
440-
/* This is obviously test code: the key is just an array of NUL bytes */
441-
memset(ticket_keys, 0, sizeof(ticket_keys));
442-
if (1 != SSL_CTX_set_tlsext_ticket_keys(prog->prog_ssl_ctx,
443-
ticket_keys, sizeof(ticket_keys)))
444-
{
445-
LSQ_ERROR("SSL_CTX_set_tlsext_ticket_keys failed");
446-
return -1;
447-
}
437+
LSQ_ERROR("cannot allocate SSL context");
438+
return -1;
448439
}
449-
else
450-
LSQ_WARN("cannot create SSL context");
440+
441+
SSL_CTX_set_min_proto_version(prog->prog_ssl_ctx, TLS1_3_VERSION);
442+
SSL_CTX_set_max_proto_version(prog->prog_ssl_ctx, TLS1_3_VERSION);
443+
SSL_CTX_set_default_verify_paths(prog->prog_ssl_ctx);
444+
445+
/* This is obviously test code: the key is just an array of NUL bytes */
446+
memset(ticket_keys, 0, sizeof(ticket_keys));
447+
if (1 != SSL_CTX_set_tlsext_ticket_keys(prog->prog_ssl_ctx,
448+
ticket_keys, sizeof(ticket_keys)))
449+
{
450+
LSQ_ERROR("SSL_CTX_set_tlsext_ticket_keys failed");
451+
return -1;
452+
}
453+
454+
if (s_keylog_dir)
455+
SSL_CTX_set_keylog_callback(prog->prog_ssl_ctx, keylog_log_line);
456+
457+
return 0;
458+
}
459+
460+
461+
static int
462+
prog_init_server (struct prog *prog)
463+
{
464+
struct service_port *sport;
451465

452466
TAILQ_FOREACH(sport, prog->prog_sports, next_sport)
453467
if (0 != sport_init_server(sport, prog->prog_engine, prog->prog_eb))
@@ -582,55 +596,46 @@ prog_stop (struct prog *prog)
582596

583597

584598
static void *
585-
keylog_open (void *ctx, lsquic_conn_t *conn)
599+
keylog_open_file (const SSL *ssl)
586600
{
587-
const struct prog *const prog = ctx;
601+
const lsquic_conn_t *conn;
588602
const lsquic_cid_t *cid;
589603
FILE *fh;
590604
int sz;
591605
char id_str[MAX_CID_LEN * 2 + 1];
592606
char path[PATH_MAX];
593607

608+
conn = lsquic_ssl_to_conn(ssl);
594609
cid = lsquic_conn_id(conn);
595610
lsquic_hexstr(cid->idbuf, cid->len, id_str, sizeof(id_str));
596-
sz = snprintf(path, sizeof(path), "%s/%s.keys", prog->prog_keylog_dir,
597-
id_str);
611+
sz = snprintf(path, sizeof(path), "%s/%s.keys", s_keylog_dir, id_str);
598612
if ((size_t) sz >= sizeof(path))
599613
{
600614
LSQ_WARN("%s: file too long", __func__);
601615
return NULL;
602616
}
603-
fh = fopen(path, "w");
617+
fh = fopen(path, "ab");
604618
if (!fh)
605-
LSQ_WARN("could not open %s for writing: %s", path, strerror(errno));
619+
LSQ_WARN("could not open %s for appending: %s", path, strerror(errno));
606620
return fh;
607621
}
608622

609623

610624
static void
611-
keylog_log_line (void *handle, const char *line)
625+
keylog_log_line (const SSL *ssl, const char *line)
612626
{
613-
fputs(line, handle);
614-
fputs("\n", handle);
615-
fflush(handle);
616-
}
627+
FILE *file;
617628

618-
619-
static void
620-
keylog_close (void *handle)
621-
{
622-
fclose(handle);
629+
file = keylog_open_file(ssl);
630+
if (file)
631+
{
632+
fputs(line, file);
633+
fputs("\n", file);
634+
fclose(file);
635+
}
623636
}
624637

625638

626-
static const struct lsquic_keylog_if keylog_if =
627-
{
628-
.kli_open = keylog_open,
629-
.kli_log_line = keylog_log_line,
630-
.kli_close = keylog_close,
631-
};
632-
633-
634639
static struct ssl_ctx_st *
635640
no_cert (void *cert_lu_ctx, const struct sockaddr *sa_UNUSED, const char *sni)
636641
{
@@ -644,10 +649,17 @@ prog_prep (struct prog *prog)
644649
int s;
645650
char err_buf[100];
646651

647-
if (prog->prog_keylog_dir)
652+
if (s_keylog_dir && prog->prog_certs)
648653
{
649-
prog->prog_api.ea_keylog_if = &keylog_if;
650-
prog->prog_api.ea_keylog_ctx = prog;
654+
struct lsquic_hash_elem *el;
655+
struct server_cert *cert;
656+
657+
for (el = lsquic_hash_first(prog->prog_certs); el;
658+
el = lsquic_hash_next(prog->prog_certs))
659+
{
660+
cert = lsquic_hashelem_getdata(el);
661+
SSL_CTX_set_keylog_callback(cert->ce_ssl_ctx, keylog_log_line);
662+
}
651663
}
652664

653665
if (0 != lsquic_engine_check_settings(prog->prog_api.ea_settings,
@@ -696,6 +708,9 @@ prog_prep (struct prog *prog)
696708
prog->prog_timer = event_new(prog->prog_eb, -1, 0,
697709
prog_timer_handler, prog);
698710

711+
if (0 != prog_init_ssl_ctx(prog))
712+
return -1;
713+
699714
if (prog->prog_engine_flags & LSENG_SERVER)
700715
s = prog_init_server(prog);
701716
else

bin/prog.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ struct prog
4545
struct lsquic_engine *prog_engine;
4646
const char *prog_hostname;
4747
int prog_ipver; /* 0, 4, or 6 */
48-
const char *prog_keylog_dir;
4948
enum {
5049
PROG_FLAG_COOLDOWN = 1 << 0,
5150
#if LSQUIC_PREFERRED_ADDR

docs/apiref.rst

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,6 +1981,10 @@ Miscellaneous Stream Functions
19811981
Other Functions
19821982
---------------
19831983

1984+
.. function:: lsquic_conn_t lsquic_ssl_to_conn (const SSL *)
1985+
1986+
Get connection associated with this SSL object.
1987+
19841988
.. function:: enum lsquic_version lsquic_str2ver (const char *str, size_t len)
19851989

19861990
Translate string QUIC version to LSQUIC QUIC version representation.
@@ -2103,22 +2107,6 @@ Miscellaneous Types
21032107

21042108
Number of elements in the peer context pointer and connection ID arrays.
21052109

2106-
.. type:: struct lsquic_keylog_if
2107-
2108-
SSL keylog interface.
2109-
2110-
.. member:: void * (*kli_open) (void *keylog_ctx, lsquic_conn_t *conn)
2111-
2112-
Return keylog handle or NULL if no key logging is desired.
2113-
2114-
.. member:: void (*kli_log_line) (void *handle, const char *line)
2115-
2116-
Log line. The first argument is the pointer returned by ``kli_open()``.
2117-
2118-
.. member:: void (*kli_close) (void *handle)
2119-
2120-
Close handle.
2121-
21222110
.. type:: enum lsquic_logger_timestamp_style
21232111

21242112
Enumerate timestamp styles supported by LSQUIC logger mechanism.

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
author = u'LiteSpeed Technologies'
2525

2626
# The short X.Y version
27-
version = u'2.26'
27+
version = u'2.27'
2828
# The full version, including alpha/beta/rc tags
29-
release = u'2.26.2'
29+
release = u'2.27.0'
3030

3131

3232
# -- General configuration ---------------------------------------------------

docs/tutorial.rst

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,37 +1078,19 @@ Key logging and Wireshark
10781078
`Wireshark`_ supports IETF QUIC. The developers have been very good at keeping up with latest versions.
10791079
You will need version 3.3 of Wireshark to support Internet-Draft 29. Support for HTTP/3 is in progress.
10801080

1081-
LSQUIC supports exporting TLS secrets. For that, you need to specify a set of function pointers via
1082-
:member:`lsquic_engine_api.ea_keylog_if`.
1083-
1084-
::
1085-
1086-
/* Secrets are logged per connection. Interface to open file (handle),
1087-
* log lines, and close file.
1088-
*/
1089-
struct lsquic_keylog_if {
1090-
void * (*kli_open) (void *keylog_ctx, lsquic_conn_t *);
1091-
void (*kli_log_line) (void *handle, const char *line);
1092-
void (*kli_close) (void *handle);
1093-
};
1094-
1095-
struct lsquic_engine_api {
1096-
/* --- 8< --- snip --- 8< --- */
1097-
const struct lsquic_keylog_if *ea_keylog_if;
1098-
void *ea_keylog_ctx;
1099-
};
1100-
1101-
There are three functions: one to open a file, one to write a line into the file, and one to close the file. The lines are not interpreted.
1102-
In the engine API struct, there are two members to set: one is the pointer to the struct with the function pointers, and the other is the context passed to "kli_open" function.
1081+
To export TLS secrets, use BoringSSL's ``SSL_CTX_set_keylog_callback()``.
1082+
Use `lsquic_ssl_to_conn()` to get the connection associated
1083+
with the SSL object.
11031084

11041085
Key logging example
11051086
-------------------
11061087

11071088
::
11081089

11091090
static void *
1110-
keylog_open (void *ctx, lsquic_conn_t *conn)
1091+
keylog_open_file (const SSL *ssl)
11111092
{
1093+
const lsquic_conn_t *conn;
11121094
const lsquic_cid_t *cid;
11131095
FILE *fh;
11141096
int sz;
@@ -1117,6 +1099,7 @@ Key logging example
11171099
char path[PATH_MAX];
11181100
static const char b2c[16] = "0123456789ABCDEF";
11191101

1102+
conn = lsquic_ssl_to_conn(ssl);
11201103
cid = lsquic_conn_id(conn);
11211104
for (i = 0; i < cid->len; ++i)
11221105
{
@@ -1130,28 +1113,30 @@ Key logging example
11301113
LOG("WARN: %s: file too long", __func__);
11311114
return NULL;
11321115
}
1133-
fh = fopen(path, "wb");
1116+
fh = fopen(path, "ab");
11341117
if (!fh)
1135-
LOG("WARN: could not open %s for writing: %s", path, strerror(errno));
1118+
LOG("WARN: could not open %s for appending: %s", path, strerror(errno));
11361119
return fh;
11371120
}
11381121

11391122
static void
1140-
keylog_log_line (void *handle, const char *line)
1123+
keylog_log_line (const SSL *ssl, const char *line)
11411124
{
1142-
fputs(line, handle);
1143-
fputs("\n", handle);
1144-
fflush(handle);
1125+
file = keylog_open_file(ssl);
1126+
if (file)
1127+
{
1128+
fputs(line, file);
1129+
fputs("\n", file);
1130+
fclose(file);
1131+
}
11451132
}
11461133

1147-
static void
1148-
keylog_close (void *handle)
1149-
{
1150-
fclose(handle);
1151-
}
1134+
/* ... */
1135+
1136+
SSL_CTX_set_keylog_callback(ssl, keylog_log_line);
11521137

1153-
The function to open the file is passed the connection object. It can be used to generate a filename
1154-
based on the connection ID.
1138+
The most involved part of this is opening the necessary file, creating it if necessary.
1139+
The connection can be used to generate a filename based on the connection ID.
11551140
We see that the line logger simply writes the passed C string to the filehandle and appends a newline.
11561141

11571142
Wireshark screenshot

0 commit comments

Comments
 (0)