Skip to content

Commit

Permalink
Merge 3c1d892 into 3d3e48f
Browse files Browse the repository at this point in the history
  • Loading branch information
qzhuyan committed Dec 20, 2023
2 parents 3d3e48f + 3c1d892 commit 64a089b
Show file tree
Hide file tree
Showing 10 changed files with 113 additions and 34 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/cover.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ jobs:
git-branch: ${{ github.ref_name }}
git-commit: ${{ github.sha }}

- name: Run cover with feature switches
run: |
sudo apt-get install lcov
export QUICER_USE_TRUSTED_STORE=1
make cover
- name: Coveralls C
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
flag-name: run-c-lcov-feature
parallel: true
git-branch: ${{ github.ref_name }}
git-commit: ${{ github.sha }}

- name: Coveralls Erl
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ if (DEFINED ENV{QUICER_USE_SNK})
add_compile_options(-DQUICER_USE_SNK)
endif()

if (DEFINED ENV{QUICER_USE_TRUSTED_STORE})
message(STATUS "Enable shared trusted store")
add_compile_options(-DQUICER_USE_TRUSTED_STORE)
endif()

if (DEFINED ENV{QUICER_USE_SANITIZERS})
set(QUIC_ENABLE_SANITIZERS "ON")
add_compile_options(-O1 -fno-omit-frame-pointer -fsanitize=address,leak,undefined)
Expand Down
5 changes: 4 additions & 1 deletion c_src/quicer_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@ async_connect3(ErlNifEnv *env,
goto Error;
}

#ifdef QUICER_USE_TRUSTED_STORE
// parse opt cacertfile
char *cacertfile = NULL;
if (!parse_cacertfile_option(env, eoptions, &cacertfile))
Expand All @@ -762,6 +763,7 @@ async_connect3(ErlNifEnv *env,
free(cacertfile);
cacertfile = NULL;
}
#endif // QUICER_USE_TRUSTED_STORE

// convert eoptions to Configuration
ERL_NIF_TERM estatus = ClientLoadConfiguration(
Expand Down Expand Up @@ -1621,7 +1623,7 @@ handle_connection_event_peer_certificate_received(QuicerConnCTX *c_ctx,
X509_free(c_ctx->peer_cert);
}
c_ctx->peer_cert = X509_dup(cert);

#if defined(QUICER_USE_TRUSTED_STORE)
X509_STORE_CTX *x509_ctx
= (X509_STORE_CTX *)Event->PEER_CERTIFICATE_RECEIVED.Chain;

Expand All @@ -1638,6 +1640,7 @@ handle_connection_event_peer_certificate_received(QuicerConnCTX *c_ctx,
if (res <= 0)
return QUIC_STATUS_BAD_CERTIFICATE;
else
#endif // QUICER_USE_TRUSTED_STORE
return QUIC_STATUS_SUCCESS;

/* @TODO validate SNI */
Expand Down
15 changes: 12 additions & 3 deletions c_src/quicer_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ init_l_ctx()
l_ctx->acceptor_queue = AcceptorQueueNew();
l_ctx->lock = enif_mutex_create("quicer:l_ctx");
l_ctx->cacertfile = NULL;
#if defined(QUICER_USE_TRUSTED_STORE)
l_ctx->trusted_store = NULL;
#endif
l_ctx->is_closed = TRUE;
l_ctx->allow_insecure = FALSE;
l_ctx->r_ctx = NULL;
Expand All @@ -78,10 +80,12 @@ init_l_ctx()
void
deinit_l_ctx(QuicerListenerCTX *l_ctx)
{
#if defined(QUICER_USE_TRUSTED_STORE)
if (l_ctx->trusted_store)
{
X509_STORE_free(l_ctx->trusted_store);
}
#endif // QUICER_USE_TRUSTED_STORE
AcceptorQueueDestroy(l_ctx->acceptor_queue);
if (l_ctx->config_resource)
{
Expand Down Expand Up @@ -145,7 +149,9 @@ init_c_ctx()
c_ctx->acceptor_queue = AcceptorQueueNew();
c_ctx->Connection = NULL;
c_ctx->lock = enif_mutex_create("quicer:c_ctx");
#if defined(QUICER_USE_TRUSTED_STORE)
c_ctx->trusted = NULL;
#endif // QUICER_USE_TRUSTED_STORE
c_ctx->TlsSecrets = NULL;
c_ctx->ResumptionTicket = NULL;
c_ctx->event_mask = 0;
Expand All @@ -161,11 +167,13 @@ void
deinit_c_ctx(QuicerConnCTX *c_ctx)
{
enif_free_env(c_ctx->env);
#if defined(QUICER_USE_TRUSTED_STORE)
if (c_ctx->trusted != NULL)
{
X509_STORE_free(c_ctx->trusted);
c_ctx->trusted = NULL;
}
#endif // QUICER_USE_TRUSTED_STORE
if (c_ctx->config_resource)
{
enif_release_resource(c_ctx->config_resource);
Expand All @@ -182,14 +190,15 @@ deinit_c_ctx(QuicerConnCTX *c_ctx)
void
destroy_c_ctx(QuicerConnCTX *c_ctx)
{
// Since enif_release_resource is async call,
// we should demon the owner now!
// Since enif_release_resource is async call,
// we should demon the owner now!
#if defined(QUICER_USE_TRUSTED_STORE)
if (c_ctx->trusted != NULL)
{
X509_STORE_free(c_ctx->trusted);
c_ctx->trusted = NULL;
}

#endif // QUICER_USE_TRUSTED_STORE
QuicerRegistrationCTX *r_ctx;
if (c_ctx->r_ctx)
{
Expand Down
8 changes: 6 additions & 2 deletions c_src/quicer_ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ typedef struct QuicerListenerCTX
ErlNifEnv *env;
ErlNifMutex *lock;
char *cacertfile;
#if defined(QUICER_USE_TRUSTED_STORE)
X509_STORE *trusted_store;
#endif
// Listener handle closed flag
// false means the handle is invalid
BOOLEAN is_closed;
Expand All @@ -93,11 +95,13 @@ typedef struct QuicerConnCTX
ErlNifMonitor owner_mon;
ErlNifEnv *env;
ErlNifMutex *lock;
#if defined(QUICER_USE_TRUSTED_STORE)
X509_STORE *trusted;
// Connection handle closed flag
// false means the handle is invalid
#endif // QUICER_USE_TRUSTED_STORE
QUIC_TLS_SECRETS *TlsSecrets;
QUIC_BUFFER *ResumptionTicket;
// Connection handle closed flag
// false means the handle is invalid
BOOLEAN is_closed;
// track lifetime of Connection handle
CXPLAT_REF_COUNT ref_count;
Expand Down
22 changes: 19 additions & 3 deletions c_src/quicer_listener.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@ ServerListenerCallback(__unused_parm__ HQUIC Listener,
c_ctx->Connection = Event->NEW_CONNECTION.Connection;
CxPlatRefInitialize(&(c_ctx->ref_count));

#if defined(QUICER_USE_TRUSTED_STORE)
if (l_ctx->trusted_store)
{
X509_STORE_up_ref(l_ctx->trusted_store);
c_ctx->trusted = l_ctx->trusted_store;
}

#endif // QUICER_USE_TRUSTED_STORE
assert(l_ctx->config_resource);
// Keep resource for c_ctx
enif_keep_resource(l_ctx->config_resource);
Expand Down Expand Up @@ -324,16 +325,31 @@ listen2(ErlNifEnv *env, __unused_parm__ int argc, const ERL_NIF_TERM argv[])
// in cacertfile
// @see QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED
CredConfig.Flags |= QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED;
CredConfig.Flags |= QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION;

#if defined(QUICER_USE_TRUSTED_STORE)
CredConfig.Flags |= QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION;
l_ctx->cacertfile = cacertfile;
if (!build_trustedstore(l_ctx->cacertfile, &l_ctx->trusted_store))
{
ret = ERROR_TUPLE_2(ATOM_CERT_ERROR);
goto exit;
}
#else
CredConfig.Flags |= QUIC_CREDENTIAL_FLAG_SET_CA_CERTIFICATE_FILE;
CredConfig.CaCertificateFile = cacertfile;
#if defined(__APPLE__)
// This seems only needed for macOS
CredConfig.Flags
|= QUIC_CREDENTIAL_FLAG_USE_TLS_BUILTIN_CERTIFICATE_VALIDATION;
#endif // __APPLE__
#endif // QUICER_USE_TRUSTED_STORE
}
else
{ // since we don't use cacertfile, free it
{ // NO verify peer
#if !defined(QUICER_USE_TRUSTED_STORE)
CredConfig.Flags |= QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION;
#endif // QUICER_USE_TRUSTED_STORE
// since we don't use cacertfile, free it
free(cacertfile);
cacertfile = NULL;
}
Expand Down
6 changes: 5 additions & 1 deletion c_src/quicer_nif.c
Original file line number Diff line number Diff line change
Expand Up @@ -848,12 +848,13 @@ resource_listener_dealloc_callback(__unused_parm__ ErlNifEnv *env, void *obj)
TP_CB_3(skip, (uintptr_t)l_ctx->Listener, 0);
}

#if defined(QUICER_USE_TRUSTED_STORE)
if (l_ctx->cacertfile)
{
CXPLAT_FREE(l_ctx->cacertfile, QUICER_CACERTFILE);
l_ctx->cacertfile = NULL;
}

#endif // QUICER_USE_TRUSTED_STORE
deinit_l_ctx(l_ctx);
// @TODO notify acceptors that the listener is closed
TP_CB_3(end, (uintptr_t)l_ctx->Listener, 0);
Expand Down Expand Up @@ -1356,6 +1357,9 @@ atom_status(ErlNifEnv *env, QUIC_STATUS status)
case TLS1_AD_BAD_CERTIFICATE_HASH_VALUE:
eterm = ATOM_QUIC_STATUS_BAD_CERTIFICATE;
break;
case SSL_AD_DECRYPT_ERROR:
eterm = ATOM_QUIC_STATUS_HANDSHAKE_FAILURE;
break;
default:
eterm = enif_make_tuple2(
env, ATOM_UNKNOWN_TLS_STATUS_CODE, ETERM_UINT_64(tlserror));
Expand Down
21 changes: 17 additions & 4 deletions c_src/quicer_tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,17 @@ parse_verify_options(ErlNifEnv *env,
ERL_NIF_TERM tmp;
if (enif_get_map_value(env, options, ATOM_CACERTFILE, &tmp))
{
#if defined(QUICER_USE_TRUSTED_STORE)
// cacertfile is set, use it for self validation.
CredConfig->Flags
|= QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION;
#else
// cacertfile is set, use it for OpenSSL validation.
CredConfig->Flags
|= QUIC_CREDENTIAL_FLAG_SET_CA_CERTIFICATE_FILE;
CredConfig->CaCertificateFile = str_from_map(
env, ATOM_CACERTFILE, &options, NULL, PATH_MAX + 1);
#endif // QUICER_USE_TRUSTED_STORE
CredConfig->Flags
|= QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED;
}
Expand All @@ -137,6 +145,7 @@ parse_verify_options(ErlNifEnv *env,

/*
** Parse optional cacertfile option
** @NOTE we alloc buffer for cacertfile, caller should free it
*/
BOOLEAN
parse_cacertfile_option(ErlNifEnv *env,
Expand All @@ -163,6 +172,7 @@ parse_cacertfile_option(ErlNifEnv *env,
return TRUE;
}

#if defined(QUICER_USE_TRUSTED_STORE)
BOOLEAN
build_trustedstore(const char *cacertfile, X509_STORE **trusted_store)
{
Expand Down Expand Up @@ -196,11 +206,8 @@ build_trustedstore(const char *cacertfile, X509_STORE **trusted_store)
*trusted_store = store;
return TRUE;
}
#endif // QUICER_USE_TRUSTED_STORE

/*
* Free certfile/certfileprotected of QUIC_CREDENTIAL_CONFIG
*
*/
void
free_certificate(QUIC_CREDENTIAL_CONFIG *cc)
{
Expand All @@ -225,6 +232,12 @@ free_certificate(QUIC_CREDENTIAL_CONFIG *cc)
QUICER_CERTIFICATE_FILE_PROTECTED);
cc->CertificateFileProtected = NULL;
}

if (cc->CaCertificateFile)
{
free((char *)cc->CaCertificateFile);
cc->CaCertificateFile = NULL;
}
}

/*
Expand Down
44 changes: 28 additions & 16 deletions test/quicer_connection_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -456,22 +456,30 @@ run_tc_conn_custom_ca_other(Config) ->
end
),
receive
listener_ready ->
{error, transport_down, #{
error := _ErrorCode,
status := bad_certificate
}} =
quicer:connect(
"localhost",
Port,
default_conn_opts_verify(Config, "other-ca"),
5000
),
SPid ! done,
ensure_server_exit_normal(Ref)
listener_ready -> ok
after 1000 ->
ct:fail("timeout")
end.
end,

Res = quicer:connect(
"localhost",
Port,
default_conn_opts_verify(Config, "other-ca"),
5000
),

?assertMatch(
{error, transport_down, #{
error := _ErrorCode,
status := Status
}} when
Status == handshake_failure;
Status == bad_certificate;
Status == cert_untrusted_root,
Res
),
SPid ! done,
ensure_server_exit_normal(Ref).

tc_conn_client_cert(Config) ->
{Pid, Ref} = spawn_monitor(fun() -> run_tc_conn_client_cert(Config) end),
Expand Down Expand Up @@ -646,8 +654,12 @@ run_tc_conn_client_bad_cert(Config) ->
end,
receive
{quic, transport_shutdown, _Ref, #{
error := _ErrorCode, status := bad_certificate
}} ->
error := _ErrorCode, status := Status
}} when
Status == handshake_failure;
Status == bad_certificate;
Status == cert_untrusted_root
->
_ = flush([])
after 2000 ->
Other = flush([]),
Expand Down
6 changes: 2 additions & 4 deletions test/quicer_snb_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2336,10 +2336,8 @@ tc_listener_no_acceptor(Config) ->
#{
?snk_kind := debug,
context := "callback",
function := "resource_conn_dealloc_callback",
%% assert Connection is unset
resource_id := 0,
tag := "start"
function := "handle_connection_event_shutdown_complete",
tag := "shutdown_complete"
},
Trace
)
Expand Down

0 comments on commit 64a089b

Please sign in to comment.