Skip to content

Commit

Permalink
Merge pull request #48 from qzhuyan/dev/William/dump-sslkeylogfile
Browse files Browse the repository at this point in the history
feat(trace): support ssl key log file dump
  • Loading branch information
qzhuyan authored Jul 19, 2021
2 parents 9c05d43 + e7b8f89 commit 8b1f81f
Show file tree
Hide file tree
Showing 21 changed files with 372 additions and 49 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ else()
set(QUIC_ENABLE_LOGGING "OFF")
endif()


if (DEFINED ENV{QUICER_USE_LTTNG})
add_compile_options(-DQUICER_USE_LTTNG)
endif()
Expand All @@ -35,6 +34,8 @@ set(QUIC_BUILD_TEST "OFF")
set(QUIC_BUILD_TOOLS "OFF")
set(QUIC_BUILD_PERF "OFF")

set(QUIC_TLS_SECRETS_SUPPORT "ON")

# src files
set(SOURCES
c_src/quicer_nif.c
Expand Down
9 changes: 9 additions & 0 deletions c_src/quicer_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ limitations under the License.
-------------------------------------------------------------------*/

#include "quicer_config.h"
#include "quicer_internal.h"
#include "quicer_queue.h"
#include <msquichelper.h>

extern BOOLEAN isRegistered;

Expand Down Expand Up @@ -157,6 +159,13 @@ ClientLoadConfiguration(ErlNifEnv *env,
return ERROR_TUPLE_2(ATOM_BADARG);
}

// Uncomment to make client prefer to use Draft-29
// This is for Draft-29 version in HOST byte order.
/* const uint32_t DesiredVersion = 0xff00001dU; */
/* Settings.DesiredVersionsList = &DesiredVersion; */
/* Settings.DesiredVersionsListLength = 1; */
/* Settings.IsSet.DesiredVersionsList = TRUE; */

//
// Configures a default client configuration, optionally disabling
// server certificate validation.
Expand Down
17 changes: 2 additions & 15 deletions c_src/quicer_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,9 @@ limitations under the License.
#ifndef __QUICER_CONFIG_H_
#define __QUICER_CONFIG_H_

#include "quicer_internal.h"
#include "quicer_nif.h"

// @todo check if we can make use of it.
//#include <msquichelper.h>

typedef struct QUIC_CREDENTIAL_CONFIG_HELPER
{
QUIC_CREDENTIAL_CONFIG CredConfig;
union
{
QUIC_CERTIFICATE_HASH CertHash;
QUIC_CERTIFICATE_HASH_STORE CertHashStore;
QUIC_CERTIFICATE_FILE CertFile;
};
} QUIC_CREDENTIAL_CONFIG_HELPER;
#include <msquichelper.h>

bool ReloadCertConfig(HQUIC Configuration,
QUIC_CREDENTIAL_CONFIG_HELPER *Config);
Expand Down Expand Up @@ -73,5 +61,4 @@ ERL_NIF_TERM setopt3(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
bool create_settings(ErlNifEnv *env,
const ERL_NIF_TERM *emap,
QUIC_SETTINGS *Settings);

#endif // __QUICER_CONFIG_H_
161 changes: 158 additions & 3 deletions c_src/quicer_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,109 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-------------------------------------------------------------------*/

#include "quicer_connection.h"

#include <assert.h>
#include <unistd.h>

extern inline void
EncodeHexBuffer(uint8_t *Buffer, uint8_t BufferLen, char *HexString);

extern inline const char* QuicStatusToString(QUIC_STATUS Status);

void
dump_sslkeylogfile(_In_z_ const char *FileName,
_In_ CXPLAT_TLS_SECRETS TlsSecrets)
{
FILE *File = NULL;
#ifdef _WIN32
if (fopen_s(&File, FileName, "ab"))
{
printf("Failed to open sslkeylogfile %s\n", FileName);
return;
}
#else
File = fopen(FileName, "ab");
#endif

if (File == NULL)
{
printf("Failed to open sslkeylogfile %s\n", FileName);
return;
}
if (fseek(File, 0, SEEK_END) == 0 && ftell(File) == 0)
{
fprintf(File, "# TLS 1.3 secrets log file\n");
}
char ClientRandomBuffer
[(2 * sizeof(((CXPLAT_TLS_SECRETS *)NULL)->ClientRandom)) + 1]
= { 0 };
char TempHexBuffer[(2 * CXPLAT_TLS_SECRETS_MAX_SECRET_LEN) + 1] = { 0 };
if (TlsSecrets.IsSet.ClientRandom)
{
EncodeHexBuffer(TlsSecrets.ClientRandom,
(uint8_t)sizeof(TlsSecrets.ClientRandom),
ClientRandomBuffer);
}

if (TlsSecrets.IsSet.ClientEarlyTrafficSecret)
{
EncodeHexBuffer(TlsSecrets.ClientEarlyTrafficSecret,
TlsSecrets.SecretLength,
TempHexBuffer);
fprintf(File,
"CLIENT_EARLY_TRAFFIC_SECRET %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
}

if (TlsSecrets.IsSet.ClientHandshakeTrafficSecret)
{
EncodeHexBuffer(TlsSecrets.ClientHandshakeTrafficSecret,
TlsSecrets.SecretLength,
TempHexBuffer);
fprintf(File,
"CLIENT_HANDSHAKE_TRAFFIC_SECRET %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
}

if (TlsSecrets.IsSet.ServerHandshakeTrafficSecret)
{
EncodeHexBuffer(TlsSecrets.ServerHandshakeTrafficSecret,
TlsSecrets.SecretLength,
TempHexBuffer);
fprintf(File,
"SERVER_HANDSHAKE_TRAFFIC_SECRET %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
}

if (TlsSecrets.IsSet.ClientTrafficSecret0)
{
EncodeHexBuffer(TlsSecrets.ClientTrafficSecret0,
TlsSecrets.SecretLength,
TempHexBuffer);
fprintf(File,
"CLIENT_TRAFFIC_SECRET_0 %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
}

if (TlsSecrets.IsSet.ServerTrafficSecret0)
{
EncodeHexBuffer(TlsSecrets.ServerTrafficSecret0,
TlsSecrets.SecretLength,
TempHexBuffer);
fprintf(File,
"SERVER_TRAFFIC_SECRET_0 %s %s\n",
ClientRandomBuffer,
TempHexBuffer);
}

fflush(File);
fclose(File);
}

//
// The clients's callback for connection events from MsQuic.
//
Expand Down Expand Up @@ -140,6 +237,12 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
MsQuic->ConnectionClose(Connection);
c_ctx->is_closed = TRUE;
}

if (NULL != c_ctx->TlsSecrets && NULL != c_ctx->ssl_keylogfile)
{
dump_sslkeylogfile(c_ctx->ssl_keylogfile, *(c_ctx->TlsSecrets));
}

destroy_c_ctx(c_ctx);
break;
case QUIC_CONNECTION_EVENT_RESUMPTION_TICKET_RECEIVED:
Expand Down Expand Up @@ -175,7 +278,7 @@ ServerConnectionCallback(HQUIC Connection,
// The handshake has completed for the connection.
//

assert(c_ctx->Connection == NULL);
assert(c_ctx->Connection == Connection);
c_ctx->Connection = Connection;
acc = c_ctx->owner;
acc_pid = &(acc->Pid);
Expand Down Expand Up @@ -214,6 +317,7 @@ ServerConnectionCallback(HQUIC Connection,

MsQuic->ConnectionSendResumptionTicket(
Connection, QUIC_SEND_RESUMPTION_FLAG_NONE, 0, NULL);

break;
case QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT:
//
Expand Down Expand Up @@ -380,6 +484,39 @@ async_connect3(ErlNifEnv *env,
return ERROR_TUPLE_2(ATOM_CONN_OPEN_ERROR);
}

ERL_NIF_TERM essl_keylogfile;
if (enif_get_map_value(
env, eoptions, ATOM_SSL_KEYLOGFILE_NAME, &essl_keylogfile))
{
char *keylogfile = CXPLAT_ALLOC_NONPAGED(PATH_MAX, QUICER_TRACE);
if (enif_get_string(
env, essl_keylogfile, keylogfile, PATH_MAX, ERL_NIF_LATIN1))
{
CXPLAT_TLS_SECRETS *TlsSecrets = CXPLAT_ALLOC_NONPAGED(
sizeof(CXPLAT_TLS_SECRETS), QUICER_TLS_SECRETS);

CxPlatZeroMemory(TlsSecrets, sizeof(CXPLAT_TLS_SECRETS));
Status = MsQuic->SetParam(c_ctx->Connection,
QUIC_PARAM_LEVEL_CONNECTION,
QUIC_PARAM_CONN_TLS_SECRETS,
sizeof(CXPLAT_TLS_SECRETS),
TlsSecrets);
if (QUIC_FAILED(Status))
{
fprintf(stderr,
"failed to enable secret logging: %s",
QuicStatusToString(Status));
}
c_ctx->TlsSecrets = TlsSecrets;
c_ctx->ssl_keylogfile = keylogfile;
}

else
{
fprintf(stderr, "failed to read string ssl_keylogfile");
}
}

if (QUIC_FAILED(Status = MsQuic->ConnectionStart(c_ctx->Connection,
c_ctx->Configuration,
QUIC_ADDRESS_FAMILY_UNSPEC,
Expand Down Expand Up @@ -533,6 +670,24 @@ addr2eterm(ErlNifEnv *env, QUIC_ADDR *addr)
enif_make_int(env, ntohs(addr->Ipv4.sin_port)));
}
}

ERL_NIF_TERM
get_conn_rid1(ErlNifEnv *env, int args, const ERL_NIF_TERM argv[])
{
QuicerConnCTX *c_ctx;
if (1 != args)
{
return ERROR_TUPLE_2(ATOM_BADARG);
}

if (!enif_get_resource(env, argv[0], ctx_connection_t, (void **)&c_ctx))
{
return ERROR_TUPLE_2(ATOM_BADARG);
}

return SUCCESS(enif_make_ulong(env, (unsigned long)c_ctx->Connection));
}

///_* Emacs
///====================================================================
/// Local Variables:
Expand Down
6 changes: 6 additions & 0 deletions c_src/quicer_connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ limitations under the License.

#ifndef __QUICER_CONNECTION_H_
#define __QUICER_CONNECTION_H_
#include "quicer_internal.h"
#include "quicer_nif.h"
#include <msquichelper.h>

ERL_NIF_TERM
async_connect3(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
Expand All @@ -31,4 +33,8 @@ QUIC_STATUS ServerConnectionCallback(HQUIC Connection,
QUIC_CONNECTION_EVENT *Event);

ERL_NIF_TERM addr2eterm(ErlNifEnv *env, QUIC_ADDR *addr);

ERL_NIF_TERM
get_conn_rid1(ErlNifEnv *env, int args, const ERL_NIF_TERM argv[]);

#endif // __QUICER_CONNECTION_H_
2 changes: 2 additions & 0 deletions c_src/quicer_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ init_c_ctx()
= CXPLAT_ALLOC_NONPAGED(sizeof(ErlNifMonitor), QUICER_OWNER_MON);
c_ctx->lock = enif_mutex_create("quicer:c_ctx");
c_ctx->is_closed = FALSE;
c_ctx->TlsSecrets = NULL;
c_ctx->ssl_keylogfile = NULL;
return c_ctx;
}

Expand Down
3 changes: 3 additions & 0 deletions c_src/quicer_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ limitations under the License.

#include "quicer_nif.h"
#include "quicer_queue.h"
#include <msquichelper.h>

#define _CTX_CALLBACK_WRITE_
#define _CTX_CALLBACK_READ_
Expand Down Expand Up @@ -50,6 +51,8 @@ typedef struct
ErlNifEnv *env;
ErlNifMutex *lock;
BOOLEAN is_closed;
CXPLAT_TLS_SECRETS *TlsSecrets;
char *ssl_keylogfile;
void *reserved1;
void *reserved2;
void *reserved3;
Expand Down
6 changes: 6 additions & 0 deletions c_src/quicer_eterms.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ extern ERL_NIF_TERM ATOM_SNK_KIND;
extern ERL_NIF_TERM ATOM_SNK_META;
extern ERL_NIF_TERM ATOM_FUNCTION;
extern ERL_NIF_TERM ATOM_SNABBKAFFE_NEMESIS;

/*----------------------------------------------------------*/
/* Additional Connection Opt */
/*----------------------------------------------------------*/
extern ERL_NIF_TERM ATOM_SSL_KEYLOGFILE_NAME;

/*----------------------------------------------------------*/
/* ATOMS ends here */
/*----------------------------------------------------------*/
Expand Down
34 changes: 34 additions & 0 deletions c_src/quicer_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*--------------------------------------------------------------------
Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-------------------------------------------------------------------*/

#ifndef QUICER_INTERNAL_H_
#define QUICER_INTERNAL_H_

#if defined(__linux__)
#include <linux/limits.h>
#elif defined(__APPLE__)
#include <sys/syslimits.h>
#else
#include <limits.h>
#endif

#if defined(__linux__)
#define CX_PLATFORM_LINUX 1
#elif defined(__APPLE__)
#define CX_PLATFORM_DARWIN 1
#endif

#endif // QUICER_INTERNAL_H_
6 changes: 4 additions & 2 deletions c_src/quicer_listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ limitations under the License.
-------------------------------------------------------------------*/

#include "quicer_listener.h"
#include "quicer_config.h"

QUIC_STATUS
ServerListenerCallback(__unused_parm__ HQUIC Listener,
Expand All @@ -23,7 +24,6 @@ ServerListenerCallback(__unused_parm__ HQUIC Listener,
{
QUIC_STATUS Status = QUIC_STATUS_SUCCESS;
QuicerListenerCTX *l_ctx = (QuicerListenerCTX *)Context;
ErlNifEnv *env = l_ctx->env;
QuicerConnCTX *c_ctx = NULL;
switch (Event->Type)
{
Expand All @@ -37,9 +37,11 @@ ServerListenerCallback(__unused_parm__ HQUIC Listener,

if (!c_ctx)
{
return ERROR_TUPLE_2(ATOM_CTX_INIT_FAILED);
return QUIC_STATUS_OUT_OF_MEMORY;
}

c_ctx->Connection = Event->NEW_CONNECTION.Connection;

c_ctx->l_ctx = l_ctx;

ACCEPTOR *conn_owner = AcceptorDequeue(l_ctx->acceptor_queue);
Expand Down
Loading

0 comments on commit 8b1f81f

Please sign in to comment.