diff --git a/c_src/quicer_config.c b/c_src/quicer_config.c index 215b8962..fde77459 100644 --- a/c_src/quicer_config.c +++ b/c_src/quicer_config.c @@ -2440,3 +2440,37 @@ get_str_from_map(ErlNifEnv *env, return enif_get_string(env, tmp_term, buff, tmp_len + 1, ERL_NIF_LATIN1); } + +BOOLEAN +build_trustedstore(const char *cacertfile, X509_STORE **trusted_store) +{ + X509_STORE *store = NULL; + X509_LOOKUP *lookup = NULL; + + if (cacertfile == NULL) + { + return FALSE; + } + + store = X509_STORE_new(); + if (store == NULL) + { + return FALSE; + } + + lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); + if (lookup == NULL) + { + X509_STORE_free(store); + return FALSE; + } + + if (!X509_LOOKUP_load_file(lookup, cacertfile, X509_FILETYPE_PEM)) + { + X509_STORE_free(store); + return FALSE; + } + + *trusted_store = store; + return TRUE; +} diff --git a/c_src/quicer_config.h b/c_src/quicer_config.h index 258f5661..d92f1c7c 100644 --- a/c_src/quicer_config.h +++ b/c_src/quicer_config.h @@ -20,6 +20,7 @@ limitations under the License. #include "quicer_internal.h" #include "quicer_nif.h" #include +#include #ifdef DEBUG #define dbg(fmt, ...) \ @@ -117,4 +118,6 @@ ERL_NIF_TERM set_connection_opt(ErlNifEnv *env, ERL_NIF_TERM optval, ERL_NIF_TERM elevel); +BOOLEAN build_trustedstore(const char *cacertfile, X509_STORE **trusted_store); + #endif // __QUICER_CONFIG_H_ diff --git a/c_src/quicer_connection.c b/c_src/quicer_connection.c index cb176277..0a8d12c9 100644 --- a/c_src/quicer_connection.c +++ b/c_src/quicer_connection.c @@ -127,13 +127,12 @@ peercert1(ErlNifEnv *env, __unused_parm__ int argc, const ERL_NIF_TERM argv[]) return ERROR_TUPLE_2(ATOM_ERROR_INTERNAL_ERROR); } - unsigned char *data - = enif_make_new_binary(env, len, &DerCert); + unsigned char *data = enif_make_new_binary(env, len, &DerCert); if (!data) - { + { return ERROR_TUPLE_2(ATOM_ERROR_NOT_ENOUGH_MEMORY); - } + } // note, using tmp is mandatory, see doc for i2d_X590 tmp = data; @@ -595,39 +594,14 @@ async_connect3(ErlNifEnv *env, } ERL_NIF_TERM ecacertfile; - X509_STORE *trusted = NULL; + if (enif_get_map_value(env, eoptions, ATOM_CACERTFILE, &ecacertfile)) { char cacertfile[PATH_MAX]; - if (enif_get_string( - env, ecacertfile, cacertfile, PATH_MAX, ERL_NIF_LATIN1) - > 0) - { - X509_LOOKUP *lookup = NULL; - trusted = X509_STORE_new(); - - if (trusted != NULL) - { - lookup = X509_STORE_add_lookup(trusted, X509_LOOKUP_file()); - if (lookup != NULL) - { - if (!X509_LOOKUP_load_file( - lookup, cacertfile, X509_FILETYPE_PEM)) - { - X509_STORE_free(trusted); - trusted = NULL; - } - } - else - { - X509_STORE_free(trusted); - trusted = NULL; - } - } - c_ctx->trusted = trusted; - } - - if (trusted == NULL) + if (!(enif_get_string( + env, ecacertfile, cacertfile, PATH_MAX, ERL_NIF_LATIN1) + > 0 + && build_trustedstore(cacertfile, &c_ctx->trusted))) { res = ERROR_TUPLE_2(ATOM_BADARG); goto Error; @@ -635,7 +609,7 @@ async_connect3(ErlNifEnv *env, } // convert eoptions to Configuration - bool HasCaCertfile = trusted != NULL; + bool HasCaCertfile = c_ctx->trusted != NULL; ERL_NIF_TERM estatus = ClientLoadConfiguration( env, &eoptions, &(c_ctx->config_resource->Configuration), HasCaCertfile); diff --git a/c_src/quicer_ctx.c b/c_src/quicer_ctx.c index 4ea8e8fb..03faa75c 100644 --- a/c_src/quicer_ctx.c +++ b/c_src/quicer_ctx.c @@ -33,6 +33,7 @@ init_l_ctx() l_ctx->acceptor_queue = AcceptorQueueNew(); l_ctx->lock = enif_mutex_create("quicer:l_ctx"); l_ctx->cacertfile = NULL; + l_ctx->trusted_store = NULL; l_ctx->is_closed = TRUE; l_ctx->allow_insecure = FALSE; return l_ctx; @@ -41,6 +42,10 @@ init_l_ctx() void deinit_l_ctx(QuicerListenerCTX *l_ctx) { + if (l_ctx->trusted_store) + { + X509_STORE_free(l_ctx->trusted_store); + } AcceptorQueueDestroy(l_ctx->acceptor_queue); if (l_ctx->config_resource) { diff --git a/c_src/quicer_ctx.h b/c_src/quicer_ctx.h index 31237bcc..dab3c5d5 100644 --- a/c_src/quicer_ctx.h +++ b/c_src/quicer_ctx.h @@ -46,6 +46,7 @@ typedef struct QuicerListenerCTX ErlNifEnv *env; ErlNifMutex *lock; char *cacertfile; + X509_STORE *trusted_store; // Listener handle closed flag // false means the handle is invalid BOOLEAN is_closed; diff --git a/c_src/quicer_listener.c b/c_src/quicer_listener.c index f32f0d59..94419684 100644 --- a/c_src/quicer_listener.c +++ b/c_src/quicer_listener.c @@ -50,34 +50,10 @@ ServerListenerCallback(__unused_parm__ HQUIC Listener, c_ctx->Connection = Event->NEW_CONNECTION.Connection; - /* reload trusted store very time to make sure we incorporate - * any changes to the file - */ - if (l_ctx->cacertfile) + if (l_ctx->trusted_store) { - X509_STORE *trusted = NULL; - X509_LOOKUP *lookup = NULL; - trusted = X509_STORE_new(); - - if (trusted != NULL) - { - lookup = X509_STORE_add_lookup(trusted, X509_LOOKUP_file()); - if (lookup != NULL) - { - if (!X509_LOOKUP_load_file( - lookup, l_ctx->cacertfile, X509_FILETYPE_PEM)) - { - X509_STORE_free(trusted); - trusted = NULL; - } - } - else - { - X509_STORE_free(trusted); - trusted = NULL; - } - } - c_ctx->trusted = trusted; + X509_STORE_up_ref(l_ctx->trusted_store); + c_ctx->trusted = l_ctx->trusted_store; } assert(l_ctx->config_resource); @@ -320,11 +296,14 @@ listen2(ErlNifEnv *env, __unused_parm__ int argc, const ERL_NIF_TERM argv[]) { l_ctx->cacertfile = (char *)CXPLAT_ALLOC_NONPAGED(len + 1, QUICER_CACERTFILE); - if (!enif_get_string(env, - ecacertfile, - l_ctx->cacertfile, - len + 1, - ERL_NIF_LATIN1)) + if (!(enif_get_string(env, + ecacertfile, + l_ctx->cacertfile, + len + 1, + ERL_NIF_LATIN1) + > 0 + && build_trustedstore(l_ctx->cacertfile, + &l_ctx->trusted_store))) { CXPLAT_FREE(l_ctx->cacertfile, QUICER_CACERTFILE); l_ctx->cacertfile = NULL; diff --git a/test/quicer_SUITE.erl b/test/quicer_SUITE.erl index a62c31f0..b1a5374b 100644 --- a/test/quicer_SUITE.erl +++ b/test/quicer_SUITE.erl @@ -382,9 +382,8 @@ tc_open_listener_inval_cacertfile_1(Config) -> tc_open_listener_inval_cacertfile_2(Config) -> Port = select_port(), - {ok, L} = quicer:listen(Port, [ {cacertfile, [1,2,3,4]} + {error, badarg} = quicer:listen(Port, [ {cacertfile, [1,2,3,4]} | default_listen_opts(Config)]), - ok = quicer:close_listener(L), ok. tc_open_listener_inval_cacertfile_3(Config) -> diff --git a/test/quicer_snb_SUITE.erl b/test/quicer_snb_SUITE.erl index 9c5ee898..e623e5ee 100644 --- a/test/quicer_snb_SUITE.erl +++ b/test/quicer_snb_SUITE.erl @@ -725,7 +725,7 @@ tc_stream_shutdown_abort(Config) -> , error_code := 1234 }, 1000, 1000), ct:pal("stop listener"), - ok = quicer:stop_listener(mqtt) + ok = quicer:terminate_listener(mqtt) end, fun(Result, Trace) -> ct:pal("Trace is ~p", [Trace]),