X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Ftrace.c;h=a8316c12b1b3ac42fa4d6355ae4537be21395162;hp=8020a58e68746733085fdb68df0cebfbcb91b2c7;hb=e39e295e205ab8461d3ac814129bbb08c2d1266d;hpb=b9ce85f631cf376cd781fd3dfdc80e927d88ee77 diff --git a/crypto/trace.c b/crypto/trace.c old mode 100644 new mode 100755 index 8020a58e68..a8316c12b1 --- a/crypto/trace.c +++ b/crypto/trace.c @@ -1,5 +1,5 @@ /* - * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -10,12 +10,13 @@ #include #include +#include "internal/thread_once.h" #include #include #include #include "internal/bio.h" #include "internal/nelem.h" -#include "internal/cryptlib_int.h" +#include "crypto/cryptlib.h" #include "e_os.h" /* strcasecmp for Windows */ @@ -65,7 +66,7 @@ static int trace_write(BIO *channel, const char *buf, size_t num, size_t *written) { struct trace_data_st *ctx = BIO_get_data(channel); - size_t cnt = ctx->callback(buf, num, ctx->category, OSSL_TRACE_CTRL_DURING, + size_t cnt = ctx->callback(buf, num, ctx->category, OSSL_TRACE_CTRL_WRITE, ctx->data); *written = cnt; @@ -119,16 +120,22 @@ struct trace_category_st { #define TRACE_CATEGORY_(name) { #name, OSSL_TRACE_CATEGORY_##name } static const struct trace_category_st trace_categories[] = { - TRACE_CATEGORY_(ANY), + TRACE_CATEGORY_(ALL), + TRACE_CATEGORY_(TRACE), TRACE_CATEGORY_(INIT), TRACE_CATEGORY_(TLS), TRACE_CATEGORY_(TLS_CIPHER), - TRACE_CATEGORY_(ENGINE_CONF), + TRACE_CATEGORY_(CONF), +#ifndef OPENSSL_NO_ENGINE TRACE_CATEGORY_(ENGINE_TABLE), TRACE_CATEGORY_(ENGINE_REF_COUNT), +#endif TRACE_CATEGORY_(PKCS5V2), TRACE_CATEGORY_(PKCS12_KEYGEN), + TRACE_CATEGORY_(PKCS12_DECRYPT), TRACE_CATEGORY_(X509V3_POLICY), + TRACE_CATEGORY_(BN_CTX), + TRACE_CATEGORY_(STORE), }; const char *OSSL_trace_get_category_name(int num) @@ -155,7 +162,7 @@ int OSSL_trace_get_category_num(const char *name) /* We use one trace channel for each trace category */ static struct { - enum { t_channel, t_callback } type; + enum { SIMPLE_CHANNEL, CALLBACK_CHANNEL } type; BIO *bio; char *prefix; char *suffix; @@ -165,87 +172,233 @@ static struct { #endif -int ossl_trace_init(void) -{ #ifndef OPENSSL_NO_TRACE - trace_lock = CRYPTO_THREAD_lock_new(); - if (trace_lock != NULL) - return 1; -#endif - return 0; +enum { + CHANNEL, + PREFIX, + SUFFIX +}; + +static int trace_attach_cb(int category, int type, const void *data) +{ + switch (type) { + case CHANNEL: + OSSL_TRACE2(TRACE, "Attach channel %p to category '%s'\n", + data, trace_categories[category].name); + break; + case PREFIX: + OSSL_TRACE2(TRACE, "Attach prefix \"%s\" to category '%s'\n", + (const char *)data, trace_categories[category].name); + break; + case SUFFIX: + OSSL_TRACE2(TRACE, "Attach suffix \"%s\" to category '%s'\n", + (const char *)data, trace_categories[category].name); + break; + default: /* No clue */ + break; + } + return 1; } -void ossl_trace_cleanup(void) +static int trace_detach_cb(int category, int type, const void *data) { -#ifndef OPENSSL_NO_TRACE - int category; + switch (type) { + case CHANNEL: + OSSL_TRACE2(TRACE, "Detach channel %p from category '%s'\n", + data, trace_categories[category].name); + break; + case PREFIX: + OSSL_TRACE2(TRACE, "Detach prefix \"%s\" from category '%s'\n", + (const char *)data, trace_categories[category].name); + break; + case SUFFIX: + OSSL_TRACE2(TRACE, "Detach suffix \"%s\" from category '%s'\n", + (const char *)data, trace_categories[category].name); + break; + default: /* No clue */ + break; + } + return 1; +} - for (category = 0; category < OSSL_TRACE_CATEGORY_NUM; category++) - OSSL_trace_set_channel(category, NULL); - CRYPTO_THREAD_lock_free(trace_lock); -#endif +static int do_ossl_trace_init(void); +static CRYPTO_ONCE trace_inited = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_trace_init) +{ + return do_ossl_trace_init(); } -int OSSL_trace_set_channel(int category, BIO *channel) +static int set_trace_data(int category, int type, BIO **channel, + const char **prefix, const char **suffix, + int (*attach_cb)(int, int, const void *), + int (*detach_cb)(int, int, const void *)) { -#ifndef OPENSSL_NO_TRACE - BIO *prev_channel; + BIO *curr_channel = NULL; + char *curr_prefix = NULL; + char *curr_suffix = NULL; - if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM) - goto err; + /* Ensure do_ossl_trace_init() is called once */ + if (!RUN_ONCE(&trace_inited, ossl_trace_init)) + return 0; - prev_channel = trace_channels[category].bio; + curr_channel = trace_channels[category].bio; + curr_prefix = trace_channels[category].prefix; + curr_suffix = trace_channels[category].suffix; - if (prev_channel != NULL) { - BIO_free(prev_channel); + /* Make sure to run the detach callback first on all data */ + if (prefix != NULL && curr_prefix != NULL) { + detach_cb(category, PREFIX, curr_prefix); + } + + if (suffix != NULL && curr_suffix != NULL) { + detach_cb(category, SUFFIX, curr_suffix); + } + + if (channel != NULL && curr_channel != NULL) { + detach_cb(category, CHANNEL, curr_channel); + } + + /* After detach callbacks are done, clear data where appropriate */ + if (prefix != NULL && curr_prefix != NULL) { + OPENSSL_free(curr_prefix); + trace_channels[category].prefix = NULL; + } + + if (suffix != NULL && curr_suffix != NULL) { + OPENSSL_free(curr_suffix); + trace_channels[category].suffix = NULL; + } + + if (channel != NULL && curr_channel != NULL) { + BIO_free(curr_channel); + trace_channels[category].type = 0; trace_channels[category].bio = NULL; } - if (channel == NULL) - return 1; /* Done */ + /* Before running callbacks are done, set new data where appropriate */ + if (channel != NULL && *channel != NULL) { + trace_channels[category].type = type; + trace_channels[category].bio = *channel; + } - trace_channels[category].bio = channel; - trace_channels[category].type = t_channel; + if (prefix != NULL && *prefix != NULL) { + if ((curr_prefix = OPENSSL_strdup(*prefix)) == NULL) + return 0; + trace_channels[category].prefix = curr_prefix; + } + + if (suffix != NULL && *suffix != NULL) { + if ((curr_suffix = OPENSSL_strdup(*suffix)) == NULL) + return 0; + trace_channels[category].suffix = curr_suffix; + } + + /* Finally, run the attach callback on the new data */ + if (channel != NULL && *channel != NULL) { + attach_cb(category, CHANNEL, *channel); + } + + if (prefix != NULL && *prefix != NULL) { + attach_cb(category, PREFIX, *prefix); + } + + if (suffix != NULL && *suffix != NULL) { + attach_cb(category, SUFFIX, *suffix); + } return 1; +} + +static int do_ossl_trace_init(void) +{ + trace_lock = CRYPTO_THREAD_lock_new(); + return trace_lock != NULL; +} - err: #endif - return 0; +void ossl_trace_cleanup(void) +{ +#ifndef OPENSSL_NO_TRACE + int category; + BIO *channel = NULL; + const char *prefix = NULL; + const char *suffix = NULL; + + for (category = 0; category < OSSL_TRACE_CATEGORY_NUM; category++) { + /* We force the TRACE category to be treated last */ + if (category == OSSL_TRACE_CATEGORY_TRACE) + continue; + set_trace_data(category, 0, &channel, &prefix, &suffix, + trace_attach_cb, trace_detach_cb); + } + set_trace_data(OSSL_TRACE_CATEGORY_TRACE, 0, &channel, + &prefix, &suffix, + trace_attach_cb, trace_detach_cb); + CRYPTO_THREAD_lock_free(trace_lock); +#endif } -int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data) +int OSSL_trace_set_channel(int category, BIO *channel) { #ifndef OPENSSL_NO_TRACE - BIO *channel = trace_channels[category].bio; - struct trace_data_st *trace_data = NULL; + if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM) + return set_trace_data(category, SIMPLE_CHANNEL, &channel, NULL, NULL, + trace_attach_cb, trace_detach_cb); +#endif + return 0; +} - if (channel != NULL) { - BIO_free(channel); - trace_channels[category].bio = NULL; +#ifndef OPENSSL_NO_TRACE +static int trace_attach_w_callback_cb(int category, int type, const void *data) +{ + switch (type) { + case CHANNEL: + OSSL_TRACE2(TRACE, + "Attach channel %p to category '%s' (with callback)\n", + data, trace_categories[category].name); + break; + case PREFIX: + OSSL_TRACE2(TRACE, "Attach prefix \"%s\" to category '%s'\n", + (const char *)data, trace_categories[category].name); + break; + case SUFFIX: + OSSL_TRACE2(TRACE, "Attach suffix \"%s\" to category '%s'\n", + (const char *)data, trace_categories[category].name); + break; + default: /* No clue */ + break; } + return 1; +} +#endif - if (callback == NULL) - return 1; /* done */ +int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data) +{ +#ifndef OPENSSL_NO_TRACE + BIO *channel = NULL; + struct trace_data_st *trace_data = NULL; - channel = BIO_new(&trace_method); - if (channel == NULL) - goto err; + if (category < 0 || category >= OSSL_TRACE_CATEGORY_NUM) + return 0; - trace_data = OPENSSL_zalloc(sizeof(struct trace_data_st)); - if (trace_data == NULL) - goto err; + if (callback != NULL) { + if ((channel = BIO_new(&trace_method)) == NULL + || (trace_data = + OPENSSL_zalloc(sizeof(struct trace_data_st))) == NULL) + goto err; - trace_data->callback = callback; - trace_data->category = category; - trace_data->data = data; + trace_data->callback = callback; + trace_data->category = category; + trace_data->data = data; - BIO_set_data(channel, trace_data); + BIO_set_data(channel, trace_data); + } - trace_channels[category].bio = channel; - trace_channels[category].type = t_callback; + if (!set_trace_data(category, CALLBACK_CHANNEL, &channel, NULL, NULL, + trace_attach_w_callback_cb, trace_detach_cb)) + goto err; return 1; @@ -260,54 +413,20 @@ int OSSL_trace_set_callback(int category, OSSL_trace_cb callback, void *data) int OSSL_trace_set_prefix(int category, const char *prefix) { #ifndef OPENSSL_NO_TRACE - char *curr_prefix = trace_channels[category].prefix; - - if (curr_prefix != NULL) { - OPENSSL_free(curr_prefix); - trace_channels[category].prefix = NULL; - } - - if (prefix == NULL) - return 1; /* Done */ - - curr_prefix = OPENSSL_strdup(prefix); - if (curr_prefix == NULL) - goto err; - - trace_channels[category].prefix = curr_prefix; - - return 1; - - err: + if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM) + return set_trace_data(category, 0, NULL, &prefix, NULL, + trace_attach_cb, trace_detach_cb); #endif - return 0; } int OSSL_trace_set_suffix(int category, const char *suffix) { #ifndef OPENSSL_NO_TRACE - char *curr_suffix = trace_channels[category].suffix; - - if (curr_suffix != NULL) { - OPENSSL_free(curr_suffix); - trace_channels[category].suffix = NULL; - } - - if (suffix == NULL) - return 1; /* done */ - - curr_suffix = OPENSSL_strdup(suffix); - if (curr_suffix == NULL) - goto err; - - trace_channels[category].suffix = curr_suffix; - - return 1; - - err: + if (category >= 0 && category < OSSL_TRACE_CATEGORY_NUM) + return set_trace_data(category, 0, NULL, NULL, &suffix, + trace_attach_cb, trace_detach_cb); #endif - return 0; } @@ -318,7 +437,7 @@ static int ossl_trace_get_category(int category) return -1; if (trace_channels[category].bio != NULL) return category; - return OSSL_TRACE_CATEGORY_ANY; + return OSSL_TRACE_CATEGORY_ALL; } #endif @@ -327,7 +446,8 @@ int OSSL_trace_enabled(int category) int ret = 0; #ifndef OPENSSL_NO_TRACE category = ossl_trace_get_category(category); - ret = trace_channels[category].bio != NULL; + if (category >= 0) + ret = trace_channels[category].bio != NULL; #endif return ret; } @@ -339,6 +459,9 @@ BIO *OSSL_trace_begin(int category) char *prefix = NULL; category = ossl_trace_get_category(category); + if (category < 0) + return NULL; + channel = trace_channels[category].bio; prefix = trace_channels[category].prefix; @@ -346,13 +469,13 @@ BIO *OSSL_trace_begin(int category) CRYPTO_THREAD_write_lock(trace_lock); current_channel = channel; switch (trace_channels[category].type) { - case t_channel: + case SIMPLE_CHANNEL: if (prefix != NULL) { (void)BIO_puts(channel, prefix); (void)BIO_puts(channel, "\n"); } break; - case t_callback: + case CALLBACK_CHANNEL: (void)BIO_ctrl(channel, OSSL_TRACE_CTRL_BEGIN, prefix == NULL ? 0 : strlen(prefix), prefix); break; @@ -373,13 +496,13 @@ void OSSL_trace_end(int category, BIO * channel) && ossl_assert(channel == current_channel)) { (void)BIO_flush(channel); switch (trace_channels[category].type) { - case t_channel: + case SIMPLE_CHANNEL: if (suffix != NULL) { (void)BIO_puts(channel, suffix); (void)BIO_puts(channel, "\n"); } break; - case t_callback: + case CALLBACK_CHANNEL: (void)BIO_ctrl(channel, OSSL_TRACE_CTRL_END, suffix == NULL ? 0 : strlen(suffix), suffix); break;